Skip to main content
The Chart of Accounts API supports creating up to 1000 Accounts in a single request using the batch endpoint. This is more efficient than individual creates when your sync produces a large number of new accounts, and helps keep API call volume within rate limit targets. This how-to covers the batch create step only. For update, unarchive, and archive operations, use the individual PUT endpoint as described in How to Create, Update, and Archive Accounts.

When to Use This

The batch endpoint is useful when:
  • Running an initial sync where many accounts need to be created from scratch.
  • A large number of new accounts have been added to the AS since the last sync cycle.
For small numbers of new accounts, the single-create endpoint works fine.

Prerequisites

Before you begin:

Steps

1. Build the Batch Request

API Endpoint: POST /v1/chart-of-accounts/batch Collect all accounts that need to be created and include them as items in the request body. Each item requires externalId, name, and archived. The code and taxCodeExternalId fields are optional. A single request can include between 1 and 1000 accounts. If you have more than 1000 accounts to create, split them across multiple requests. Example Pseudo:
newAccounts = [account for account in activeASAccounts if not matchedInPleo]

for batch in chunks(newAccounts, size=1000):
    items = []
    for account in batch:
        items.append({
            externalId: account.externalId,
            code:       account.code,
            name:       account.name,
            archived:   false
        })
    POST /v1/chart-of-accounts/batch with { companyId, items }

Example Request

curl -X POST "https://external.staging.pleo.io/v1/chart-of-accounts/batch" \
  -H "Authorization: Bearer <access_token>" \
  -H "Content-Type: application/json" \
  -d '{
        "companyId": "12abc3d4-e567-890e-1234-abc56e78fabc",
        "items": [
          {
            "externalId": "ext-3000",
            "code": "3000",
            "name": "Software",
            "archived": false
          },
          {
            "externalId": "ext-6000",
            "code": "6000",
            "name": "Consulting",
            "archived": false
          },
          {
            "externalId": "ext-7000",
            "code": "7000",
            "name": "Equipment",
            "archived": false
          }
        ]
      }'

2. Handle the Response

The API returns a 201 even when some items fail. Always check both the created and failed arrays in the response.

Example Response

{
  "data": {
    "created": [
      {
        "id": "f1a2b3c4-d5e6-7f89-abcd-ef1234567890",
        "companyId": "12abc3d4-e567-890e-1234-abc56e78fabc",
        "externalId": "ext-3000",
        "code": "3000",
        "name": "Software",
        "archived": false
      },
      {
        "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567891",
        "companyId": "12abc3d4-e567-890e-1234-abc56e78fabc",
        "externalId": "ext-6000",
        "code": "6000",
        "name": "Consulting",
        "archived": false
      },
      {
        "id": "b2c3d4e5-f6a7-8901-bcde-f12345678912",
        "companyId": "12abc3d4-e567-890e-1234-abc56e78fabc",
        "externalId": "ext-7000",
        "code": "7000",
        "name": "Equipment",
        "archived": false
      }
    ],
    "failed": []
  }
}

Handling Failures

Items that fail validation are returned in the failed array with a reasons field explaining what went wrong. Successfully validated items are still created: the batch does not roll back.
{
  "data": {
    "created": [...],
    "failed": [
      {
        "reasons": ["EXTERNAL_ID_ALREADY_EXISTS"],
        "request": {
          "externalId": "ext-3000",
          "code": "3000",
          "name": "Software",
          "archived": false
        }
      }
    ]
  }
}