Update a registration prerequisite
The registrations.update_prerequisite operation: PATCH /api/v1/registrations/{id}/prerequisites/{code} in the REST API and the registrations_update_prerequisite tool in the MCP server.
/api/v1/registrations/{id}/prerequisites/{code}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.
At a glance
- REST:
PATCH /api/v1/registrations/{id}/prerequisites/{code} - MCP tool:
registrations_update_prerequisite - Operation ID:
registrations.update_prerequisite - Scope: Legal entity
- Permission:
registrations:write - Risk tier:
write - Dry run: Supported (send
Ownrecord-Dry-Run: true) - Idempotency:
Idempotency-Keyoptional - Modes: Test and live
- Authentication: API key with the
registrations:writescope - Since: M3
Request
Path parameters
| Field | Type | Description |
|---|---|---|
id | string | The registration (regn_…) or its regime's ID, e.g. EU_OSS_UNION or US_SALES_TAX:TX. |
code | string | The prerequisite's code, e.g. portal_access (the registration lists them). |
Body
A JSON object (Content-Type: application/json):
| Field | Type | Required | Description |
|---|---|---|---|
status | one of todo, in_progress, done | No | todo, in_progress or done. |
notes | string | No | Replaces the notes (empty clears them). |
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). |
attachments[].reference | string | Yes | A document uploaded to this registration (file_…), or the authority's receipt or application number, or a link to the document. |
attachments[].label | string | No | What the document is, e.g. OSS registration confirmation. |
Response
200 OK with a JSON object:
| Field | Type | Description |
|---|---|---|
id | regn_… ID | |
object | "registration" | |
entityId | ent_… ID | |
livemode | boolean | |
regimeId | string | |
regimeName | string or null | |
jurisdictionIds | array of string | |
state | one of not_applicable, monitored, pre_registration, grace, registered, blocked_b2c, deregistered | |
stateReason | one of 18 values, e.g. home_country, below_threshold, zero_threshold (all in the OpenAPI document) | |
stateChangedAt | date-time | |
armed | boolean | |
triggeredAt | date-time or null | |
deadlineAt | date-time or null | |
autoBlockAt | date-time or null | |
applicationSubmittedAt | date-time or null | |
escalationLevel | integer (0 to 3) | |
registrationNumber | string or null | |
effectiveFrom | date-time or null | |
registeredAt | date-time or null | |
prerequisitesDone | boolean | |
prerequisitesProgress | object | |
prerequisitesProgress.done | integer | |
prerequisitesProgress.total | integer | |
threshold | object or null | |
timeZones | array of string | |
createdAt | date-time | |
updatedAt | date-time | |
prerequisites | array of object | |
prerequisites[].code | string | |
prerequisites[].description | string or null | |
prerequisites[].leadTimeDays | integer or null | |
prerequisites[].status | one of todo, in_progress, done | |
prerequisites[].doneAt | date-time or null | |
prerequisites[].notes | string | |
prerequisites[].owner | string or null | |
prerequisites[].attachments | array of object | |
prerequisites[].attachments[].kind | one of file, reference | |
prerequisites[].attachments[].ref | string | |
prerequisites[].attachments[].label | string or null | |
prerequisites[].attachments[].addedAt | date-time | |
prerequisites[].attachments[].addedBy | string | |
prerequisites[].updatedAt | date-time or null | |
prerequisites[].updatedBy | string or null | |
evidenceFiles | array of object | |
evidenceFiles[].kind | one of file, reference | |
evidenceFiles[].ref | string | |
evidenceFiles[].label | string or null | |
evidenceFiles[].addedAt | date-time | |
evidenceFiles[].addedBy | string | |
history | array of object | |
history[].from | one of not_applicable, monitored, pre_registration, grace, registered, blocked_b2c, deregistered or null | |
history[].to | one of not_applicable, monitored, pre_registration, grace, registered, blocked_b2c, deregistered | |
history[].at | date-time | |
history[].by | string | |
history[].reason | one of 18 values, e.g. home_country, below_threshold, zero_threshold (all in the OpenAPI document) | |
history[].note | string or null | |
counters | array of object | |
counters[].windowKey | string | |
counters[].amount | money | |
counters[].transactionCount | integer | |
counters[].lastEventAt | date-time | |
regime | object or null | |
playbooks | array of object | |
playbooks[].key | string | |
playbooks[].kind | one of registration, filing, deregistration, other | |
playbooks[].markdown | string | |
officialLinks | array of object | |
officialLinks[].label | string | |
officialLinks[].url | string | |
actions | object | |
actions.arm | object | |
actions.arm.allowed | boolean | |
actions.arm.code | string or null | |
actions.arm.message | string or null | |
actions.markApplicationSubmitted | object | |
actions.markApplicationSubmitted.allowed | boolean | |
actions.markApplicationSubmitted.code | string or null | |
actions.markApplicationSubmitted.message | string or null | |
actions.markRegistered | object | |
actions.markRegistered.allowed | boolean | |
actions.markRegistered.code | string or null | |
actions.markRegistered.message | string or null | |
actions.deregister | object | |
actions.deregister.allowed | boolean | |
actions.deregister.code | string or null | |
actions.deregister.message | string or null | |
safetyBufferHours | integer | |
knowledgeCommit | string |
Examples
Portal access is done
PATCH /api/v1/registrations/EU_OSS_UNION/prerequisites/portal_access
Authorization: Bearer or_test_…
Content-Type: application/json
{
"status": "done",
"owner": "Ana (finance)",
"notes": "ePorezna access for the finance team"
}
Response (200):
{
"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"
}
Errors
| Code | HTTP status | When | What to do |
|---|---|---|---|
validation_failed | 400 | 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. | Fix the fields listed in details.issues and send the request again. |
resource_not_found | 404 | This entity has no such registration in this mode. | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode. |
jurisdiction_blocked | 422 | The tax knowledge no longer has a usable regime for this registration, so it can't change now. | This jurisdiction isn't covered by usable tax knowledge for this seller. Contact support if you need to sell there. |
idempotency_key_reused | 409 | The idempotency key was used before with another input. | Use a new Idempotency-Key for a different request, or resend the original request unchanged. |
livemode_not_allowed | 403 | You have no live-mode access, so you can't change live registrations. | Use test mode, or credentials for the target's mode. Developers need live access granted by an organization owner or admin. |
scope_required | 400 | The request names no legal entity (an org key without Ownrecord-Entity). | Call the operation with credentials or a target at its level: an organization, a legal entity, a brand or the platform (details.required_scope). |
permission_denied | 403 | You can't change this entity's registrations (tax managers, owners and admins can). | Ask an organization owner or admin for a role or scope that allows this action. |
version_conflict | 409 | The registration changed at the same moment (a sale or the deadline job); reload and retry. | Fetch the object again and retry the change. |
It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.