# Exports tools

> MCP tools for Exports: exports_create, exports_get, exports_gl_mapping_get, exports_gl_mapping_set, exports_list.

- `exports_create`: Request an accounting export
- `exports_get`: Get an accounting export
- `exports_gl_mapping_get`: Get the general-ledger mapping
- `exports_gl_mapping_set`: Set the general-ledger mapping
- `exports_list`: List accounting exports

## `exports_create`

**Request an accounting export.** Operation [`exports.create`](https://ownrecord.io/docs/reference/exports-create.md) · Legal entity level · permission `ledger:write` · risk tier `write` · since M8

Requests the legal entity's accounting export for a period: calendar days `from` to `to` (included) in the
entity's time zone, every brand of the entity, in the mode of the request. It is built in the background
(usually within a minute): poll `exports.get` until `status` is `ready`. Three CSV files (RFC 4180, UTF-8):

- **journal**: one row per ledger entry of every posted transaction effective in the period, with the brand,
  the Ownrecord account, the entity's general-ledger account from its mapping (`exports.gl_mapping.set`), debit
  or credit in the entry's currency (exact decimals) and what the transaction links to (payment, invoice and
  credit note numbers, refund, dispute). Each transaction balances per currency; all periods together sum to the
  trial balance;
- **invoice register**: every invoice issued in the period (numbers, dates, customer, totals, status);
- **credit-note register**: every credit note issued in the period, with its original invoice.

Download the files from the console (entity → Exports) for 30 days.

Annotations: `readOnlyHint: false` · `destructiveHint: false` · `idempotentHint: false` · `openWorldHint: false`

### Arguments

| Argument          | Type         | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `from`            | string       | yes      | The first day, in the legal entity's time zone (YYYY-MM-DD).                                                                                                                                             |
| `to`              | string       | yes      | The last day, included; at most 366 days after `from`, and not after today.                                                                                                                              |
| `entity_id`       | ID (`ent_…`) | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity.                                                        |
| `idempotency_key` | string       | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean      | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): `from` or `to` isn't a calendar date.
- [`export_period_invalid`](https://ownrecord.io/docs/reference/errors.md#export_period_invalid): `from` is after `to`, the period is longer than 366 days, or it ends after today in the entity's time zone.
- [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused): The idempotency key was used before for another request.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`, or a brand key: exports belong to the entity).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't export this entity's books or change its mapping (`ledger:write`: finance, owners and admins).
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't use live exports.

### Example

**The third quarter**

Arguments:

```json
{
  "from": "2026-07-01",
  "to": "2026-09-30",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "exp_01m4tx5nj8emwbyf7y9vcf4aaa",
  "object": "data_export",
  "livemode": false,
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
  "kind": "accounting",
  "status": "queued",
  "from": "2026-07-01",
  "to": "2026-09-30",
  "timeZone": "Europe/Zagreb",
  "requestedBy": {
    "type": "user",
    "id": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
  },
  "glMappingVersion": null,
  "files": [],
  "summary": null,
  "failure": null,
  "readyAt": null,
  "expiresAt": null,
  "createdAt": "2026-10-02T08:00:00.000Z",
  "updatedAt": "2026-10-02T08:00:00.000Z",
  "version": 1
}
```

## `exports_get`

**Get an accounting export.** Operation [`exports.get`](https://ownrecord.io/docs/reference/exports-get.md) · Legal entity level · permission `ledger:read` · risk tier `read` · since M8

Returns an accounting export: its status, period, the general-ledger mapping version used, its files (name,
size, SHA-256, rows) and a summary (the journal's totals per currency, which must balance, and the accounts the
mapping doesn't map; the registers' counts and totals). A failed export says why. The files download from the
console for 30 days after the export is ready; then it is `expired`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument    | Type         | Required | Description                                                                                                                                       |
| ----------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | ID (`exp_…`) | yes      | The export's ID (`exp_…`).                                                                                                                        |
| `entity_id` | ID (`ent_…`) | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): `id` isn't an export ID (`exp_…`).
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such export in this mode.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`, or a brand key: exports belong to the entity).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't read this entity's ledger (`ledger:read`; brand-scoped members never see it).
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't use live exports.

### Example

**A ready export**

Arguments:

```json
{
  "id": "exp_01m4tx5nj8emwbyf7y9vcf4aaa",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "id": "exp_01m4tx5nj8emwbyf7y9vcf4aaa",
  "object": "data_export",
  "livemode": false,
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
  "kind": "accounting",
  "status": "ready",
  "from": "2026-07-01",
  "to": "2026-09-30",
  "timeZone": "Europe/Zagreb",
  "requestedBy": {
    "type": "user",
    "id": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
  },
  "glMappingVersion": 3,
  "files": [
    {
      "part": "journal",
      "fileId": "file_01m4tx5nj8emwbyf7y9vcf4aab",
      "filename": "acme-hr-journal-2026-07-01-to-2026-09-30.csv",
      "contentType": "text/csv; charset=utf-8",
      "size": 421888,
      "sha256": "9f2c1d5e7a3b4c6d8e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d",
      "rows": 412
    },
    {
      "part": "invoices",
      "fileId": "file_01m4tx5nj8emwbyf7y9vcf4aac",
      "filename": "acme-hr-invoice-register-2026-07-01-to-2026-09-30.csv",
      "contentType": "text/csv; charset=utf-8",
      "size": 98304,
      "sha256": "9f2c1d5e7a3b4c6d8e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d",
      "rows": 96
    },
    {
      "part": "credit_notes",
      "fileId": "file_01m4tx5nj8emwbyf7y9vcf4aad",
      "filename": "acme-hr-credit-note-register-2026-07-01-to-2026-09-30.csv",
      "contentType": "text/csv; charset=utf-8",
      "size": 3072,
      "sha256": "9f2c1d5e7a3b4c6d8e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d",
      "rows": 3
    }
  ],
  "summary": {
    "journal": {
      "transactions": 180,
      "rows": 412,
      "totals": [
        {
          "currency": "EUR",
          "debit": "48210000000",
          "credit": "48210000000"
        }
      ],
      "unmappedAccounts": [],
      "unmappedCount": 0
    },
    "invoices": {
      "count": 96,
      "totals": [
        {
          "currency": "EUR",
          "net": "18400000000",
          "tax": "4600000000",
          "gross": "23000000000",
          "count": 96
        }
      ]
    },
    "creditNotes": {
      "count": 3,
      "totals": [
        {
          "currency": "EUR",
          "net": "160000000",
          "tax": "40000000",
          "gross": "200000000",
          "count": 3
        }
      ]
    }
  },
  "failure": null,
  "readyAt": "2026-10-02T08:00:21.000Z",
  "expiresAt": "2026-11-01T08:00:21.000Z",
  "createdAt": "2026-10-02T08:00:00.000Z",
  "updatedAt": "2026-10-02T08:00:21.000Z",
  "version": 3
}
```

## `exports_gl_mapping_get`

**Get the general-ledger mapping.** Operation [`exports.gl_mapping.get`](https://ownrecord.io/docs/reference/exports-gl-mapping-get.md) · Legal entity level · permission `ledger:read` · risk tier `read` · since M8

Returns the legal entity's general-ledger mapping in the mode of the request: the rules that map Ownrecord
ledger accounts to the entity's own chart of accounts in the accounting export's journal. A rule's `account` is
an account kind (e.g. `tax_payable`), an account code, or a code prefix ending in `*`; for each account the
exact code wins, then the longest prefix, then the kind. With no mapping (`version` 0), the journal's
general-ledger columns stay empty.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument    | Type         | Required | Description                                                                                                                                       |
| ----------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `entity_id` | ID (`ent_…`) | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`, or a brand key: exports belong to the entity).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't read this entity's ledger (`ledger:read`; brand-scoped members never see it).
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't use live exports.

### Example

**A mapping to a German chart (SKR03-style codes)**

Arguments:

```json
{
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "gl_mapping",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
  "livemode": false,
  "rules": [
    {
      "account": "processor_clearing",
      "glAccount": "1360",
      "glName": "Stripe clearing"
    },
    {
      "account": "bank",
      "glAccount": "1200",
      "glName": "Bank"
    },
    {
      "account": "tax_payable",
      "glAccount": "1776",
      "glName": "VAT payable"
    },
    {
      "account": "tax_payable:EU_OSS_UNION:*",
      "glAccount": "1777",
      "glName": "OSS VAT payable"
    },
    {
      "account": "revenue",
      "glAccount": "8400",
      "glName": "Revenue"
    },
    {
      "account": "processor_fees",
      "glAccount": "4970",
      "glName": "Payment fees"
    }
  ],
  "version": 3,
  "updatedAt": "2026-10-01T09:00:00.000Z",
  "updatedBy": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
}
```

## `exports_gl_mapping_set`

**Set the general-ledger mapping.** Operation [`exports.gl_mapping.set`](https://ownrecord.io/docs/reference/exports-gl-mapping-set.md) · Legal entity level · permission `ledger:write` · risk tier `write` · since M8

Replaces the legal entity's general-ledger mapping in the mode of the request with the rules given (at most
200\). Each rule maps Ownrecord ledger accounts to an account of the entity's own chart: `account` is an account
kind (`processor_clearing`, `bank`, `tax_payable`, `revenue`, `processor_fees`, …), an account code (e.g.
`bank:ent_…:EUR`) or a code prefix ending in `*` (e.g. `tax_payable:EU_OSS_UNION:*`); `glAccount` is the
general-ledger code and `glName` its name. Exports requested afterwards use the new mapping; earlier exports
keep theirs. Pass the `version` you read as `expectedVersion` to avoid overwriting someone else's change.

Annotations: `readOnlyHint: false` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument          | Type            | Required | Description                                                                                                                                                                                              |
| ----------------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `rules`           | array of object | yes      | The whole table: it replaces the current rules. (at most 200 items)                                                                                                                                      |
| `expectedVersion` | integer         | no       | The mapping's `version` you read (0 while none is set): a guard against a concurrent change. (0–9007199254740991)                                                                                        |
| `entity_id`       | ID (`ent_…`)    | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity.                                                        |
| `idempotency_key` | string          | no       | A unique string for this change. Retrying with the same key and arguments never acts twice. When left out, the server generates one and returns it in the result's `idempotency_key`. (1–255 characters) |
| `dry_run`         | boolean         | no       | true: check permissions and rules and compute the result, then roll everything back. Nothing is saved. (default `false`)                                                                                 |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Idempotency:** the result returns the `idempotency_key` used, yours or one the server generated. Retry with it: a call with the same key and arguments never acts twice (keys are kept for 24 hours).
- **Dry run:** supported. `dry_run: true` checks permissions and rules and computes the result, then rolls everything back.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A rule is malformed (a field missing or too long), or there are more than 200.
- [`gl_mapping_invalid`](https://ownrecord.io/docs/reference/errors.md#gl_mapping_invalid): A rule's account isn't a kind, code or prefix, a glAccount isn't valid, or two rules map the same accounts (`details.problems`).
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The mapping changed since you read it (`expectedVersion`).
- [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused): The idempotency key was used before for another request.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`, or a brand key: exports belong to the entity).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't export this entity's books or change its mapping (`ledger:write`: finance, owners and admins).
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't use live exports.

### Example

**Map clearing, bank, VAT, revenue and fees**

Arguments:

```json
{
  "rules": [
    {
      "account": "processor_clearing",
      "glAccount": "1360",
      "glName": "Stripe clearing"
    },
    {
      "account": "bank",
      "glAccount": "1200",
      "glName": "Bank"
    },
    {
      "account": "tax_payable",
      "glAccount": "1776",
      "glName": "VAT payable"
    },
    {
      "account": "tax_payable:EU_OSS_UNION:*",
      "glAccount": "1777",
      "glName": "OSS VAT payable"
    },
    {
      "account": "revenue",
      "glAccount": "8400",
      "glName": "Revenue"
    },
    {
      "account": "processor_fees",
      "glAccount": "4970",
      "glName": "Payment fees"
    }
  ],
  "expectedVersion": 2,
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "object": "gl_mapping",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
  "livemode": false,
  "rules": [
    {
      "account": "processor_clearing",
      "glAccount": "1360",
      "glName": "Stripe clearing"
    },
    {
      "account": "bank",
      "glAccount": "1200",
      "glName": "Bank"
    },
    {
      "account": "tax_payable",
      "glAccount": "1776",
      "glName": "VAT payable"
    },
    {
      "account": "tax_payable:EU_OSS_UNION:*",
      "glAccount": "1777",
      "glName": "OSS VAT payable"
    },
    {
      "account": "revenue",
      "glAccount": "8400",
      "glName": "Revenue"
    },
    {
      "account": "processor_fees",
      "glAccount": "4970",
      "glName": "Payment fees"
    }
  ],
  "version": 3,
  "updatedAt": "2026-10-01T09:00:00.000Z",
  "updatedBy": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
}
```

## `exports_list`

**List accounting exports.** Operation [`exports.list`](https://ownrecord.io/docs/reference/exports-list.md) · Legal entity level · permission `ledger:read` · risk tier `read` · since M8

Lists the legal entity's accounting exports in the mode of the request, newest first. Filter by `status` (one or
several, comma-separated); paginate with `limit` (1–100, default 10) and `starting_after`.

Annotations: `readOnlyHint: true` · `destructiveHint: false` · `idempotentHint: true` · `openWorldHint: false`

### Arguments

| Argument         | Type                                                              | Required | Description                                                                                                                                       |
| ---------------- | ----------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`         | array of one of `queued`, `running`, `ready`, `expired`, `failed` | no       | (1–5 items)                                                                                                                                       |
| `limit`          | integer                                                           | no       | (1–100)                                                                                                                                           |
| `starting_after` | ID (`exp_…`)                                                      | no       | The `next_cursor` of the previous page.                                                                                                           |
| `entity_id`      | ID (`ent_…`)                                                      | no       | The legal entity to act on (ent\_…), inside your API key's reach. Needed with an organization key; entity and brand keys act on their own entity. |

- **Legal entity:** pass `entity_id` with an organization key; entity and brand keys act on their own entity.
- **Read-only:** changes nothing; `idempotency_key` is ignored.

### Errors

- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A filter or pagination value is invalid.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`, or a brand key: exports belong to the entity).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't read this entity's ledger (`ledger:read`; brand-scoped members never see it).
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't use live exports.

### Example

**The latest export**

Arguments:

```json
{
  "limit": 1,
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "exp_01m4tx5nj8emwbyf7y9vcf4aaa",
      "object": "data_export",
      "livemode": false,
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47zm",
      "kind": "accounting",
      "status": "ready",
      "from": "2026-07-01",
      "to": "2026-09-30",
      "timeZone": "Europe/Zagreb",
      "requestedBy": {
        "type": "user",
        "id": "usr_01m4tx5nj8emwbyf7y9vcf47zk"
      },
      "glMappingVersion": 3,
      "files": [
        {
          "part": "journal",
          "fileId": "file_01m4tx5nj8emwbyf7y9vcf4aab",
          "filename": "acme-hr-journal-2026-07-01-to-2026-09-30.csv",
          "contentType": "text/csv; charset=utf-8",
          "size": 421888,
          "sha256": "9f2c1d5e7a3b4c6d8e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d",
          "rows": 412
        },
        {
          "part": "invoices",
          "fileId": "file_01m4tx5nj8emwbyf7y9vcf4aac",
          "filename": "acme-hr-invoice-register-2026-07-01-to-2026-09-30.csv",
          "contentType": "text/csv; charset=utf-8",
          "size": 98304,
          "sha256": "9f2c1d5e7a3b4c6d8e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d",
          "rows": 96
        },
        {
          "part": "credit_notes",
          "fileId": "file_01m4tx5nj8emwbyf7y9vcf4aad",
          "filename": "acme-hr-credit-note-register-2026-07-01-to-2026-09-30.csv",
          "contentType": "text/csv; charset=utf-8",
          "size": 3072,
          "sha256": "9f2c1d5e7a3b4c6d8e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d",
          "rows": 3
        }
      ],
      "summary": {
        "journal": {
          "transactions": 180,
          "rows": 412,
          "totals": [
            {
              "currency": "EUR",
              "debit": "48210000000",
              "credit": "48210000000"
            }
          ],
          "unmappedAccounts": [],
          "unmappedCount": 0
        },
        "invoices": {
          "count": 96,
          "totals": [
            {
              "currency": "EUR",
              "net": "18400000000",
              "tax": "4600000000",
              "gross": "23000000000",
              "count": 96
            }
          ]
        },
        "creditNotes": {
          "count": 3,
          "totals": [
            {
              "currency": "EUR",
              "net": "160000000",
              "tax": "40000000",
              "gross": "200000000",
              "count": 3
            }
          ]
        }
      },
      "failure": null,
      "readyAt": "2026-10-02T08:00:21.000Z",
      "expiresAt": "2026-11-01T08:00:21.000Z",
      "createdAt": "2026-10-02T08:00:00.000Z",
      "updatedAt": "2026-10-02T08:00:21.000Z",
      "version": 3
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```
