Lock a filing period
The filing_periods.lock operation: POST /api/v1/filing_periods/{id}/lock in the REST API and the filing_periods_lock tool in the MCP server.
/api/v1/filing_periods/{id}/lockLocks a filing period that is over (spec §21.1): the first step of a return. The period's documents are
complete, so its report can be generated (filing_periods.prepare). A refund or credit note issued later is
dated when it is issued and goes into a later return as a correction of this period (spec §9.6).
Works on an open period from its lockableAt on (its end). Compliance tier (spec §41.4): tax managers,
finance, owners and admins; an agent's call needs approval under the default policy. Returns the period.
At a glance
- REST:
POST /api/v1/filing_periods/{id}/lock - MCP tool:
filing_periods_lock - Operation ID:
filing_periods.lock - Scope: Legal entity
- Permission:
filings:write - Risk tier:
compliance - Dry run: Supported (send
Ownrecord-Dry-Run: true) - Idempotency:
Idempotency-Keyrequired - Modes: Test and live
- Authentication: API key with the
filings:writescope - Since: M8
Request
Path parameters
| Field | Type | Description |
|---|---|---|
id | fp_… ID | The filing period (fp_…). |
Body
A JSON object (Content-Type: application/json):
| Field | Type | Required | Description |
|---|---|---|---|
note | string | No | A note for the period's history, e.g. who checked the figures. |
Response
200 OK with a JSON object:
| Field | Type | Description |
|---|---|---|
id | fp_… ID | |
object | "filing_period" | |
entityId | ent_… ID | |
livemode | boolean | |
regimeId | string | |
registrationId | regn_… ID | |
reportKind | one of eu_oss, eu_domestic, uk_vat, ch_mwst, generic, us_state | |
reportAvailable | boolean | |
frequency | one of monthly, quarterly, annual | |
periodKey | string | The period: "2026-Q3", "2026-07" or "2026". |
periodStart | date-time | |
periodEnd | date-time | The end (exclusive): the next period's first local midnight. |
firstDay | string | |
lastDay | string | |
timeZone | string | |
currency | string | |
dueDate | string | |
dueAt | date-time | 23:59:59 local time on the due date. |
lockableAt | date-time | |
status | one of open, locked, prepared, submitted, paid | |
statusChangedAt | date-time | |
lockedAt | date-time or null | |
preparedAt | date-time or null | |
submittedAt | date-time or null | |
reference | string or null | |
paidAt | date-time or null | |
paymentRef | string or null | |
totals | object or null | |
createdAt | date-time | |
updatedAt | date-time | |
registration | object or null | |
endsBeforeRegistration | boolean | |
report | object or null | |
files | array of object | |
files[].format | one of csv, xlsx, xml | |
files[].fileId | file_… ID | |
files[].filename | string | |
files[].contentType | string | |
files[].size | integer | |
files[].sha256 | string | |
receipts | array of object | |
receipts[].kind | one of file, reference | |
receipts[].reference | string | |
receipts[].label | string or null | |
receipts[].addedAt | date-time | |
receipts[].addedBy | string | |
paymentLedgerTxnIds | array of txn_… ID | |
reminders | array of object | |
reminders[].code | string | |
reminders[].at | date-time | |
reminders[].skipped | boolean | |
history | array of object | |
history[].from | one of open, locked, prepared, submitted, paid or null | |
history[].to | one of open, locked, prepared, submitted, paid | |
history[].at | date-time | |
history[].by | string | |
history[].note | string or null | |
actions | object | |
actions.lock | object | |
actions.lock.allowed | boolean | |
actions.lock.code | string or null | |
actions.lock.message | string or null | |
actions.prepare | object | |
actions.prepare.allowed | boolean | |
actions.prepare.code | string or null | |
actions.prepare.message | string or null | |
actions.submit | object | |
actions.submit.allowed | boolean | |
actions.submit.code | string or null | |
actions.submit.message | string or null | |
actions.markPaid | object | |
actions.markPaid.allowed | boolean | |
actions.markPaid.code | string or null | |
actions.markPaid.message | string or null |
Examples
Lock the Q3 OSS period
POST /api/v1/filing_periods/fp_01m4tx5nj8emwbyf7y9vcf47y0/lock
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Response (200):
{
"id": "fp_01m4tx5nj8emwbyf7y9vcf47y0",
"object": "filing_period",
"entityId": "ent_01m4tx5nj8emwbyf7y9vcf47x2",
"livemode": true,
"regimeId": "EU_OSS_UNION",
"registrationId": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
"reportKind": "eu_oss",
"reportAvailable": true,
"frequency": "quarterly",
"periodKey": "2026-Q3",
"periodStart": "2026-06-30T22:00:00.000Z",
"periodEnd": "2026-09-30T22:00:00.000Z",
"firstDay": "2026-07-01",
"lastDay": "2026-09-30",
"timeZone": "Europe/Zagreb",
"currency": "EUR",
"dueDate": "2026-10-31",
"dueAt": "2026-10-31T22:59:59.000Z",
"lockableAt": "2026-09-30T22:00:00.000Z",
"status": "locked",
"statusChangedAt": "2026-10-02T08:00:00.000Z",
"lockedAt": "2026-10-02T08:00:00.000Z",
"preparedAt": null,
"submittedAt": null,
"reference": null,
"paidAt": null,
"paymentRef": null,
"totals": null,
"createdAt": "2026-07-01T03:00:00.000Z",
"updatedAt": "2026-10-02T08:00:00.000Z",
"registration": {
"id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
"state": "registered",
"registrationNumber": "HR12345678901",
"effectiveFrom": "2026-03-31T22:00:00.000Z"
},
"endsBeforeRegistration": false,
"report": null,
"files": [],
"receipts": [],
"paymentLedgerTxnIds": [],
"reminders": [],
"history": [
{
"from": null,
"to": "open",
"at": "2026-07-01T03:00:00.000Z",
"by": "system",
"note": null
},
{
"from": "open",
"to": "locked",
"at": "2026-10-02T08:00:00.000Z",
"by": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
"note": null
}
],
"actions": {
"lock": {
"allowed": false,
"code": "filing_period_status_invalid",
"message": "This period is locked: \"lock\" needs open."
},
"prepare": {
"allowed": true,
"code": null,
"message": null
},
"submit": {
"allowed": false,
"code": "filing_period_status_invalid",
"message": "This period is locked: \"submit\" needs prepared."
},
"markPaid": {
"allowed": false,
"code": "filing_period_status_invalid",
"message": "This period is locked: \"mark_paid\" needs submitted."
}
}
}
Errors
| Code | HTTP status | When | What to do |
|---|---|---|---|
validation_failed | 400 | A field is malformed (param names it). | Fix the fields listed in details.issues and send the request again. |
resource_not_found | 404 | No filing period with this ID exists for this legal entity and mode. | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode. |
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). |
filing_period_status_invalid | 409 | The period isn't open (details.status). | Reload the period and check its status: details.allowed_from lists the statuses the action needs. Periods go open → locked → prepared → submitted → paid. |
filing_period_not_ended | 409 | The period isn't over yet (details.lockable_at). | Lock the period from details.lockable_at on: after its last day (plus the lock delay for late documents). |
version_conflict | 409 | The period changed at the same moment. Reload it and try again. | Fetch the object again and retry the change. |
permission_denied | 403 | You can't work on this entity's filings (tax managers, finance, owners and admins can). | Ask an organization owner or admin for a role or scope that allows this action. |
It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, idempotency_key_required, idempotency_key_reused, idempotency_in_progress, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.