> ## Documentation Index
> Fetch the complete documentation index at: https://developers.pleo.io/llms.txt
> Use this file to discover all available pages before exploring further.

# How to Transfer Attachments

export const WhatComesNext = ({children, href}) => <div className="mt-4">
    <a href={href} className="
        inline-flex items-center justify-center
        rounded-full
        bg-black text-white dark:bg-[#1f262b]
        px-5 py-2.5 text-sm font-medium
        no-underline border-0
        hover:bg-[#ffe6ea] dark:hover:bg-[#2b1f23]
        hover:text-black
        transition-colors
      ">
      {children} →
    </a>
  </div>;

export const TransferAttachmentsDiagram = () => {
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "28px"}}}%%
flowchart LR
    S1["1. Check for Attachments"] -->|has attachments| S2["2. Download Attachments"] --> S3["3. Handle Multiple Attachments"] --> S4["4. Upload & Associate"]
    S4 -->|success| S6["6. Ensure Idempotency"]
    S4 -->|fails| S5["5. Handle Failures"] --> S6
    S1 -->|no attachments| SKIP["Skip"]

click S1 "#1-check-for-attachments"
click S2 "#2-download-attachments"
click S3 "#3-handle-multiple-attachments"
click S4 "#4-upload-and-associate-attachments"
click S5 "#5-handle-failures"
click S6 "#6-ensure-idempotency"

style S1 white-space:normal
style S2 white-space:normal
style S3 white-space:normal
style S4 white-space:normal
style S5 white-space:normal
style S6 white-space:normal
style SKIP white-space:normal
`;
  return <Mermaid chart={diagram} />;
};

export const WorkflowDiagramTopNavASERP = ({highlight}) => {
  const highlightStyle = highlight ? `style ${highlight} stroke:#f63b92,stroke-width:5px` : "";
  const diagram = `
%%{init: {"themeVariables": {"fontSize": "30px"}}}%%
flowchart LR
    
    WF1["Pleo APIs"] 

    subgraph ERP["AS/ERP"]
    direction LR
        START1[" "]  
        A["1.Determine Bookkeeping Method"] --> B["2.Apply Accounts Mapping"]
        B --> C["3.Apply Data Mapping"]
        C --> D["4.Transfer Attachments"]
        D --> E["5.Assign Accounting Period"]
        E --> F["6.Apply Posting Behaviour"]
    end

    WF2["Pleo APIs"] 

    WF1 --> A
    F --> WF2

    %% Click actions
    click WF1 "/docs/current/how-tos/accounting-integrations/how-to-fetch-export-item-data-for-as-erp-processing"
    click A "/docs/current/how-tos/accounting-integrations/how-to-determine-the-bookkeeping-method-for-as-erp-processing"
    click B "/docs/current/how-tos/accounting-integrations/how-to-determine-accounts-mapping-for-as-erp-processing"
    click C "/docs/current/how-tos/accounting-integrations/how-to-apply-data-mapping-for-as-erp-processing"
    click D "/docs/current/how-tos/accounting-integrations/how-to-transfer-attachments-for-as-erp-processing"
    click E "/docs/current/how-tos/accounting-integrations/how-to-assign-accounting-periods-for-as-erp-processing"
    click F "/docs/current/how-tos/accounting-integrations/how-to-apply-posting-behaviour-for-as-erp-processing"
    click WF2 "/docs/current/how-tos/accounting-integrations/how-to-update-export-items-for-as-erp-processing"

    %% Styling for wrapping
    style A white-space:normal
    style B white-space:normal
    style C white-space:normal
    style D white-space:normal
    style E white-space:normal
    style F white-space:normal

    %% Make subgraph transparent with black border
    style START1 fill:transparent,stroke:transparent,color:transparent
    style ERP fill:none,stroke:#000000

${highlightStyle}
`;
  return <Mermaid chart={diagram} />;
};

export const NoteCallout = ({title, children, icon = "💡"}) => <div style={{
  backgroundColor: 'var(--recommended-bg)',
  borderLeft: '4px solid #3beaf6',
  borderRadius: '10px',
  padding: '18px 22px',
  marginBottom: '20px',
  boxShadow: '1px 1px 3px rgba(0,0,0,0.06)'
}}>
    <div style={{
  display: 'flex',
  alignItems: 'flex-start',
  gap: '14px'
}}>
      <span style={{
  fontSize: '22px',
  lineHeight: '1',
  flexShrink: 0
}}>
        {icon}
      </span>
      <div>
        {title && <div style={{
  fontSize: '16px',
  fontWeight: 600,
  color: 'var(--recommended-title)',
  marginBottom: '6px'
}}>
            {title}
          </div>}
        <div style={{
  fontSize: '14px',
  lineHeight: 1.65
}}>
          {children}
        </div>
      </div>
    </div>
  </div>;

export const RememberCallout = ({title, children, icon = "🪢"}) => <div style={{
  backgroundColor: 'var(--recommended-bg)',
  borderLeft: '4px solid #f63b92',
  borderRadius: '10px',
  padding: '18px 22px',
  marginBottom: '20px',
  boxShadow: '1px 1px 3px rgba(0,0,0,0.06)'
}}>
    <div style={{
  display: 'flex',
  alignItems: 'flex-start',
  gap: '14px'
}}>
      <span style={{
  fontSize: '22px',
  lineHeight: '1',
  flexShrink: 0
}}>
        {icon}
      </span>
      <div>
        {title && <div style={{
  fontSize: '16px',
  fontWeight: 600,
  color: 'var(--recommended-title)',
  marginBottom: '6px'
}}>
            {title}
          </div>}
        <div style={{
  fontSize: '14px',
  lineHeight: 1.65
}}>
          {children}
        </div>
      </div>
    </div>
  </div>;

<WorkflowDiagramTopNavASERP highlight="D" />

<div style={{ border: "2px solid #f63b92", borderRadius: "8px", padding: "16px", backgroundColor: "transparent" }}>
  <TransferAttachmentsDiagram />
</div>

Attachment handling ensures that **supporting documents (receipts, invoices)** are transferred and linked to accounting entries in your Accounting System.

## Prerequisites

Before you begin:

* You've [fetched the export item payload data](/docs/current/how-tos/accounting-integrations/how-to-fetch-export-item-data-for-as-erp-processing)
* You've completed:
  * [Accounts Mapping](/docs/current/how-tos/accounting-integrations/how-to-determine-accounts-mapping-for-as-erp-processing)
  * [Data Mapping](/docs/current/how-tos/accounting-integrations/how-to-apply-data-mapping-for-as-erp-processing)
* You're familiar with the [Integration Design for attachment handling](/docs/current/integration-design/exports/integration-design-exports-attachment-handling)

## Relevant Export Item Fields

<Accordion title="Example Export Item Payload (Journal Entry)">
  ```json theme={null}
    {
        "companyId": "12abc3d4-e567-890e-1234-abc56e78fabc",
        "accountingEntryId": "59540ed2-0d68-4e36-9e31-58223975d9e9",
        "type": "card_purchase",
        "subType": null,
        "date": "2025-12-10T15:46:34Z",
        "amount": {
          "inSupplierCurrency": {
            "currency": "GBP",
            "value": 6366
          },
          "inWalletCurrency": {
            "currency": "GBP",
            "value": 6366
          }
        },
        "note": "Printer ink",
        "files": [
          {
            "url": "<string>",
            "type": "image/jpeg",
            "size": 13010
          }
        ],
        "supplier": {
          "code": "1340472473",
          "name": "Target",
          "categoryCode": "1000",
          "country": "GB",
          "account": null,
          "taxIdentifier": null
        },
        "user": {
          "id": "6b71f6bd-e83d-4d49-88ee-2b8cda2d57cf",
          "name": "Luke Richardson",
          "code": null
        },
        "team": {
          "id": "747aaf60-56c6-4b46-ad92-f8a0cb59cf8b",
          "code": "5678",
          "name": "Engineering"
        },
        "accountingEntryLines": [
          {
            "accountingEntryLineId": "0c76ea71-aaaa-4ece-bb68-e1166ccaea04",
            "lineAmount": {
              "inSupplierCurrency": {
                "currency": "GBP",
                "value": 6366
              },
              "inWalletCurrency": {
                "currency": "GBP",
                "value": 6366
              }
            },
            "netAmount": {
              "inSupplierCurrency": {
                "currency": "GBP",
                "value": 6366
              },
              "inWalletCurrency": {
                "currency": "GBP",
                "value": 6366
              }
            },
            "account": {
              "id": "7966c3ba-e4de-4574-8604-6cfa48d62cc8",
              "code": "6990000",
              "name": "Printing & Stationary",
              "identifier": "6990000"
            },
            "tax": {
              "id": "997d8526-5872-484d-ba07-c7a07e08e555",
              "code": "0001",
              "type": "inclusive",
              "amount": {
                "inSupplierCurrency": {
                  "currency": "GBP",
                  "value": 0
                },
                "inWalletCurrency": {
                  "currency": "GBP",
                  "value": 0
                }
              },
              "rate": 0.00
            },
            "tags": []
          }
        ],
        "additionalInformation": {
          "reconciliationId": "2500001",
          "reconciledEntries": null,
          "attendees": [],
          "invoiceInformation": null
        },
        "bookkeeping": {
          "method": "journal"
        },
        "vendor": {
          "id": "22e1f2c9-1360-4291-ab41-6b23dcea8888",
          "name": "TestVendor",
          "code": "acc1234",
          "externalId": "ext12345",
          "registrationNumber": "reg001234",
          "taxRegistrationNumber": "taxreg1234",
          "country": "UK",
          "defaultCurrency": "GBP"
        },
        "contraAccount": {
          "id": "993d664c-9b7c-4efc-a677-510e69200857",
          "code": "0876000",
          "name": "0876000_ChartAccounts",
          "identifier": "0876000"
        },
        "_links": {
          "web": {
            "exportItem": "https://app.staging.pleo.io/export/export-item/0c76ea71-aaaa-4ece-bb68-e1166ccaea04"
          }
        },
        "servicePeriod": null
      },
     # [other Export Items omitted for brevity]
     # [Pagination omitted for brevity]
  ```
</Accordion>

Attachments are provided in:

```json theme={null}
"files": [
  {
    "url": "https://file.url",
    "type": "application/pdf",
    "size": 13010
  }
]
```

Each Export Item may contain:

* zero attachments
* one attachment
* multiple attachments

## Steps

### 1. Check for Attachments

```pseudo theme={null}
if files is empty:
    continue processing
```

<RememberCallout title="Remember">
  Not all Export Items contain attachments.

  <br />

  <br />

  This is not an error at the platform level. However, your integration must explicitly define whether attachments are:

  * optional (continue processing), or
  * required (fail the Export Item if missing).
</RememberCallout>

### 2. Download Attachments

Iterate through all files:

```pseudo theme={null}
attachments = []

for file in files:
    attachment = download(file.url)
    attachments.append(attachment)
```

Guidelines:

* download immediately (URLs may expire)
* preserve file format and filename where possible

### 3. Handle Multiple Attachments

If multiple attachments exist:

```pseudo theme={null}
if accountingSystem.supportsMultipleAttachments:
    upload all attachments
else:
    mergedFile = merge(attachments)
    upload mergedFile
```

Recommended merge strategies:

* PDF merge (preferred)
* ZIP archive (fallback)

### 4. Upload and Associate Attachments

Attach files to the created record:

* journal entry
* vendor invoice (AP)
* expense transaction

```pseudo theme={null}
for attachment in attachments:
    uploadToAccountingSystem(entryId, attachment)
```

Ensure:

* attachments are linked to the correct entry
* traceability to the original Export Item is preserved

### 5. Handle Failures

Attachment failures must be handled explicitly.

```pseudo theme={null}
try:
    download/upload
except transientError:
    retry
except permanentError:
    log failure
```

Recommended behaviour:

* retry transient failures (network/timeouts)
* log all failures
* decide whether to:
  * fail the Export Item, or
  * continue without attachment (system-dependent)

<RememberCallout title="Remember">
  Do not silently discard attachments — always log or surface failures.
</RememberCallout>

### 6. Ensure Idempotency

Avoid duplicate uploads when retrying exports.

```pseudo theme={null}
if attachmentAlreadyUploaded(file):
    skip upload
```

Strategies:

* Generate a deterministic attachment key, for example:
  * `accountingEntryId + file index`, or
  * a hash of file metadata (e.g. URL, size, type)
* Store processed attachment keys to prevent duplicate uploads during retries
* Optionally check existing attachments in the Accounting System (if supported)

<RememberCallout title="Remember">
  Attachment URLs may change across requests. Do not rely on URL alone as a unique identifier.
</RememberCallout>

## Results

After completing this step:

* All available attachments have been:
  * downloaded
  * uploaded
  * linked to accounting entries
* Attachments remain traceable to their originating Export Item

***

## What Comes Next?

<WhatComesNext href="/docs/current/how-tos/accounting-integrations/how-to-assign-accounting-periods-for-as-erp-processing">
  How to Assign Accounting Periods
</WhatComesNext>

***

<div className="text-xs uppercase" style={{ fontVariant: 'small-caps' }}>
  this how-to is part of:
</div>

<div className="mt-4 flex flex-wrap gap-2">
  <a
    href="/docs/current/guides/accounting-system-processing-workflow-guide"
    className="inline-flex items-center rounded-full border border-gray-300 dark:border-gray-600
px-3 py-1 text-xs font-medium
bg-white dark:bg-[#1f262b] text-black dark:text-white
hover:bg-gray-100 dark:hover:bg-[#2b2f33]
transition-colors"
  >
    AS/ERP Processing Workflow Guide
  </a>

  <a
    href="/docs/current/guides/export-integration-workflow-guide"
    className="inline-flex items-center rounded-full border border-gray-300 dark:border-gray-600
px-3 py-1 text-xs font-medium
bg-white dark:bg-[#1f262b] text-black dark:text-white
hover:bg-gray-100 dark:hover:bg-[#2b2f33]
transition-colors"
  >
    Export Integration Workflow Guide (Step 5)
  </a>
</div>

***

## Related Reading

* [Export Lifecycle](/docs/current/platform/exports/lifecycle)
* [Connection and Authorisation Overview](/docs/current/integration-design/auth/integration-design-auth-overview)

***
