Mark a jurisdiction registered
The registrations.mark_registered operation: POST /api/v1/registrations/{id}/mark_registered in the REST API and the registrations_mark_registered tool in the MCP server.
/api/v1/registrations/{id}/mark_registeredRecords 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.
At a glance
- REST:
POST /api/v1/registrations/{id}/mark_registered - MCP tool:
registrations_mark_registered - Operation ID:
registrations.mark_registered - Scope: Legal entity
- Permission:
registrations:write - Risk tier:
compliance - Dry run: Supported (send
Ownrecord-Dry-Run: true) - Idempotency:
Idempotency-Keyrequired - Modes: Test and live
- Authentication: API key with the
registrations:writescope - Fresh sign-in: In the console, a sign-in within the last 15 minutes
- 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. |
Body
A JSON object (Content-Type: application/json):
| Field | Type | Required | Description |
|---|---|---|---|
registrationNumber | string | Yes | The registration number the tax authority issued. |
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. |
proof[].reference | string | Yes | A document uploaded to this registration (file_…), or the authority's receipt or application number, or a link to the document. |
proof[].label | string | No | What the document is, e.g. OSS registration confirmation. |
note | string | No | Why, or anything the team should know; kept in the registration's history and the audit log. |
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
The OSS registration was confirmed
POST /api/v1/registrations/EU_OSS_UNION/mark_registered
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json
{
"registrationNumber": "HR12345678901",
"effectiveFrom": "2026-11-01",
"proof": [
{
"reference": "https://docs.example.com/oss-confirmation.pdf",
"label": "Confirmation letter"
}
]
}
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": "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"
}
Errors
| Code | HTTP status | When | What to do |
|---|---|---|---|
registration_transition_invalid | 409 | The registration is registered or not_applicable (details.allowed_from). | Check the registration's state (details.state): details.allowed_from lists the states the action needs. Reload the registration and try the action that fits its state. |
registration_details_invalid | 400 | The number, the effective date or the proof is missing (param names it). | Fill in the field named in param: the registration number, the date it is effective from, or at least one proof file. |
fresh_auth_required | 403 | Your last sign-in is older than 15 minutes. | Sign in again, then repeat the action within 15 minutes. |
validation_failed | 400 | A field is malformed, or a file_… proof isn't a document of this registration (param: proof.0.reference). | 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. |
approval_required | 202 | The organization's approval policy needs a second person for this action; nothing changed yet. | Nothing ran yet. An approver reviews approval.summary and the dry-run result in the console (approval.approveUrl). Poll GET /approvals/{id} or watch for the approval.resolved event; sending the same request again with the same Idempotency-Key returns the same approval. |
approval_rejected | 409 | The same request was sent again after it was rejected. | Read the reason in details.approval.rejection. To try again, send a new request with a new Idempotency-Key. |
approval_expired | 409 | The same request was sent again after its approval request expired. | Send the request again with a new Idempotency-Key to create a new approval request. Requests expire after 72 hours. |
stale_approval | 409 | The approved request could no longer run as requested. | Check the current state (details.approval.failure says what failed), then send a new request with a new Idempotency-Key. |
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_key_required, idempotency_in_progress, approval_policy_denied, rate_limited, internal_error.