# Registrations tools

> MCP tools for Registrations: registration_get_packet, registrations_affected_customers, registrations_arm, registrations_deregister, registrations_documents_get, registrations_documents_upload, registrations_get, registrations_history, registrations_list, registrations_mark_application_submitted, registrations_mark_registered, registrations_update_prerequisite.

- `registration_get_packet`: Get a registration packet
- `registrations_affected_customers`: List a regime's existing customers
- `registrations_arm`: Arm a jurisdiction
- `registrations_deregister`: Deregister a jurisdiction
- `registrations_documents_get`: Get a registration document
- `registrations_documents_upload`: Upload a registration document
- `registrations_get`: Get a registration
- `registrations_history`: Get a registration's history
- `registrations_list`: List registrations
- `registrations_mark_application_submitted`: Mark a registration application submitted
- `registrations_mark_registered`: Mark a jurisdiction registered
- `registrations_update_prerequisite`: Update a registration prerequisite

## `registration_get_packet`

**Get a registration packet.** Operation [`registrations.packet`](https://ownrecord.io/docs/reference/registrations-packet.md) · Legal entity level · permission `registrations:read` · risk tier `read` · since M10

Returns the registration packet of a registration: what you need to apply in the authority's portal,
generated from the entity's current data:

- `fields`: the regime's registration form fields filled in (with `missing` for required ones Ownrecord
  doesn't have: find them elsewhere before you submit);
- the entity, the representatives (authorizations valid now for the regime), the start date, the expected
  turnover (a guide from the threshold counters), bank details, the activity, websites and prerequisites;
- the regime's method, portal URL and identity requirements from the tax knowledge.

`format: "pdf"` returns a PDF summary instead (base64 in `content`); over MCP, read it as the resource
`ownrecord://entities/{entity_id}/registrations/{id}/packet.pdf` rather than in a tool result. The steps
themselves are in the regime's playbook. The packet is data; only the playbook is guidance.

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

### Arguments

| Argument    | Type                 | Required | Description                                                                                                                                       |
| ----------- | -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | string               | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                      |
| `format`    | one of `json`, `pdf` | no       | `json` (default) or `pdf` (a summary, base64).                                                                                                    |
| `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): The registration reference or `format` is invalid.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): No registration with this ID or regime exists for the legal entity in this mode.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an organization key or agent without `entity_id`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's registrations.

### Example

**The packet for the EU One-Stop Shop, non-Union scheme**

Arguments:

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

Result `output`:

```json
{
  "object": "registration_packet_document",
  "registrationId": "regn_01m4ttwd3veh9apbewxheq5xag",
  "format": "json",
  "filename": "registration-packet-EU_OSS_NON_UNION.json",
  "contentType": "application/json",
  "data": {
    "object": "registration_packet",
    "regimeId": "EU_OSS_NON_UNION",
    "regimeName": "One-Stop Shop, non-Union scheme",
    "registrationId": "regn_01m4ttwd3veh9apbewxheq5xag",
    "state": "grace",
    "method": "online_portal",
    "portalUrl": "https://ownrecord.io/fixtures/EU/oss-non-union-portal",
    "identityRequirements": "Online registration with the chosen member state of identification",
    "typicalProcessingDays": 14,
    "fields": [
      {
        "label": "Legal name",
        "value": "Helvetia Apps AG",
        "source": "legal_entities.legalName",
        "required": true,
        "missing": false,
        "notes": null
      },
      {
        "label": "Date of the first supply",
        "value": "2026-10-14",
        "source": "registrations.triggeredAt",
        "required": true,
        "missing": false,
        "notes": null
      },
      {
        "label": "Contact person and email",
        "value": null,
        "source": null,
        "required": true,
        "missing": true,
        "notes": "The entity's tax manager"
      }
    ],
    "entity": {
      "legalName": "Helvetia Apps AG",
      "tradingName": null,
      "address": "Bahnhofstrasse 1, 8001 Zürich, CH",
      "country": "CH",
      "companyRegistryId": "CHE-000.000.042",
      "taxId": {
        "type": "ch_vat",
        "value": "CHE-000.000.042 MWST"
      },
      "currency": "CHF",
      "timeZone": "Europe/Zurich"
    },
    "representatives": [
      {
        "name": "Ana Horvat",
        "kind": "employee_eid",
        "contact": "ana.horvat@example.com",
        "validFrom": "2026-01-01",
        "validTo": null,
        "portals": ["OSS portal"]
      }
    ],
    "startDate": "2026-10-14",
    "expectedTurnover": {
      "amount": {
        "amount": "1200000000",
        "currency": "EUR",
        "decimal": "1200.00"
      },
      "basis": "Sales counted toward the EU_OSS_NON_UNION threshold in 2026, all brands (a guide, not a forecast)."
    },
    "bankDetails": null,
    "activity": "Software as a service",
    "websites": ["pay.helvetia.example"],
    "prerequisites": [
      {
        "code": "portal_access",
        "description": "Open a portal account",
        "leadTimeDays": 14,
        "status": "done"
      }
    ],
    "missing": ["Contact person and email"]
  },
  "content": null,
  "size": 1630,
  "sha256": "9b2f4c6e8a0d1f3b5c7e9a2d4f6b8c0e1a3d5f7b9c2e4a6d8f0b1c3e5a7d9f2b"
}
```

## `registrations_affected_customers`

**List a regime's existing customers.** Operation [`registrations.affected_customers`](https://ownrecord.io/docs/reference/registrations-affected-customers.md) · Legal entity level · permission `registrations:read` · risk tier `read` · since M7

Lists the customers the legal entity has already charged tax under a registration's regime, in the mode of
the request, all brands combined, with their open liability. When a regime is blocked for new consumers
(`blocked_b2c`), these existing customers keep their renewals, top-ups and refunds, and their tax is still
charged and owed (spec §10.7).

For each customer: `pendingRegistration`, the tax charged before the entity registered
(`tax_pending_registration` in the ledger, net of refunds): the open liability; `chargedAsRegistered`, the
tax charged while registered; the regime's jurisdictions and the first and last sale. `email` and `name` are
shown only if you can read that brand's customers.

`summary` has the regime's open liability per jurisdiction (the ledger balances), the number of customers,
and pending amounts linked to no customer (`unattributed`). Customers are listed newest first; paginate with
`limit` (1–100, default 25) and `starting_after`.

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

### Arguments

| Argument         | Type         | Required | Description                                                                                                                                       |
| ---------------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`             | string       | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                      |
| `limit`          | integer      | no       | Page size, 1 to 100 (default 25). (1–100)                                                                                                         |
| `starting_after` | ID (`cus_…`) | 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): `id`, `limit` or `starting_after` is malformed.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration 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`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's registrations.

### Example

**Two consumers of a blocked OSS registration**

Arguments:

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

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "object": "affected_customer",
      "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47xs",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "email": "lena@example.de",
      "name": "Lena Schmidt",
      "deleted": false,
      "jurisdictionIds": ["DE"],
      "pendingRegistration": [
        {
          "amount": "3800000",
          "currency": "EUR"
        }
      ],
      "chargedAsRegistered": [],
      "firstSaleAt": "2026-10-14T09:30:00.000Z",
      "lastSaleAt": "2026-10-14T09:30:00.000Z",
      "transactionCount": 1
    },
    {
      "object": "affected_customer",
      "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47xr",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "email": "marie@example.fr",
      "name": null,
      "deleted": false,
      "jurisdictionIds": ["FR"],
      "pendingRegistration": [
        {
          "amount": "7980000",
          "currency": "EUR"
        }
      ],
      "chargedAsRegistered": [],
      "firstSaleAt": "2026-10-15T10:02:11.000Z",
      "lastSaleAt": "2026-11-15T10:02:13.000Z",
      "transactionCount": 2
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "registrationId": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "regimeId": "EU_OSS_NON_UNION",
  "summary": {
    "customerCount": 2,
    "customersWithOpenLiability": 2,
    "openLiability": [
      {
        "jurisdictionId": "DE",
        "pendingRegistration": {
          "amount": "3800000",
          "currency": "EUR"
        }
      },
      {
        "jurisdictionId": "FR",
        "pendingRegistration": {
          "amount": "7980000",
          "currency": "EUR"
        }
      }
    ],
    "openLiabilityTotal": [
      {
        "amount": "11780000",
        "currency": "EUR"
      }
    ],
    "unattributed": []
  }
}
```

## `registrations_arm`

**Arm a jurisdiction.** Operation [`registrations.arm`](https://ownrecord.io/docs/reference/registrations-arm.md) · Legal entity level · permission `registrations:write` · risk tier `compliance` · since M3

Arms a blocked jurisdiction: you confirm that its registration prerequisites are complete and that someone
will register within the regime's grace period. It stays `blocked_b2c` with `armed: true`, and the first
consumer sale there starts the grace period and its deadline (spec §10.2). Use it for regimes with no
threshold that allow registering shortly after the first sale (EU non-Union OSS, the UK).

Needs `blocked_b2c` (not armed), every prerequisite `done` and a regime with a grace period; an obligation
already triggered whose grace period has passed can't be armed (register and mark it registered instead).

Compliance tier (spec §41.4): tax managers, owners and admins. If the organization's approval policy lists
this operation, the call answers `approval_required` and runs once a second person approves it.
Dry-run it first (`Ownrecord-Dry-Run: true`, `dry_run: true`) to see the result. Returns the registration.

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

### Arguments

| Argument          | Type         | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | string       | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                                                                             |
| `note`            | string       | no       | Why, or anything the team should know; kept in the registration's history and the audit log. (1–1000 characters)                                                                                         |
| `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

- [`registration_transition_invalid`](https://ownrecord.io/docs/reference/errors.md#registration_transition_invalid): The registration isn't `blocked_b2c`, or it is armed already (`details.allowed_from`).
- [`registration_prerequisites_incomplete`](https://ownrecord.io/docs/reference/errors.md#registration_prerequisites_incomplete): A prerequisite isn't `done` yet.
- [`registration_grace_not_allowed`](https://ownrecord.io/docs/reference/errors.md#registration_grace_not_allowed): The regime has no grace period (e.g. US states).
- [`registration_grace_expired`](https://ownrecord.io/docs/reference/errors.md#registration_grace_expired): An obligation already triggered and its grace period has passed.
- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is missing or malformed (`details.issues`).
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration in this mode.
- [`jurisdiction_blocked`](https://ownrecord.io/docs/reference/errors.md#jurisdiction_blocked): The tax knowledge no longer has a usable regime for this registration, so it can't change now.
- [`approval_required`](https://ownrecord.io/docs/reference/errors.md#approval_required): The organization's approval policy needs a second person for this action; nothing changed yet.
- [`approval_rejected`](https://ownrecord.io/docs/reference/errors.md#approval_rejected): The same request was sent again after it was rejected.
- [`approval_expired`](https://ownrecord.io/docs/reference/errors.md#approval_expired): The same request was sent again after its approval request expired.
- [`stale_approval`](https://ownrecord.io/docs/reference/errors.md#stale_approval): The approved request could no longer run as requested.
- [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused): The idempotency key was used before with another input.
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't change live registrations.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this entity's registrations (tax managers, owners and admins can).
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The registration changed at the same moment (a sale or the deadline job); reload and retry.

### Example

**Arm EU non-Union OSS**

Arguments:

```json
{
  "id": "EU_OSS_NON_UNION",
  "note": "OSS portal access ready; Ana files within the month",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "object": "registration",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "regimeId": "EU_OSS_NON_UNION",
  "regimeName": "EU One-Stop Shop, non-Union scheme",
  "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
  "state": "blocked_b2c",
  "stateReason": "armed",
  "stateChangedAt": "2026-10-13T12:00:00.000Z",
  "armed": true,
  "triggeredAt": null,
  "deadlineAt": null,
  "autoBlockAt": null,
  "applicationSubmittedAt": null,
  "escalationLevel": 0,
  "registrationNumber": null,
  "effectiveFrom": null,
  "registeredAt": null,
  "prerequisitesDone": true,
  "prerequisitesProgress": {
    "done": 1,
    "total": 1
  },
  "threshold": null,
  "timeZones": ["Europe/Zagreb"],
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T12:00:00.000Z",
  "prerequisites": [
    {
      "code": "portal_access",
      "description": "Access to the tax portal of the member state of identification",
      "leadTimeDays": 7,
      "status": "done",
      "doneAt": "2026-10-13T12:00:00.000Z",
      "notes": "ePorezna access for the finance team",
      "owner": "Ana (finance)",
      "attachments": [],
      "updatedAt": "2026-10-13T12:00:00.000Z",
      "updatedBy": "usr_01m4tx5nj8emwbyf7y9vcf47xa"
    }
  ],
  "evidenceFiles": [],
  "history": [
    {
      "from": null,
      "to": "monitored",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "below_threshold",
      "note": null
    },
    {
      "from": "monitored",
      "to": "pre_registration",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "pre_registration_ratio_reached",
      "note": null
    }
  ],
  "counters": [
    {
      "windowKey": "2026",
      "amount": {
        "amount": "8500000000",
        "currency": "EUR"
      },
      "transactionCount": 412,
      "lastEventAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "regime": {
    "id": "EU_OSS_UNION",
    "name": "EU One-Stop Shop, Union scheme",
    "version": "3f2a9c41d07e88b1",
    "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
    "sellerEstablishment": "in_eu_other_ms",
    "customerType": "b2c",
    "threshold": {
      "amount": {
        "amount": "10000000000",
        "currency": "EUR"
      },
      "measure": "eu_cross_border_b2c",
      "window": "calendar_year_current_or_previous",
      "transactionCount": null,
      "whatCounts": "B2C electronically supplied services to consumers in other member states, net of VAT.",
      "amountInclusive": false
    },
    "zeroThreshold": false,
    "grace": {
      "rule": "nth_day_of_following_month",
      "days": null,
      "nthDay": 10
    },
    "collectBeforeRegistration": true,
    "b2bReverseChargeNoRegistration": true,
    "b2bChargeWhenRegistered": false,
    "requiresFiscalRepresentative": false,
    "requiresLocalAgent": false,
    "securityDeposit": null,
    "registration": {
      "method": "online",
      "portalUrl": "https://e-porezna.porezna-uprava.hr",
      "identityRequirements": null,
      "typicalProcessingDays": 7
    },
    "status": "verified",
    "unverified": false,
    "fixture": false,
    "validFrom": "2021-07-01",
    "validTo": null
  },
  "playbooks": [
    {
      "key": "EU/playbooks/EU_OSS_UNION-registration.md",
      "kind": "registration",
      "markdown": "# Registering for the Union OSS\n\n1. Sign in to the portal of your member state …"
    }
  ],
  "officialLinks": [
    {
      "label": "EU One-Stop Shop, Union scheme: registration portal",
      "url": "https://e-porezna.porezna-uprava.hr"
    }
  ],
  "actions": {
    "arm": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"arm\" isn't possible."
    },
    "markApplicationSubmitted": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"application_submitted\" isn't possible."
    },
    "markRegistered": {
      "allowed": true,
      "code": null,
      "message": null
    },
    "deregister": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"deregister\" isn't possible."
    }
  },
  "safetyBufferHours": 72,
  "knowledgeCommit": "1c14b2ec912aca347dd518b2044096f3b5d8eef1"
}
```

## `registrations_deregister`

**Deregister a jurisdiction.** Operation [`registrations.deregister`](https://ownrecord.io/docs/reference/registrations-deregister.md) · Legal entity level · permission `registrations:write` · risk tier `compliance` · since M3

Records that the entity's registration for a regime has ended (it deregistered with the tax authority). The
registration becomes `deregistered`: consumer sales there are then treated like `monitored` for a regime
with a threshold (a new crossing triggers again) or like `blocked_b2c` for a zero-threshold regime (spec
§10.1). The registration number and proof stay in its history.

Needs `registered`. Returns the registration.

Compliance tier (spec §41.4): tax managers, owners and admins. If the organization's approval policy lists
this operation, the call answers `approval_required` and runs once a second person approves it.

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

### Arguments

| Argument          | Type         | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | string       | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                                                                             |
| `note`            | string       | no       | Why, or anything the team should know; kept in the registration's history and the audit log. (1–1000 characters)                                                                                         |
| `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

- [`registration_transition_invalid`](https://ownrecord.io/docs/reference/errors.md#registration_transition_invalid): The registration isn't `registered`.
- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is missing or malformed (`details.issues`).
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration in this mode.
- [`jurisdiction_blocked`](https://ownrecord.io/docs/reference/errors.md#jurisdiction_blocked): The tax knowledge no longer has a usable regime for this registration, so it can't change now.
- [`approval_required`](https://ownrecord.io/docs/reference/errors.md#approval_required): The organization's approval policy needs a second person for this action; nothing changed yet.
- [`approval_rejected`](https://ownrecord.io/docs/reference/errors.md#approval_rejected): The same request was sent again after it was rejected.
- [`approval_expired`](https://ownrecord.io/docs/reference/errors.md#approval_expired): The same request was sent again after its approval request expired.
- [`stale_approval`](https://ownrecord.io/docs/reference/errors.md#stale_approval): The approved request could no longer run as requested.
- [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused): The idempotency key was used before with another input.
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't change live registrations.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this entity's registrations (tax managers, owners and admins can).
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The registration changed at the same moment (a sale or the deadline job); reload and retry.

### Example

**Deregistered after closing UK sales**

Arguments:

```json
{
  "id": "regn_01m4tx5nj8emwbyf7y9vcf47xm",
  "note": "Stopped selling to UK consumers",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "regn_01m4tx5nj8emwbyf7y9vcf47xm",
  "object": "registration",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "regimeId": "GB_VAT_NETP",
  "regimeName": "United Kingdom, VAT for non-established taxable persons",
  "jurisdictionIds": ["GB"],
  "state": "deregistered",
  "stateReason": "deregistered",
  "stateChangedAt": "2026-10-14T09:30:00.000Z",
  "armed": false,
  "triggeredAt": null,
  "deadlineAt": null,
  "autoBlockAt": null,
  "applicationSubmittedAt": null,
  "escalationLevel": 0,
  "registrationNumber": "GB123456789",
  "effectiveFrom": null,
  "registeredAt": null,
  "prerequisitesDone": true,
  "prerequisitesProgress": {
    "done": 0,
    "total": 0
  },
  "threshold": null,
  "timeZones": ["Europe/London"],
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z",
  "prerequisites": [],
  "evidenceFiles": [],
  "history": [],
  "counters": [],
  "regime": null,
  "playbooks": [],
  "officialLinks": [],
  "actions": {
    "arm": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"arm\" isn't possible."
    },
    "markApplicationSubmitted": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"application_submitted\" isn't possible."
    },
    "markRegistered": {
      "allowed": true,
      "code": null,
      "message": null
    },
    "deregister": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"deregister\" isn't possible."
    }
  },
  "safetyBufferHours": 72,
  "knowledgeCommit": "1c14b2ec912aca347dd518b2044096f3b5d8eef1"
}
```

## `registrations_documents_get`

**Get a registration document.** Operation [`registrations.documents.get`](https://ownrecord.io/docs/reference/registrations-documents-get.md) · Legal entity level · permission `registrations:read` · risk tier `read` · since M7

Returns a document uploaded to a registration (`registrations.documents.upload`): its file name, type, size
and SHA-256. In the console, documents open from the registration's page; the file itself is served only
after this check, and only when its bytes still match the SHA-256.

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

### Arguments

| Argument    | Type          | Required | Description                                                                                                                                       |
| ----------- | ------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | string        | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                      |
| `file`      | ID (`file_…`) | yes      | The document's ID (`file_…`).                                                                                                                     |
| `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` or `file` is malformed.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration in this mode, or the file isn't one of its documents.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's registrations.

### Example

**The uploaded OSS submission receipt**

Arguments:

```json
{
  "id": "EU_OSS_NON_UNION",
  "file": "file_01m4tx5nj8emwbyf7y9vcf47xq",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "id": "file_01m4tx5nj8emwbyf7y9vcf47xq",
  "object": "registration_document",
  "registrationId": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "livemode": true,
  "filename": "oss-submission-receipt.pdf",
  "contentType": "application/pdf",
  "size": 82,
  "sha256": "36dc4d8396e18eff67cf01ca1121f420465e698179be0d927351dbe6ac07884d",
  "createdAt": "2026-10-20T08:15:00.000Z"
}
```

## `registrations_documents_upload`

**Upload a registration document.** Operation [`registrations.documents.upload`](https://ownrecord.io/docs/reference/registrations-documents-upload.md) · Legal entity level · permission `registrations:write` · risk tier `write` · since M7

Uploads a document to a registration: a submission receipt, a registration confirmation, a company register
extract for a prerequisite. Send the file base64-encoded in `content`: a PDF, PNG, JPEG or WebP file of at
most 3 MB, with its `filename`. The type is read from the file itself.

The document is stored privately (spec §7.10) and returned with its `file_…` ID. Use that ID as the
`reference` of a prerequisite's attachment (`registrations.update_prerequisite`) or of the proof when you
mark the application submitted or the registration registered. Uploading the same file to the same
registration again returns the same document.

Write tier: tax managers, owners and admins. Dry-run it to check a file without storing it.

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

### Arguments

| Argument          | Type                                                              | Required | Description                                                                                                                                                                                              |
| ----------------- | ----------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | string                                                            | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                                                                             |
| `content`         | string                                                            | yes      | The file's bytes, base64-encoded: a PDF, PNG, JPEG or WebP file of at most 3 MB. (1–4294304 characters)                                                                                                  |
| `filename`        | string                                                            | no       | The file's name, shown in the console and used for downloads, e.g. `oss-receipt.pdf`. (1–200 characters)                                                                                                 |
| `contentType`     | one of `application/pdf`, `image/png`, `image/jpeg`, `image/webp` | no       | The file's type. Optional: it is read from the file, and must agree when given.                                                                                                                          |
| `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): The content isn't base64, is larger than 3 MB, isn't a PDF, PNG, JPEG or WebP file, or isn't the `contentType` given (`param` names the field).
- [`upstream_timeout`](https://ownrecord.io/docs/reference/errors.md#upstream_timeout): The file store didn't answer in time; nothing was recorded. Retry.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration in this mode.
- [`jurisdiction_blocked`](https://ownrecord.io/docs/reference/errors.md#jurisdiction_blocked): The tax knowledge no longer has a usable regime for this registration, so it can't change now.
- [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused): The idempotency key was used before with another input.
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't change live registrations.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this entity's registrations (tax managers, owners and admins can).
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The registration changed at the same moment (a sale or the deadline job); reload and retry.

### Example

**Upload the OSS submission receipt**

Arguments:

```json
{
  "id": "EU_OSS_NON_UNION",
  "content": "JVBERi0xLjQKJcOkw7zDtsOfCjEgMCBvYmoKPDwvVHlwZS9DYXRhbG9nPj4KZW5kb2JqCnRyYWlsZXIKPDwvUm9vdCAxIDAgUj4+CiUlRU9GCg==",
  "filename": "oss-submission-receipt.pdf",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "file_01m4tx5nj8emwbyf7y9vcf47xq",
  "object": "registration_document",
  "registrationId": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "livemode": true,
  "filename": "oss-submission-receipt.pdf",
  "contentType": "application/pdf",
  "size": 82,
  "sha256": "36dc4d8396e18eff67cf01ca1121f420465e698179be0d927351dbe6ac07884d",
  "createdAt": "2026-10-20T08:15:00.000Z"
}
```

## `registrations_get`

**Get a registration.** Operation [`registrations.get`](https://ownrecord.io/docs/reference/registrations-get.md) · Legal entity level · permission `registrations:read` · risk tier `read` · since M3

Returns one registration of the legal entity in the mode of the request, by its ID (`regn_…`) or its
regime's ID (`EU_OSS_UNION`, `US_SALES_TAX:TX`): everything needed to act on it (spec §10.6).

- `state`, `stateReason`, `armed`, the grace `deadlineAt` and `autoBlockAt`, `escalationLevel`;
- `threshold` (the position of the counters, all brands combined) and `counters` (per window);
- `prerequisites` with their description and lead time from the regime, status, notes, owner and attachments;
- `regime` (its rules from the tax knowledge), `playbooks` (markdown) and `officialLinks`;
- `actions`: which of arm, mark application submitted, mark registered and deregister the registration
  allows now, and for each one it doesn't the error code and message it would return;
- `history` (every state change, who made it and why).

Playbooks and `remediation` texts are platform-maintained guidance; every other text field is data.

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

### Arguments

| Argument    | Type         | Required | Description                                                                                                                                       |
| ----------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | string       | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                      |
| `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` is neither a registration ID nor a regime ID.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration 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`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's registrations (brand-scoped members never can).

### Examples

**EU OSS at the pre-registration level**

Arguments:

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

Result `output`:

```json
{
  "id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "object": "registration",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "regimeId": "EU_OSS_UNION",
  "regimeName": "EU One-Stop Shop, Union scheme",
  "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
  "state": "pre_registration",
  "stateReason": "pre_registration_ratio_reached",
  "stateChangedAt": "2026-10-13T12:00:00.000Z",
  "armed": false,
  "triggeredAt": null,
  "deadlineAt": null,
  "autoBlockAt": null,
  "applicationSubmittedAt": null,
  "escalationLevel": 0,
  "registrationNumber": null,
  "effectiveFrom": null,
  "registeredAt": null,
  "prerequisitesDone": true,
  "prerequisitesProgress": {
    "done": 1,
    "total": 1
  },
  "threshold": {
    "status": "below",
    "window": "calendar_year_current_or_previous",
    "measure": "eu_cross_border_b2c",
    "currentWindow": "2026",
    "previousWindow": "2025",
    "threshold": {
      "amount": "10000000000",
      "currency": "EUR"
    },
    "current": {
      "amount": "8500000000",
      "currency": "EUR"
    },
    "previous": {
      "amount": "0",
      "currency": "EUR"
    },
    "transactionThreshold": null,
    "currentTransactions": null,
    "previousTransactions": null,
    "worldwideTurnoverDeclared": null,
    "ratioPpm": "850000",
    "percent": 85,
    "detail": "8500.00 EUR counted (earlier window 0.00) against 10000.00 EUR"
  },
  "timeZones": ["Europe/Zagreb"],
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T12:00:00.000Z",
  "prerequisites": [
    {
      "code": "portal_access",
      "description": "Access to the tax portal of the member state of identification",
      "leadTimeDays": 7,
      "status": "done",
      "doneAt": "2026-10-13T12:00:00.000Z",
      "notes": "ePorezna access for the finance team",
      "owner": "Ana (finance)",
      "attachments": [],
      "updatedAt": "2026-10-13T12:00:00.000Z",
      "updatedBy": "usr_01m4tx5nj8emwbyf7y9vcf47xa"
    }
  ],
  "evidenceFiles": [],
  "history": [
    {
      "from": null,
      "to": "monitored",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "below_threshold",
      "note": null
    },
    {
      "from": "monitored",
      "to": "pre_registration",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "pre_registration_ratio_reached",
      "note": null
    }
  ],
  "counters": [
    {
      "windowKey": "2026",
      "amount": {
        "amount": "8500000000",
        "currency": "EUR"
      },
      "transactionCount": 412,
      "lastEventAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "regime": {
    "id": "EU_OSS_UNION",
    "name": "EU One-Stop Shop, Union scheme",
    "version": "3f2a9c41d07e88b1",
    "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
    "sellerEstablishment": "in_eu_other_ms",
    "customerType": "b2c",
    "threshold": {
      "amount": {
        "amount": "10000000000",
        "currency": "EUR"
      },
      "measure": "eu_cross_border_b2c",
      "window": "calendar_year_current_or_previous",
      "transactionCount": null,
      "whatCounts": "B2C electronically supplied services to consumers in other member states, net of VAT.",
      "amountInclusive": false
    },
    "zeroThreshold": false,
    "grace": {
      "rule": "nth_day_of_following_month",
      "days": null,
      "nthDay": 10
    },
    "collectBeforeRegistration": true,
    "b2bReverseChargeNoRegistration": true,
    "b2bChargeWhenRegistered": false,
    "requiresFiscalRepresentative": false,
    "requiresLocalAgent": false,
    "securityDeposit": null,
    "registration": {
      "method": "online",
      "portalUrl": "https://e-porezna.porezna-uprava.hr",
      "identityRequirements": null,
      "typicalProcessingDays": 7
    },
    "status": "verified",
    "unverified": false,
    "fixture": false,
    "validFrom": "2021-07-01",
    "validTo": null
  },
  "playbooks": [
    {
      "key": "EU/playbooks/EU_OSS_UNION-registration.md",
      "kind": "registration",
      "markdown": "# Registering for the Union OSS\n\n1. Sign in to the portal of your member state …"
    }
  ],
  "officialLinks": [
    {
      "label": "EU One-Stop Shop, Union scheme: registration portal",
      "url": "https://e-porezna.porezna-uprava.hr"
    }
  ],
  "actions": {
    "arm": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"arm\" isn't possible."
    },
    "markApplicationSubmitted": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"application_submitted\" isn't possible."
    },
    "markRegistered": {
      "allowed": true,
      "code": null,
      "message": null
    },
    "deregister": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"deregister\" isn't possible."
    }
  },
  "safetyBufferHours": 72,
  "knowledgeCommit": "1c14b2ec912aca347dd518b2044096f3b5d8eef1"
}
```

**A registration in grace, by its ID**

Arguments:

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

Result `output`:

```json
{
  "id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "object": "registration",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "regimeId": "EU_OSS_UNION",
  "regimeName": "EU One-Stop Shop, Union scheme",
  "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
  "state": "grace",
  "stateReason": "threshold_crossed",
  "stateChangedAt": "2026-10-14T09:30:00.000Z",
  "armed": false,
  "triggeredAt": "2026-10-14T09:30:00.000Z",
  "deadlineAt": "2026-11-10T22:59:59.000Z",
  "autoBlockAt": "2026-11-07T22:59:59.000Z",
  "applicationSubmittedAt": null,
  "escalationLevel": 0,
  "registrationNumber": null,
  "effectiveFrom": null,
  "registeredAt": null,
  "prerequisitesDone": true,
  "prerequisitesProgress": {
    "done": 1,
    "total": 1
  },
  "threshold": {
    "status": "over",
    "window": "calendar_year_current_or_previous",
    "measure": "eu_cross_border_b2c",
    "currentWindow": "2026",
    "previousWindow": "2025",
    "threshold": {
      "amount": "10000000000",
      "currency": "EUR"
    },
    "current": {
      "amount": "8500000000",
      "currency": "EUR"
    },
    "previous": {
      "amount": "0",
      "currency": "EUR"
    },
    "transactionThreshold": null,
    "currentTransactions": null,
    "previousTransactions": null,
    "worldwideTurnoverDeclared": null,
    "ratioPpm": "1004500",
    "percent": 100,
    "detail": "8500.00 EUR counted (earlier window 0.00) against 10000.00 EUR"
  },
  "timeZones": ["Europe/Zagreb"],
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z",
  "prerequisites": [
    {
      "code": "portal_access",
      "description": "Access to the tax portal of the member state of identification",
      "leadTimeDays": 7,
      "status": "done",
      "doneAt": "2026-10-13T12:00:00.000Z",
      "notes": "ePorezna access for the finance team",
      "owner": "Ana (finance)",
      "attachments": [],
      "updatedAt": "2026-10-13T12:00:00.000Z",
      "updatedBy": "usr_01m4tx5nj8emwbyf7y9vcf47xa"
    }
  ],
  "evidenceFiles": [],
  "history": [
    {
      "from": null,
      "to": "monitored",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "below_threshold",
      "note": null
    },
    {
      "from": "monitored",
      "to": "pre_registration",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "pre_registration_ratio_reached",
      "note": null
    }
  ],
  "counters": [
    {
      "windowKey": "2026",
      "amount": {
        "amount": "8500000000",
        "currency": "EUR"
      },
      "transactionCount": 412,
      "lastEventAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "regime": {
    "id": "EU_OSS_UNION",
    "name": "EU One-Stop Shop, Union scheme",
    "version": "3f2a9c41d07e88b1",
    "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
    "sellerEstablishment": "in_eu_other_ms",
    "customerType": "b2c",
    "threshold": {
      "amount": {
        "amount": "10000000000",
        "currency": "EUR"
      },
      "measure": "eu_cross_border_b2c",
      "window": "calendar_year_current_or_previous",
      "transactionCount": null,
      "whatCounts": "B2C electronically supplied services to consumers in other member states, net of VAT.",
      "amountInclusive": false
    },
    "zeroThreshold": false,
    "grace": {
      "rule": "nth_day_of_following_month",
      "days": null,
      "nthDay": 10
    },
    "collectBeforeRegistration": true,
    "b2bReverseChargeNoRegistration": true,
    "b2bChargeWhenRegistered": false,
    "requiresFiscalRepresentative": false,
    "requiresLocalAgent": false,
    "securityDeposit": null,
    "registration": {
      "method": "online",
      "portalUrl": "https://e-porezna.porezna-uprava.hr",
      "identityRequirements": null,
      "typicalProcessingDays": 7
    },
    "status": "verified",
    "unverified": false,
    "fixture": false,
    "validFrom": "2021-07-01",
    "validTo": null
  },
  "playbooks": [
    {
      "key": "EU/playbooks/EU_OSS_UNION-registration.md",
      "kind": "registration",
      "markdown": "# Registering for the Union OSS\n\n1. Sign in to the portal of your member state …"
    }
  ],
  "officialLinks": [
    {
      "label": "EU One-Stop Shop, Union scheme: registration portal",
      "url": "https://e-porezna.porezna-uprava.hr"
    }
  ],
  "actions": {
    "arm": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is grace, so \"arm\" isn't possible."
    },
    "markApplicationSubmitted": {
      "allowed": true,
      "code": null,
      "message": null
    },
    "markRegistered": {
      "allowed": true,
      "code": null,
      "message": null
    },
    "deregister": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is grace, so \"deregister\" isn't possible."
    }
  },
  "safetyBufferHours": 72,
  "knowledgeCommit": "1c14b2ec912aca347dd518b2044096f3b5d8eef1"
}
```

## `registrations_history`

**Get a registration's history.** Operation [`registrations.history`](https://ownrecord.io/docs/reference/registrations-history.md) · Legal entity level · permission `registrations:read` · risk tier `read` · since M7

Returns a registration's history as one timeline, newest first:

- `state`: every state change, who made it, why and the operator's note (also on the registration);
- `audit`: what the audit log recorded about the registration: prerequisite updates with what changed,
  uploaded documents, and actions not tied to a state change. An audit entry made with a state change is
  listed in that entry's `audited` instead of on its own;
- `event`: deadline escalations (`registration.deadline_escalated`), with the level reached.

Each source is read up to its 200 most recent entries (`truncated` says when one had more).

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

### Arguments

| Argument    | Type         | Required | Description                                                                                                                                       |
| ----------- | ------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`        | string       | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                      |
| `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` is neither a registration ID nor a regime ID.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration 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`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's registrations.

### Example

**Armed, in grace after the first sale, escalated, then submitted**

Arguments:

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

Result `output`:

```json
{
  "object": "registration_history",
  "registrationId": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "regimeId": "EU_OSS_NON_UNION",
  "data": [
    {
      "id": "state:2",
      "at": "2026-10-20T08:15:00.000Z",
      "source": "state",
      "type": "state_changed",
      "actor": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
      "state": {
        "from": "grace",
        "to": "grace",
        "reason": "application_submitted",
        "note": null
      },
      "changes": null,
      "escalation": null,
      "audited": ["registrations.mark_application_submitted"]
    },
    {
      "id": "aud_01m4tx5nj8emwbyf7y9vcf47xt",
      "at": "2026-10-20T08:14:02.000Z",
      "source": "audit",
      "type": "registrations.documents.upload",
      "actor": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
      "state": null,
      "changes": {
        "before": null,
        "after": {
          "fileId": "file_01m4tx5nj8emwbyf7y9vcf47xq",
          "filename": "oss-submission-receipt.pdf",
          "contentType": "application/pdf",
          "size": 82,
          "sha256": "36dc4d8396e18eff67cf01ca1121f420465e698179be0d927351dbe6ac07884d"
        }
      },
      "escalation": null,
      "audited": []
    },
    {
      "id": "evt_01m4tx5nj8emwbyf7y9vcf47xv",
      "at": "2026-10-18T07:07:00.000Z",
      "source": "event",
      "type": "registration.deadline_escalated",
      "actor": "system",
      "state": null,
      "changes": null,
      "escalation": {
        "level": 1,
        "deadlineAt": "2026-11-10T22:59:59.000Z"
      },
      "audited": []
    },
    {
      "id": "state:1",
      "at": "2026-10-14T09:30:00.000Z",
      "source": "state",
      "type": "state_changed",
      "actor": "system",
      "state": {
        "from": "blocked_b2c",
        "to": "grace",
        "reason": "first_sale_after_arming",
        "note": null
      },
      "changes": null,
      "escalation": null,
      "audited": []
    },
    {
      "id": "state:0",
      "at": "2026-10-13T12:00:00.000Z",
      "source": "state",
      "type": "state_changed",
      "actor": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
      "state": {
        "from": "blocked_b2c",
        "to": "blocked_b2c",
        "reason": "armed",
        "note": "Ana files by the 10th"
      },
      "changes": null,
      "escalation": null,
      "audited": ["registrations.arm"]
    }
  ],
  "truncated": false
}
```

## `registrations_list`

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

Lists the legal entity's registrations in the mode of the request, newest first: one per tax regime of the
tax knowledge (spec §10.8), created with the entity in both modes (test mode starts as a copy of live mode),
each in its state (`registered`, `grace`, `pre_registration`, `monitored`, `blocked_b2c`, …) with its
deadlines and threshold position. Filter by `state`.

Each registration has its `state` and `stateReason`, the grace `deadlineAt` and `autoBlockAt` (when new
consumer sales stop automatically unless the application is submitted), the prerequisites progress, and the
`threshold` position: what the entity sold toward the regime's threshold, all brands combined, with
`percent` of the threshold reached.

States: `registered`, `grace`, `monitored`, `pre_registration`, `blocked_b2c` (`armed: true` when the
first consumer sale will start the grace period), `not_applicable` and `deregistered`. Filter by `state`.
Paginate with `limit` (1–100, default 10) and `starting_after` (the `next_cursor` of the previous page).

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

### Arguments

| Argument         | Type                                                                                                                                                                                                                                      | Required | Description                                                                                                                                       |
| ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state`          | one of `not_applicable`, `monitored`, `pre_registration`, `grace`, `registered`, `blocked_b2c`, `deregistered` or array of one of `not_applicable`, `monitored`, `pre_registration`, `grace`, `registered`, `blocked_b2c`, `deregistered` | no       | Only registrations in this state (or these states).                                                                                               |
| `limit`          | integer                                                                                                                                                                                                                                   | no       | Page size, 1 to 100 (default 10). (1–100)                                                                                                         |
| `starting_after` | ID (`regn_…`)                                                                                                                                                                                                                             | 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 the page size is malformed (`details.issues`).
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't see this entity's registrations (brand-scoped members never can).

### Examples

**Registrations near or over a threshold**

Arguments:

```json
{
  "state": ["pre_registration", "grace"],
  "limit": 10,
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy"
}
```

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
      "object": "registration",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "livemode": true,
      "regimeId": "EU_OSS_UNION",
      "regimeName": "EU One-Stop Shop, Union scheme",
      "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
      "state": "pre_registration",
      "stateReason": "pre_registration_ratio_reached",
      "stateChangedAt": "2026-10-13T12:00:00.000Z",
      "armed": false,
      "triggeredAt": null,
      "deadlineAt": null,
      "autoBlockAt": null,
      "applicationSubmittedAt": null,
      "escalationLevel": 0,
      "registrationNumber": null,
      "effectiveFrom": null,
      "registeredAt": null,
      "prerequisitesDone": true,
      "prerequisitesProgress": {
        "done": 1,
        "total": 1
      },
      "threshold": {
        "status": "below",
        "window": "calendar_year_current_or_previous",
        "measure": "eu_cross_border_b2c",
        "currentWindow": "2026",
        "previousWindow": "2025",
        "threshold": {
          "amount": "10000000000",
          "currency": "EUR"
        },
        "current": {
          "amount": "8500000000",
          "currency": "EUR"
        },
        "previous": {
          "amount": "0",
          "currency": "EUR"
        },
        "transactionThreshold": null,
        "currentTransactions": null,
        "previousTransactions": null,
        "worldwideTurnoverDeclared": null,
        "ratioPpm": "850000",
        "percent": 85,
        "detail": "8500.00 EUR counted (earlier window 0.00) against 10000.00 EUR"
      },
      "timeZones": ["Europe/Zagreb"],
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

**Every registration, first page**

Arguments:

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

Result `output`:

```json
{
  "object": "list",
  "data": [
    {
      "id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
      "object": "registration",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "livemode": true,
      "regimeId": "EU_OSS_UNION",
      "regimeName": "EU One-Stop Shop, Union scheme",
      "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
      "state": "pre_registration",
      "stateReason": "pre_registration_ratio_reached",
      "stateChangedAt": "2026-10-13T12:00:00.000Z",
      "armed": false,
      "triggeredAt": null,
      "deadlineAt": null,
      "autoBlockAt": null,
      "applicationSubmittedAt": null,
      "escalationLevel": 0,
      "registrationNumber": null,
      "effectiveFrom": null,
      "registeredAt": null,
      "prerequisitesDone": true,
      "prerequisitesProgress": {
        "done": 1,
        "total": 1
      },
      "threshold": {
        "status": "below",
        "window": "calendar_year_current_or_previous",
        "measure": "eu_cross_border_b2c",
        "currentWindow": "2026",
        "previousWindow": "2025",
        "threshold": {
          "amount": "10000000000",
          "currency": "EUR"
        },
        "current": {
          "amount": "8500000000",
          "currency": "EUR"
        },
        "previous": {
          "amount": "0",
          "currency": "EUR"
        },
        "transactionThreshold": null,
        "currentTransactions": null,
        "previousTransactions": null,
        "worldwideTurnoverDeclared": null,
        "ratioPpm": "850000",
        "percent": 85,
        "detail": "8500.00 EUR counted (earlier window 0.00) against 10000.00 EUR"
      },
      "timeZones": ["Europe/Zagreb"],
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-13T12:00:00.000Z"
    },
    {
      "id": "regn_01m4tx5nj8emwbyf7y9vcf47xm",
      "object": "registration",
      "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
      "livemode": true,
      "regimeId": "HR_DOMESTIC",
      "regimeName": "Croatia, domestic VAT",
      "jurisdictionIds": ["HR"],
      "state": "registered",
      "stateReason": "home_country",
      "stateChangedAt": "2026-10-13T12:00:00.000Z",
      "armed": false,
      "triggeredAt": null,
      "deadlineAt": null,
      "autoBlockAt": null,
      "applicationSubmittedAt": null,
      "escalationLevel": 0,
      "registrationNumber": "HR12345678901",
      "effectiveFrom": null,
      "registeredAt": null,
      "prerequisitesDone": false,
      "prerequisitesProgress": {
        "done": 0,
        "total": 2
      },
      "threshold": null,
      "timeZones": ["Europe/Zagreb"],
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "has_more": true,
  "next_cursor": "regn_01m4tx5nj8emwbyf7y9vcf47xm"
}
```

## `registrations_mark_application_submitted`

**Mark a registration application submitted.** Operation [`registrations.mark_application_submitted`](https://ownrecord.io/docs/reference/registrations-mark-application-submitted.md) · Legal entity level · permission `registrations:write` · risk tier `compliance` · since M3

Records that the registration application for a regime in grace was filed with the tax authority, with
proof (the submission receipt). The deadline is then satisfied: no more escalations, and new consumer sales
are not stopped automatically while the registration number is awaited (spec §10.2). Mark it registered
when the number arrives.

Needs `grace`, once. `proof` lists at least one document of the receipt: a file uploaded to the
registration (`registrations.documents.upload`, then its `file_…` ID), the authority's receipt or
application number, or a link to the document in your own storage.

Compliance tier (spec §41.4): tax managers, owners and admins. If the organization's approval policy lists
this operation, the call answers `approval_required` and runs once a second person approves it.
Returns the registration.

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

### Arguments

| Argument          | Type            | Required | Description                                                                                                                                                                                              |
| ----------------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | string          | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                                                                             |
| `proof`           | array of object | yes      | Proof: at least one document (uploaded `file_…` or a reference) of the submission receipt or the registration confirmation. (1–10 items)                                                                 |
| `note`            | string          | no       | Why, or anything the team should know; kept in the registration's history and the audit log. (1–1000 characters)                                                                                         |
| `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

- [`registration_transition_invalid`](https://ownrecord.io/docs/reference/errors.md#registration_transition_invalid): The registration isn't in `grace`, or the application is already marked submitted.
- [`registration_details_invalid`](https://ownrecord.io/docs/reference/errors.md#registration_details_invalid): No proof was given (`param`: `proof`).
- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is malformed, or a `file_…` proof isn't a document of this registration (`param`: `proof.0.reference`).
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration in this mode.
- [`jurisdiction_blocked`](https://ownrecord.io/docs/reference/errors.md#jurisdiction_blocked): The tax knowledge no longer has a usable regime for this registration, so it can't change now.
- [`approval_required`](https://ownrecord.io/docs/reference/errors.md#approval_required): The organization's approval policy needs a second person for this action; nothing changed yet.
- [`approval_rejected`](https://ownrecord.io/docs/reference/errors.md#approval_rejected): The same request was sent again after it was rejected.
- [`approval_expired`](https://ownrecord.io/docs/reference/errors.md#approval_expired): The same request was sent again after its approval request expired.
- [`stale_approval`](https://ownrecord.io/docs/reference/errors.md#stale_approval): The approved request could no longer run as requested.
- [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused): The idempotency key was used before with another input.
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't change live registrations.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this entity's registrations (tax managers, owners and admins can).
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The registration changed at the same moment (a sale or the deadline job); reload and retry.

### Example

**The OSS application was filed**

Arguments:

```json
{
  "id": "EU_OSS_UNION",
  "proof": [
    {
      "reference": "ePorezna receipt 2026-OSS-118274",
      "label": "Submission receipt"
    }
  ],
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "object": "registration",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "regimeId": "EU_OSS_UNION",
  "regimeName": "EU One-Stop Shop, Union scheme",
  "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
  "state": "grace",
  "stateReason": "application_submitted",
  "stateChangedAt": "2026-10-20T08:15:00.000Z",
  "armed": false,
  "triggeredAt": "2026-10-14T09:30:00.000Z",
  "deadlineAt": "2026-11-10T22:59:59.000Z",
  "autoBlockAt": null,
  "applicationSubmittedAt": "2026-10-20T08:15:00.000Z",
  "escalationLevel": 0,
  "registrationNumber": null,
  "effectiveFrom": null,
  "registeredAt": null,
  "prerequisitesDone": true,
  "prerequisitesProgress": {
    "done": 1,
    "total": 1
  },
  "threshold": {
    "status": "over",
    "window": "calendar_year_current_or_previous",
    "measure": "eu_cross_border_b2c",
    "currentWindow": "2026",
    "previousWindow": "2025",
    "threshold": {
      "amount": "10000000000",
      "currency": "EUR"
    },
    "current": {
      "amount": "8500000000",
      "currency": "EUR"
    },
    "previous": {
      "amount": "0",
      "currency": "EUR"
    },
    "transactionThreshold": null,
    "currentTransactions": null,
    "previousTransactions": null,
    "worldwideTurnoverDeclared": null,
    "ratioPpm": "1004500",
    "percent": 100,
    "detail": "8500.00 EUR counted (earlier window 0.00) against 10000.00 EUR"
  },
  "timeZones": ["Europe/Zagreb"],
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-20T08:15:00.000Z",
  "prerequisites": [
    {
      "code": "portal_access",
      "description": "Access to the tax portal of the member state of identification",
      "leadTimeDays": 7,
      "status": "done",
      "doneAt": "2026-10-13T12:00:00.000Z",
      "notes": "ePorezna access for the finance team",
      "owner": "Ana (finance)",
      "attachments": [],
      "updatedAt": "2026-10-13T12:00:00.000Z",
      "updatedBy": "usr_01m4tx5nj8emwbyf7y9vcf47xa"
    }
  ],
  "evidenceFiles": [
    {
      "kind": "reference",
      "ref": "ePorezna receipt 2026-OSS-118274",
      "label": "Submission receipt",
      "addedAt": "2026-10-20T08:15:00.000Z",
      "addedBy": "usr_01m4tx5nj8emwbyf7y9vcf47xa"
    }
  ],
  "history": [
    {
      "from": null,
      "to": "monitored",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "below_threshold",
      "note": null
    },
    {
      "from": "monitored",
      "to": "pre_registration",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "pre_registration_ratio_reached",
      "note": null
    },
    {
      "from": "pre_registration",
      "to": "grace",
      "at": "2026-10-14T09:30:00.000Z",
      "by": "system",
      "reason": "threshold_crossed",
      "note": null
    },
    {
      "from": "grace",
      "to": "grace",
      "at": "2026-10-20T08:15:00.000Z",
      "by": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
      "reason": "application_submitted",
      "note": null
    }
  ],
  "counters": [
    {
      "windowKey": "2026",
      "amount": {
        "amount": "8500000000",
        "currency": "EUR"
      },
      "transactionCount": 412,
      "lastEventAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "regime": {
    "id": "EU_OSS_UNION",
    "name": "EU One-Stop Shop, Union scheme",
    "version": "3f2a9c41d07e88b1",
    "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
    "sellerEstablishment": "in_eu_other_ms",
    "customerType": "b2c",
    "threshold": {
      "amount": {
        "amount": "10000000000",
        "currency": "EUR"
      },
      "measure": "eu_cross_border_b2c",
      "window": "calendar_year_current_or_previous",
      "transactionCount": null,
      "whatCounts": "B2C electronically supplied services to consumers in other member states, net of VAT.",
      "amountInclusive": false
    },
    "zeroThreshold": false,
    "grace": {
      "rule": "nth_day_of_following_month",
      "days": null,
      "nthDay": 10
    },
    "collectBeforeRegistration": true,
    "b2bReverseChargeNoRegistration": true,
    "b2bChargeWhenRegistered": false,
    "requiresFiscalRepresentative": false,
    "requiresLocalAgent": false,
    "securityDeposit": null,
    "registration": {
      "method": "online",
      "portalUrl": "https://e-porezna.porezna-uprava.hr",
      "identityRequirements": null,
      "typicalProcessingDays": 7
    },
    "status": "verified",
    "unverified": false,
    "fixture": false,
    "validFrom": "2021-07-01",
    "validTo": null
  },
  "playbooks": [
    {
      "key": "EU/playbooks/EU_OSS_UNION-registration.md",
      "kind": "registration",
      "markdown": "# Registering for the Union OSS\n\n1. Sign in to the portal of your member state …"
    }
  ],
  "officialLinks": [
    {
      "label": "EU One-Stop Shop, Union scheme: registration portal",
      "url": "https://e-porezna.porezna-uprava.hr"
    }
  ],
  "actions": {
    "arm": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is grace, so \"arm\" isn't possible."
    },
    "markApplicationSubmitted": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "The application for EU_OSS_UNION is already marked submitted (2026-10-20T08:15:00.000Z)."
    },
    "markRegistered": {
      "allowed": true,
      "code": null,
      "message": null
    },
    "deregister": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is grace, so \"deregister\" isn't possible."
    }
  },
  "safetyBufferHours": 72,
  "knowledgeCommit": "1c14b2ec912aca347dd518b2044096f3b5d8eef1"
}
```

## `registrations_mark_registered`

**Mark a jurisdiction registered.** Operation [`registrations.mark_registered`](https://ownrecord.io/docs/reference/registrations-mark-registered.md) · Legal entity level · permission `registrations:write` · risk tier `compliance` · since M3

Records the registration the tax authority confirmed: its `registrationNumber`, the date it is
`effectiveFrom` (YYYY-MM-DD, from the start of that day in the jurisdiction's time zone) and `proof` (at least
one document of the confirmation: a file uploaded to the registration, as its `file_…` ID, or a reference).
The registration becomes `registered`: consumer sales there are charged tax as registered (spec §10.1). For
US states, nothing is collected before `effectiveFrom`. Tax collected while the registration was pending
(`tax_pending_registration`) moves to `tax_payable` in the same transaction, per jurisdiction and currency
(ledger kind `tax_transfer`, linked to the registration; spec §11.3).

Works from `grace`, `blocked_b2c` (armed or not), `monitored`, `pre_registration` and `deregistered`
(registering early is the point of pre-registration); not from `registered` or `not_applicable`.

Compliance tier (spec §41.4): tax managers, owners and admins. If the organization's approval policy lists
this operation, the call answers `approval_required` and runs once a second person approves it.
People need a sign-in within the last 15 minutes (spec §3.1). Returns the registration.

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

### Arguments

| Argument             | Type            | Required | Description                                                                                                                                                                                              |
| -------------------- | --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`                 | string          | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                                                                             |
| `registrationNumber` | string          | yes      | The registration number the tax authority issued. (1–100 characters)                                                                                                                                     |
| `effectiveFrom`      | string          | yes      | The first day the registration is effective (YYYY-MM-DD), in the jurisdiction's time zone.                                                                                                               |
| `proof`              | array of object | yes      | Proof: at least one document (uploaded `file_…` or a reference) of the submission receipt or the registration confirmation. (1–10 items)                                                                 |
| `note`               | string          | no       | Why, or anything the team should know; kept in the registration's history and the audit log. (1–1000 characters)                                                                                         |
| `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

- [`registration_transition_invalid`](https://ownrecord.io/docs/reference/errors.md#registration_transition_invalid): The registration is `registered` or `not_applicable` (`details.allowed_from`).
- [`registration_details_invalid`](https://ownrecord.io/docs/reference/errors.md#registration_details_invalid): The number, the effective date or the proof is missing (`param` names it).
- [`fresh_auth_required`](https://ownrecord.io/docs/reference/errors.md#fresh_auth_required): Your last sign-in is older than 15 minutes.
- [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed): A field is malformed, or a `file_…` proof isn't a document of this registration (`param`: `proof.0.reference`).
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration in this mode.
- [`jurisdiction_blocked`](https://ownrecord.io/docs/reference/errors.md#jurisdiction_blocked): The tax knowledge no longer has a usable regime for this registration, so it can't change now.
- [`approval_required`](https://ownrecord.io/docs/reference/errors.md#approval_required): The organization's approval policy needs a second person for this action; nothing changed yet.
- [`approval_rejected`](https://ownrecord.io/docs/reference/errors.md#approval_rejected): The same request was sent again after it was rejected.
- [`approval_expired`](https://ownrecord.io/docs/reference/errors.md#approval_expired): The same request was sent again after its approval request expired.
- [`stale_approval`](https://ownrecord.io/docs/reference/errors.md#stale_approval): The approved request could no longer run as requested.
- [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused): The idempotency key was used before with another input.
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't change live registrations.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this entity's registrations (tax managers, owners and admins can).
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The registration changed at the same moment (a sale or the deadline job); reload and retry.

### Example

**The OSS registration was confirmed**

Arguments:

```json
{
  "id": "EU_OSS_UNION",
  "registrationNumber": "HR12345678901",
  "effectiveFrom": "2026-11-01",
  "proof": [
    {
      "reference": "https://docs.example.com/oss-confirmation.pdf",
      "label": "Confirmation letter"
    }
  ],
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "object": "registration",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "regimeId": "EU_OSS_UNION",
  "regimeName": "EU One-Stop Shop, Union scheme",
  "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
  "state": "registered",
  "stateReason": "registered",
  "stateChangedAt": "2026-10-14T09:30:00.000Z",
  "armed": false,
  "triggeredAt": null,
  "deadlineAt": null,
  "autoBlockAt": null,
  "applicationSubmittedAt": null,
  "escalationLevel": 0,
  "registrationNumber": "HR12345678901",
  "effectiveFrom": "2026-10-31T23:00:00.000Z",
  "registeredAt": "2026-10-14T09:30:00.000Z",
  "prerequisitesDone": true,
  "prerequisitesProgress": {
    "done": 1,
    "total": 1
  },
  "threshold": {
    "status": "below",
    "window": "calendar_year_current_or_previous",
    "measure": "eu_cross_border_b2c",
    "currentWindow": "2026",
    "previousWindow": "2025",
    "threshold": {
      "amount": "10000000000",
      "currency": "EUR"
    },
    "current": {
      "amount": "8500000000",
      "currency": "EUR"
    },
    "previous": {
      "amount": "0",
      "currency": "EUR"
    },
    "transactionThreshold": null,
    "currentTransactions": null,
    "previousTransactions": null,
    "worldwideTurnoverDeclared": null,
    "ratioPpm": "850000",
    "percent": 85,
    "detail": "8500.00 EUR counted (earlier window 0.00) against 10000.00 EUR"
  },
  "timeZones": ["Europe/Zagreb"],
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-14T09:30:00.000Z",
  "prerequisites": [
    {
      "code": "portal_access",
      "description": "Access to the tax portal of the member state of identification",
      "leadTimeDays": 7,
      "status": "done",
      "doneAt": "2026-10-13T12:00:00.000Z",
      "notes": "ePorezna access for the finance team",
      "owner": "Ana (finance)",
      "attachments": [],
      "updatedAt": "2026-10-13T12:00:00.000Z",
      "updatedBy": "usr_01m4tx5nj8emwbyf7y9vcf47xa"
    }
  ],
  "evidenceFiles": [
    {
      "kind": "reference",
      "ref": "https://docs.example.com/oss-confirmation.pdf",
      "label": "Confirmation letter",
      "addedAt": "2026-10-14T09:30:00.000Z",
      "addedBy": "usr_01m4tx5nj8emwbyf7y9vcf47xa"
    }
  ],
  "history": [
    {
      "from": null,
      "to": "monitored",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "below_threshold",
      "note": null
    },
    {
      "from": "monitored",
      "to": "pre_registration",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "pre_registration_ratio_reached",
      "note": null
    }
  ],
  "counters": [
    {
      "windowKey": "2026",
      "amount": {
        "amount": "8500000000",
        "currency": "EUR"
      },
      "transactionCount": 412,
      "lastEventAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "regime": {
    "id": "EU_OSS_UNION",
    "name": "EU One-Stop Shop, Union scheme",
    "version": "3f2a9c41d07e88b1",
    "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
    "sellerEstablishment": "in_eu_other_ms",
    "customerType": "b2c",
    "threshold": {
      "amount": {
        "amount": "10000000000",
        "currency": "EUR"
      },
      "measure": "eu_cross_border_b2c",
      "window": "calendar_year_current_or_previous",
      "transactionCount": null,
      "whatCounts": "B2C electronically supplied services to consumers in other member states, net of VAT.",
      "amountInclusive": false
    },
    "zeroThreshold": false,
    "grace": {
      "rule": "nth_day_of_following_month",
      "days": null,
      "nthDay": 10
    },
    "collectBeforeRegistration": true,
    "b2bReverseChargeNoRegistration": true,
    "b2bChargeWhenRegistered": false,
    "requiresFiscalRepresentative": false,
    "requiresLocalAgent": false,
    "securityDeposit": null,
    "registration": {
      "method": "online",
      "portalUrl": "https://e-porezna.porezna-uprava.hr",
      "identityRequirements": null,
      "typicalProcessingDays": 7
    },
    "status": "verified",
    "unverified": false,
    "fixture": false,
    "validFrom": "2021-07-01",
    "validTo": null
  },
  "playbooks": [
    {
      "key": "EU/playbooks/EU_OSS_UNION-registration.md",
      "kind": "registration",
      "markdown": "# Registering for the Union OSS\n\n1. Sign in to the portal of your member state …"
    }
  ],
  "officialLinks": [
    {
      "label": "EU One-Stop Shop, Union scheme: registration portal",
      "url": "https://e-porezna.porezna-uprava.hr"
    }
  ],
  "actions": {
    "arm": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is registered, so \"arm\" isn't possible."
    },
    "markApplicationSubmitted": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is registered, so \"application_submitted\" isn't possible."
    },
    "markRegistered": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is registered, so \"mark_registered\" isn't possible."
    },
    "deregister": {
      "allowed": true,
      "code": null,
      "message": null
    }
  },
  "safetyBufferHours": 72,
  "knowledgeCommit": "1c14b2ec912aca347dd518b2044096f3b5d8eef1"
}
```

## `registrations_update_prerequisite`

**Update a registration prerequisite.** Operation [`registrations.update_prerequisite`](https://ownrecord.io/docs/reference/registrations-update-prerequisite.md) · Legal entity level · permission `registrations:write` · risk tier `write` · since M3

Updates one prerequisite of a registration (portal access, a fiscal representative, documents …): its
`status` (`todo`, `in_progress`, `done`), `notes`, `owner` (who on the team looks after it) and
`attachments` (documents, added to the list: files uploaded with `registrations.documents.upload`, by their
`file_…` ID, or references such as a receipt number or a link). The registration lists its prerequisites
with their codes, descriptions and lead times (`registrations.get`).

Grace periods and arming need every prerequisite `done` (spec §10.2): a sale that crosses a threshold while one
is open blocks consumer sales instead of starting the grace period. Reopening a prerequisite of an armed
jurisdiction keeps it armed, but its next sale then blocks.

Write tier: tax managers, owners and admins. Returns the registration.

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

### Arguments

| Argument          | Type                                 | Required | Description                                                                                                                                                                                              |
| ----------------- | ------------------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`              | string                               | yes      | The registration (`regn_…`) or its regime's ID, e.g. `EU_OSS_UNION` or `US_SALES_TAX:TX`. (1–110 characters)                                                                                             |
| `code`            | string                               | yes      | The prerequisite's code, e.g. `portal_access` (the registration lists them). (1–100 characters)                                                                                                          |
| `status`          | one of `todo`, `in_progress`, `done` | no       | `todo`, `in_progress` or `done`.                                                                                                                                                                         |
| `notes`           | string                               | no       | Replaces the notes (empty clears them). (at most 2000 characters)                                                                                                                                        |
| `owner`           | string or null                       | no       | Who on the team looks after it (a name); null clears it.                                                                                                                                                 |
| `attachments`     | array of object                      | no       | Documents to add: files uploaded to the registration (`file_…`), or references (receipt numbers, links). (1–20 items)                                                                                    |
| `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): The registration has no prerequisite with this `code`, nothing would change, a prerequisite would keep more than 20 attachments, or a `file_…` attachment isn't a document of this registration.
- [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found): This entity has no such registration in this mode.
- [`jurisdiction_blocked`](https://ownrecord.io/docs/reference/errors.md#jurisdiction_blocked): The tax knowledge no longer has a usable regime for this registration, so it can't change now.
- [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused): The idempotency key was used before with another input.
- [`livemode_not_allowed`](https://ownrecord.io/docs/reference/errors.md#livemode_not_allowed): You have no live-mode access, so you can't change live registrations.
- [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required): The request names no legal entity (an org key without `Ownrecord-Entity`).
- [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied): You can't change this entity's registrations (tax managers, owners and admins can).
- [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict): The registration changed at the same moment (a sale or the deadline job); reload and retry.

### Example

**Portal access is done**

Arguments:

```json
{
  "id": "EU_OSS_UNION",
  "code": "portal_access",
  "status": "done",
  "owner": "Ana (finance)",
  "notes": "ePorezna access for the finance team",
  "entity_id": "ent_01jbx4m3v8e9t0s6k2c5n7q1wy",
  "idempotency_key": "8d0c5f8e-4b7a-4e43-9b0f-2f6a0c1d9e21"
}
```

Result `output`:

```json
{
  "id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
  "object": "registration",
  "entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
  "livemode": true,
  "regimeId": "EU_OSS_UNION",
  "regimeName": "EU One-Stop Shop, Union scheme",
  "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
  "state": "pre_registration",
  "stateReason": "pre_registration_ratio_reached",
  "stateChangedAt": "2026-10-13T12:00:00.000Z",
  "armed": false,
  "triggeredAt": null,
  "deadlineAt": null,
  "autoBlockAt": null,
  "applicationSubmittedAt": null,
  "escalationLevel": 0,
  "registrationNumber": null,
  "effectiveFrom": null,
  "registeredAt": null,
  "prerequisitesDone": true,
  "prerequisitesProgress": {
    "done": 1,
    "total": 1
  },
  "threshold": {
    "status": "below",
    "window": "calendar_year_current_or_previous",
    "measure": "eu_cross_border_b2c",
    "currentWindow": "2026",
    "previousWindow": "2025",
    "threshold": {
      "amount": "10000000000",
      "currency": "EUR"
    },
    "current": {
      "amount": "8500000000",
      "currency": "EUR"
    },
    "previous": {
      "amount": "0",
      "currency": "EUR"
    },
    "transactionThreshold": null,
    "currentTransactions": null,
    "previousTransactions": null,
    "worldwideTurnoverDeclared": null,
    "ratioPpm": "850000",
    "percent": 85,
    "detail": "8500.00 EUR counted (earlier window 0.00) against 10000.00 EUR"
  },
  "timeZones": ["Europe/Zagreb"],
  "createdAt": "2026-10-13T12:00:00.000Z",
  "updatedAt": "2026-10-13T12:00:00.000Z",
  "prerequisites": [
    {
      "code": "portal_access",
      "description": "Access to the tax portal of the member state of identification",
      "leadTimeDays": 7,
      "status": "done",
      "doneAt": "2026-10-13T12:00:00.000Z",
      "notes": "ePorezna access for the finance team",
      "owner": "Ana (finance)",
      "attachments": [],
      "updatedAt": "2026-10-13T12:00:00.000Z",
      "updatedBy": "usr_01m4tx5nj8emwbyf7y9vcf47xa"
    }
  ],
  "evidenceFiles": [],
  "history": [
    {
      "from": null,
      "to": "monitored",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "below_threshold",
      "note": null
    },
    {
      "from": "monitored",
      "to": "pre_registration",
      "at": "2026-10-13T12:00:00.000Z",
      "by": "system",
      "reason": "pre_registration_ratio_reached",
      "note": null
    }
  ],
  "counters": [
    {
      "windowKey": "2026",
      "amount": {
        "amount": "8500000000",
        "currency": "EUR"
      },
      "transactionCount": 412,
      "lastEventAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "regime": {
    "id": "EU_OSS_UNION",
    "name": "EU One-Stop Shop, Union scheme",
    "version": "3f2a9c41d07e88b1",
    "jurisdictionIds": ["AT", "DE", "FR", "HR", "IT", "NL"],
    "sellerEstablishment": "in_eu_other_ms",
    "customerType": "b2c",
    "threshold": {
      "amount": {
        "amount": "10000000000",
        "currency": "EUR"
      },
      "measure": "eu_cross_border_b2c",
      "window": "calendar_year_current_or_previous",
      "transactionCount": null,
      "whatCounts": "B2C electronically supplied services to consumers in other member states, net of VAT.",
      "amountInclusive": false
    },
    "zeroThreshold": false,
    "grace": {
      "rule": "nth_day_of_following_month",
      "days": null,
      "nthDay": 10
    },
    "collectBeforeRegistration": true,
    "b2bReverseChargeNoRegistration": true,
    "b2bChargeWhenRegistered": false,
    "requiresFiscalRepresentative": false,
    "requiresLocalAgent": false,
    "securityDeposit": null,
    "registration": {
      "method": "online",
      "portalUrl": "https://e-porezna.porezna-uprava.hr",
      "identityRequirements": null,
      "typicalProcessingDays": 7
    },
    "status": "verified",
    "unverified": false,
    "fixture": false,
    "validFrom": "2021-07-01",
    "validTo": null
  },
  "playbooks": [
    {
      "key": "EU/playbooks/EU_OSS_UNION-registration.md",
      "kind": "registration",
      "markdown": "# Registering for the Union OSS\n\n1. Sign in to the portal of your member state …"
    }
  ],
  "officialLinks": [
    {
      "label": "EU One-Stop Shop, Union scheme: registration portal",
      "url": "https://e-porezna.porezna-uprava.hr"
    }
  ],
  "actions": {
    "arm": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"arm\" isn't possible."
    },
    "markApplicationSubmitted": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"application_submitted\" isn't possible."
    },
    "markRegistered": {
      "allowed": true,
      "code": null,
      "message": null
    },
    "deregister": {
      "allowed": false,
      "code": "registration_transition_invalid",
      "message": "EU_OSS_UNION is pre_registration, so \"deregister\" isn't possible."
    }
  },
  "safetyBufferHours": 72,
  "knowledgeCommit": "1c14b2ec912aca347dd518b2044096f3b5d8eef1"
}
```
