> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.staple.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.staple.ai/_mcp/server.

# Accounts Payable

## Business flow

Accounts Payable (AP) covers the flow of *receiving* e-invoices from your suppliers and managing them inside your system. With Staple, your team does not need to integrate directly with each country's tax authority or with the Peppol network — Staple acts as the central hub between your business and every supported e-invoicing network.

The flow works as follows:

1. **Staple receives the invoice.** A supplier issues an e-invoice. The invoice is delivered to Staple through the relevant national e-invoicing platform (such as KSeF in Poland, MyInvois in Malaysia, or SDI in Italy) or through the Peppol network. Staple receives and stores the invoice on your behalf.
2. **Staple notifies your system.** A webhook is sent to your registered endpoint as soon as the invoice is uploaded into Staple. The notification carries the identifiers your system needs to retrieve the invoice in the next step.
3. **Your system retrieves the invoice in STAR format.** Using the `documentId` from the webhook, your system calls the Export endpoint and receives the invoice as a STAR JSON payload — the same unified schema Staple uses for every supported country. The response also includes validation proof from the tax authority or Peppol.
4. **Your team acts on the invoice.** Your AP team reviews the invoice in your accounting or ERP system and decides what to do with it. They can accept it, reject it, or mark it as paid once payment has been made.
5. **You notify Staple of the decision.** For each decision, your system calls the corresponding Staple endpoint — Accept, Reject, or Paid.
6. **Staple synchronises the status.** Where the tax authority or Peppol network requires the status to be reported back (for example, an invoice acknowledgement or a paid notification), Staple handles that synchronisation automatically.
7. **The original document is available for download.** Whenever you need the original e-invoice file — for audit, dispute resolution, or archival — you can retrieve it through the Download original document endpoint.

![Accounts Payable flow — from import to archive, every state stays in sync](https://files.buildwithfern.com/staple.docs.buildwithfern.com/4a0832a79c7c6034e0542ebce254f9ade81e7dae393295f8a7285491517b9e24/docs/assets/einvoice/new_AP_flow_1.png)

## Document state machine

Every received e-invoice progresses through a small set of states inside Staple. The state machine below shows the valid transitions:

```text
Received --accept--> Accepted --paid--> Paid
    |
    --reject--> Rejected
```

* A document starts in the `Received` state as soon as Staple receives it from the tax authority or the Peppol network.
* Calling **Accept** moves the document from `Received` to `Accepted`.
* Calling **Reject** moves the document from `Received` to `Rejected`.
* Calling **Paid** moves the document from `Accepted` to `Paid`. Paid is only valid from the `Accepted` state.
* Once a document is in `Accepted`, it cannot be rejected.
* `Rejected` and `Paid` are terminal states — no further transitions are possible.

Each AP endpoint requires you to identify the document being acted on. You can use either of two identifiers, depending on how the document entered Staple:

* **`documentId`** — used for paper invoices that customers send to Staple via email or other channels. Staple scans the document, extracts the data, and assigns a `documentId`. Paper invoices do not have a tax authority reference.
* **`taxAuthorityReference`** — used for e-invoices that Staple pulls from the tax authority or the Peppol network. This is the unique identifier assigned by the tax authority. The exact form depends on the country:

| Country       | Identifier                     |
| ------------- | ------------------------------ |
| 🇲🇾 Malaysia | MyInvois UUID                  |
| 🇮🇹 Italy    | SDI IdentificativoSdI          |
| 🇵🇱 Poland   | KSeF number                    |
| 🇮🇳 India    | IRN (Invoice Reference Number) |
| 🌐 Peppol     | Peppol Message ID              |

Exactly one of `documentId` or `taxAuthorityReference` must be supplied on every Accept, Reject, and Paid request. The same rule applies to the Download original document endpoint, which accepts an array of `docIds`.

## Webhook notifications

When a new e-invoice arrives at Staple, your system is notified through a webhook so you can retrieve the invoice and act on it without polling.

To start receiving webhook notifications, subscribe to the `Document uploaded` event in the Staple UI:

1. In Staple, open **User Profile → Webhooks**.
2. Configure a webhook URL on your server and subscribe to the **Document uploaded** event.

You will need the **Manage webhooks** permission in your Staple workspace to configure webhooks. If you do not see the Webhooks page in your User Profile, contact your workspace administrator.

### Webhook payload

When a new document — including an inbound e-invoice — is uploaded to Staple, the following payload is delivered to your registered webhook URL:

```json
{
  "event": "document.uploaded",
  "payload": {
    "documentInfo": {
      "documentId": 123,
      "documentName": "invoice.pdf",
      "taxAuthorityReference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "uploadedAt": "2026-06-11T12:34:56.789Z"
    },
    "userInfo": {
      "email": "user@example.com",
      "firstName": "Jane",
      "lastName": "Doe"
    }
  }
}
```

For paper invoices, `taxAuthorityReference` will be `null`.

Use the `documentId` (or `taxAuthorityReference` if you prefer) from this payload to retrieve the e-invoice in STAR format through the Export endpoint described in the next section.

## Export documents

`POST https://api.staple.io/v1/documents/export`

Export one or more received documents in your chosen format. For e-invoices, exporting in **STAR** format returns the invoice as a country-agnostic JSON payload that your accounting or ERP system can process consistently regardless of which country the invoice came from.

The response also includes a validation block confirming whether the invoice has been validated by the tax authority or the Peppol network — and when — so your system can rely on the data without performing its own validation.

Bearer token, e.g. `Authorization: Bearer <token>`.

One or more Staple document IDs to export.

Export format. Allowed values: `STAR`, `CSV`, `JSON`, `TXT`, `XML`. Default is `CSV`. For e-invoices, use `STAR`.

```http title="Single document — Request"
POST https://api.staple.io/v1/documents/export
Authorization: Bearer <token>
Content-Type: application/json

{
  "docIds": [9021],
  "formatType": "STAR"
}
```

```http title="Batched — Request"
POST https://api.staple.io/v1/documents/export
Authorization: Bearer <token>
Content-Type: application/json

{
  "docIds": [9021, 9022, 9023],
  "formatType": "STAR"
}
```

The response contains the STAR payload for each requested document, along with a validation block.

```json title="Response"
{
  "exportDocumentByDocIds": {
    "data": [
      {
        "docId": 9021,
        "star": {
          "Country": "DE",
          "DocNumber": "INV-0001",
          "IssueDate": "2026-05-09",
          "Currency": "EUR",
          "Supplier": {
            "Name": "Mustermann GmbH",
            "TaxID": { "Country": "DE", "Code": "111111125" }
          },
          "Customer": {
            "Name": "Buyer GmbH",
            "TaxID": { "Country": "DE", "Code": "222222229" }
          },
          "Lines": [
            {
              "Quantity": "1.00",
              "Item": { "Name": "Consulting service", "Price": "1000.00" },
              "Taxes": [{ "Cat": "VAT", "Rate": "standard" }]
            }
          ]
        },
        "validation": {
          "status": "validated",
          "validatedAt": "2026-05-09T09:21:00Z",
          "source": "tax_authority",
          "reference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
        }
      }
    ],
    "message": "Documents exported successfully."
  }
}
```

### Validation block

| Field         | Type              | Description                                                                                                                                                                                                         |
| ------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`      | string            | Validation outcome. One of `validated`, `failed`, or `not_required`.                                                                                                                                                |
| `validatedAt` | string (datetime) | ISO 8601 timestamp of when the validation was completed by the source system.                                                                                                                                       |
| `source`      | string            | The system that performed the validation. One of `tax_authority` or `peppol`.                                                                                                                                       |
| `reference`   | string            | The validation reference issued by the source system — for example, the tax authority's unique identifier for the validated invoice (MyInvois UUID, SDI IdentificativoSdI, KSeF number, IRN, or Peppol Message ID). |

The full STAR schema reference is documented in [Schema Objects](/e-invoice/reference/schema-objects).

## Accept

`POST https://api.staple.io/v1/documents/move/accepted`

Notify Staple that your AP team has accepted an invoice. This moves the document from `Received` to `Accepted`. For e-invoices, Staple synchronises the acceptance status to the relevant tax authority or the Peppol network. For paper invoices, only the local state is updated.

Bearer token, e.g. `Authorization: Bearer <token>`.

Document identifier for paper invoices. Exactly one of `documentId` or `taxAuthorityReference` is required.

Opaque tax authority identifier for e-invoices. Exactly one of `documentId` or `taxAuthorityReference` is required.

```http title="Request"
POST https://api.staple.io/v1/documents/move/accepted
Authorization: Bearer <token>
Content-Type: application/json

{
  "taxAuthorityReference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
```

```json title="Response"
{
  "acceptDocument": {
    "message": "Document has been accepted.",
    "syncStatus": "pending"
  }
}
```

## Reject

`POST https://api.staple.io/v1/documents/move/rejected`

Notify Staple that your AP team has rejected an invoice. This moves the document from `Received` to `Rejected`. For e-invoices, Staple synchronises the rejection to the tax authority or the Peppol network. For paper invoices, only the local state is updated.

Once a document has been accepted, it can no longer be rejected through this endpoint.

Bearer token, e.g. `Authorization: Bearer <token>`.

Document identifier for paper invoices. Exactly one of `documentId` or `taxAuthorityReference` is required.

Opaque tax authority identifier for e-invoices. Exactly one of `documentId` or `taxAuthorityReference` is required.

One or more rejection reasons.

```http title="Request — paper invoice"
POST https://api.staple.io/v1/documents/move/rejected
Authorization: Bearer <token>
Content-Type: application/json

{
  "documentId": "9021",
  "reasons": ["duplicate", "incorrect_amount"]
}
```

```http title="Request — e-invoice"
POST https://api.staple.io/v1/documents/move/rejected
Authorization: Bearer <token>
Content-Type: application/json

{
  "taxAuthorityReference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "reasons": ["buyer_rejected"]
}
```

```json title="Response — e-invoice"
{
  "rejectDocument": {
    "message": "Document has been rejected.",
    "syncStatus": "pending"
  }
}
```

```json title="Response — paper invoice"
{
  "rejectDocument": {
    "message": "Document has been rejected.",
    "syncStatus": "not_applicable"
  }
}
```

## Paid

`POST https://api.staple.io/v1/documents/move/paid`

Notify Staple that an accepted invoice has been paid. This moves the document from `Accepted` to `Paid`. Payment metadata is required for e-invoices, where the payment status must be reported externally. For paper invoices, payment metadata is optional.

Partial payments are not supported in the current release — Paid is treated as a single terminal event for the full invoice amount.

Bearer token, e.g. `Authorization: Bearer <token>`.

Document identifier for paper invoices. Exactly one of `documentId` or `taxAuthorityReference` is required.

Opaque tax authority identifier for e-invoices. Exactly one of `documentId` or `taxAuthorityReference` is required.

Payment metadata. Required for e-invoices, optional for paper invoices.

Payment timestamp in ISO 8601 format, e.g. `2026-05-21T10:30:00Z`.

Amount paid, 2 decimal places, e.g. `"1500.00"`.

ISO 4217 currency code, e.g. `EUR`.

External payment transaction reference, e.g. `TXN-12345`.

Payment method identifier, e.g. `bank_transfer`.

```http title="Request"
POST https://api.staple.io/v1/documents/move/paid
Authorization: Bearer <token>
Content-Type: application/json

{
  "taxAuthorityReference": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "payment": {
    "paidAt": "2026-05-21T10:30:00Z",
    "amount": "1500.00",
    "currency": "EUR",
    "paymentReference": "TXN-12345",
    "paymentMethod": "bank_transfer"
  }
}
```

```json title="Response"
{
  "paidDocument": {
    "message": "Document has been marked as paid.",
    "syncStatus": "pending"
  }
}
```

## `syncStatus` values

Every response from the Accept, Reject, and Paid endpoints includes a `syncStatus` field. This indicates whether and how the state change has been synchronised externally with the tax authority or the Peppol network.

| Value            | Meaning                                                                                                            |
| ---------------- | ------------------------------------------------------------------------------------------------------------------ |
| `not_applicable` | Paper invoices, or e-invoices in countries where external sync is not required for this action.                    |
| `pending`        | The local state has been updated. Async synchronisation to the tax authority or Peppol network has been initiated. |
| `synced`         | External synchronisation has completed successfully. Returned on idempotent replay after sync has finished.        |
| `failed`         | External synchronisation has failed. The local state has still been updated; reconciliation may be required.       |

## Search documents

`POST https://api.staple.io/v2/search/documents`

Search for documents using filters such as document ID, tax authority reference, status, date range, and queue. This endpoint is useful when your buyer-side team needs to look up a specific e-invoice or list all e-invoices in a given state.

Bearer token, e.g. `Authorization: Bearer <token>`.

Filter criteria. See the fields below.

Pagination control. See the fields below.

### `filter` object fields

| Field                    | Type       | Required | Description                                                                                                                           |
| ------------------------ | ---------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `documentIds`            | integer\[] | Optional | Array of Staple document IDs to look up directly.                                                                                     |
| `taxAuthorityReferences` | string\[]  | Optional | Array of tax authority references to look up directly (MyInvois UUID, SDI IdentificativoSdI, KSeF number, IRN, or Peppol Message ID). |
| `queue`                  | integer\[] | Optional | Array of queue IDs to search within.                                                                                                  |
| `tab`                    | string\[]  | Optional | Document state(s) to include. Allowed values: `RECEIVED`, `COMPLETED`, `REJECTED`, `EXPORTED`, `EXPORT_FAILED`.                       |
| `uploadedAt`             | object     | Optional | Filter by upload date. Object with `from` and `to` fields, each formatted as `dd/mm/yyyy`.                                            |
| `completedAt`            | object     | Optional | Filter by completion date. Object with `from` and `to` fields, each formatted as `dd/mm/yyyy`.                                        |
| `rejectedAt`             | object     | Optional | Filter by rejection date. Object with `from` and `to` fields, each formatted as `dd/mm/yyyy`.                                         |
| `exportedAt`             | object     | Optional | Filter by export date. Object with `from` and `to` fields, each formatted as `dd/mm/yyyy`.                                            |

### `pagination` object fields

| Field  | Type    | Required | Description                             |
| ------ | ------- | -------- | --------------------------------------- |
| `skip` | integer | Required | Current page number (zero-indexed).     |
| `take` | integer | Required | Number of documents to return per page. |

```http title="Request — search by date range"
POST https://api.staple.io/v2/search/documents
Authorization: Bearer <token>
Content-Type: application/json

{
  "filter": {
    "queue": [4173],
    "tab": ["RECEIVED"],
    "uploadedAt": {
      "from": "01/05/2026",
      "to": "31/05/2026"
    }
  },
  "pagination": {
    "skip": 0,
    "take": 50
  }
}
```

```http title="Request — look up specific documents"
POST https://api.staple.io/v2/search/documents
Authorization: Bearer <token>
Content-Type: application/json

{
  "filter": {
    "documentIds": [9021, 9022],
    "taxAuthorityReferences": ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"]
  },
  "pagination": {
    "skip": 0,
    "take": 50
  }
}
```

The underlying endpoint supports additional filters used elsewhere in the Staple platform (such as filename and content search) — those filters are omitted here as they are not commonly used in e-invoice workflows.

## Download original document

`POST https://api.staple.io/v1/documents/download`

Download the original files of one or more received documents. The response is a ZIP archive containing the original files (for example, the raw XML for an e-invoice or the source PDF for a scanned paper invoice).

This endpoint is useful for audit, dispute resolution, or archival — when you need the exact file Staple received from the supplier or the tax authority.

Bearer token, e.g. `Authorization: Bearer <token>`.

`application/json`.

Array of document IDs to download.

```http title="Request"
POST https://api.staple.io/v1/documents/download
Authorization: Bearer <token>
Content-Type: application/json

{
  "docIds": [9021, 9022, 9023]
}
```

The response is a stream of ZIP-archive bytes containing the original file for each requested document. Save the response stream to disk and unzip to access the individual files.