# 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.

Locks 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-Key` required
- **Modes:** Test and live
- **Authentication:** API key with the `filings:write` scope
- **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

```http
POST /api/v1/filing_periods/fp_01m4tx5nj8emwbyf7y9vcf47y0/lock
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
```

Response (`200`):

```json
{
  "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`](https://ownrecord.io/docs/reference/errors.md#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`](https://ownrecord.io/docs/reference/errors.md#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`](https://ownrecord.io/docs/reference/errors.md#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`](https://ownrecord.io/docs/reference/errors.md#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`](https://ownrecord.io/docs/reference/errors.md#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`](https://ownrecord.io/docs/reference/errors.md#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`](https://ownrecord.io/docs/reference/errors.md#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](https://ownrecord.io/docs/reference.md#common-errors): [`api_version_unsupported`](https://ownrecord.io/docs/reference/errors.md#api_version_unsupported), [`invalid_json`](https://ownrecord.io/docs/reference/errors.md#invalid_json), [`unsupported_media_type`](https://ownrecord.io/docs/reference/errors.md#unsupported_media_type), [`authentication_required`](https://ownrecord.io/docs/reference/errors.md#authentication_required), [`api_key_invalid`](https://ownrecord.io/docs/reference/errors.md#api_key_invalid), [`idempotency_key_required`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_required), [`idempotency_key_reused`](https://ownrecord.io/docs/reference/errors.md#idempotency_key_reused), [`idempotency_in_progress`](https://ownrecord.io/docs/reference/errors.md#idempotency_in_progress), [`approval_required`](https://ownrecord.io/docs/reference/errors.md#approval_required), [`approval_rejected`](https://ownrecord.io/docs/reference/errors.md#approval_rejected), [`approval_expired`](https://ownrecord.io/docs/reference/errors.md#approval_expired), [`stale_approval`](https://ownrecord.io/docs/reference/errors.md#stale_approval), [`approval_policy_denied`](https://ownrecord.io/docs/reference/errors.md#approval_policy_denied), [`rate_limited`](https://ownrecord.io/docs/reference/errors.md#rate_limited), [`internal_error`](https://ownrecord.io/docs/reference/errors.md#internal_error).
