# Submit a compliance task

> The tasks.submit operation: POST /api/v1/tasks/{id}/submit in the REST API and the tasks_submit tool in the MCP server.

Submits the outcome of a task whose completion changes a registration or a filing period, with the
evidence: the task is done and, in the same transaction, the linked state changes:

| Task                    | `reference`                                                    | Changes                                                                                                    |
| ----------------------- | -------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| `filing.submit`         | the return's reference (required)                              | the period becomes `submitted`                                                                             |
| `filing.pay`            | the payment reference (required); `paidOn` (default today)     | the period becomes `paid`; the ledger moves the tax payable to the bank                                    |
| `registration.submit`   | the application or receipt number                              | in grace, the application is marked submitted (the deadline is met); then `registration.confirm` is raised |
| `registration.confirm`  | the registration number (required); `effectiveFrom` (required) | the registration becomes `registered`                                                                      |
| `deregistration.submit` | the authority's reference                                      | the registration becomes `deregistered`                                                                    |

Evidence: receipt files uploaded to the task (`tasks.documents.upload`, then `outputs.files`), more
`outputs.references`, `outputs.submittedAt` (default now) and `outputs.notes`. They are attached to the
filing period's receipts or the registration's evidence. Registration tasks need a receipt file or a
reference as proof. `*.submit` tasks reference the authorization the work was done under
(`authorizationId`): valid now, for this entity, mode and the task's regime. Ownrecord records it; it
doesn't grant it.

Compliance tier (spec §41.4): under your approval policy the call may answer `approval_required` (HTTP
202\): nothing changes yet, the task waits (`awaiting_approval`), and once a person approves it runs exactly
as sent. Dry-run it first. The caller must also be allowed to change the linked registration
(`registrations:write`) or filing period (`filings:write`). People need a sign-in within the last 15
minutes. While someone else holds the task's lease, only they can submit it.

## At a glance

- **REST:** `POST /api/v1/tasks/{id}/submit`
- **MCP tool:** `tasks_submit`
- **Operation ID:** `tasks.submit`
- **Scope:** Organization, or one of its legal entities or brands
- **Permission:** `tasks: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 `tasks:write` scope
- **Fresh sign-in:** In the console, a sign-in within the last 15 minutes
- **Since:** M10

## Request

### Path parameters

| Field | Type        | Description |
| ----- | ----------- | ----------- |
| `id`  | `task_…` ID |             |

### Body

A JSON object (`Content-Type: application/json`):

| Field                 | Type                 | Required | Description                                                                |
| --------------------- | -------------------- | -------- | -------------------------------------------------------------------------- |
| `reference`           | string               | No       | The authority's reference for this task (see the table).                   |
| `effectiveFrom`       | string               | No       | `registration.confirm`: the first day the registration is effective.       |
| `paidOn`              | string               | No       | `filing.pay`: the day the tax was paid, in the period's time zone.         |
| `authorizationId`     | `atz_…` ID           | No       | The authorization the work was done under (required for `*.submit` tasks). |
| `outputs`             | object               | No       |                                                                            |
| `outputs.references`  | object               | No       |                                                                            |
| `outputs.submittedAt` | date-time            | No       |                                                                            |
| `outputs.files`       | array of `file_…` ID | No       |                                                                            |
| `outputs.notes`       | string               | No       |                                                                            |
| `expectedVersion`     | integer (at least 1) | No       |                                                                            |

## Response

`200 OK` with a JSON object:

| Field                | Type                                                                                                                             | Description |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------- | ----------- |
| `id`                 | `task_…` ID                                                                                                                      |             |
| `object`             | `"task"`                                                                                                                         |             |
| `type`               | one of 12 values, e.g. `registration.prerequisites`, `registration.prepare`, `registration.submit` (all in the OpenAPI document) |             |
| `entityId`           | `ent_…` ID                                                                                                                       |             |
| `livemode`           | boolean                                                                                                                          |             |
| `regimeId`           | string or null                                                                                                                   |             |
| `registrationId`     | `regn_…` ID or null                                                                                                              |             |
| `filingPeriodId`     | `fp_…` ID or null                                                                                                                |             |
| `prerequisiteCode`   | string or null                                                                                                                   |             |
| `title`              | string                                                                                                                           |             |
| `description`        | string or null                                                                                                                   |             |
| `priority`           | one of `low`, `normal`, `high`, `urgent`                                                                                         |             |
| `status`             | one of `open`, `claimed`, `in_progress`, `awaiting_approval`, `done`, `failed`, `cancelled`                                      |             |
| `reason`             | one of 11 values, e.g. `auto_blocked`, `existing_customer_sale`, `prerequisite_open` (all in the OpenAPI document) or null       |             |
| `dueAt`              | date-time or null                                                                                                                |             |
| `overdue`            | boolean                                                                                                                          |             |
| `assignee`           | object or null                                                                                                                   |             |
| `claimedUntil`       | date-time or null                                                                                                                |             |
| `leaseActive`        | boolean                                                                                                                          |             |
| `completeWith`       | one of `tasks.complete`, `tasks.submit`                                                                                          |             |
| `needsAuthorization` | boolean                                                                                                                          |             |
| `inputs`             | array of object                                                                                                                  |             |
| `inputs[].kind`      | string                                                                                                                           |             |
| `inputs[].fileId`    | `file_…` ID or null                                                                                                              |             |
| `inputs[].data`      | object or null                                                                                                                   |             |
| `outputs`            | object or null                                                                                                                   |             |
| `authorizationId`    | `atz_…` ID or null                                                                                                               |             |
| `approvalRequestId`  | `apr_…` ID or null                                                                                                               |             |
| `failure`            | object or null                                                                                                                   |             |
| `checklist`          | array of object                                                                                                                  |             |
| `checklist[].text`   | string                                                                                                                           |             |
| `checklist[].done`   | boolean                                                                                                                          |             |
| `createdAt`          | date-time                                                                                                                        |             |
| `updatedAt`          | date-time                                                                                                                        |             |
| `completedAt`        | date-time or null                                                                                                                |             |
| `completedBy`        | string or null                                                                                                                   |             |
| `version`            | integer (at least 1)                                                                                                             |             |

## Examples

### The Q3 OSS return was filed

An agent's call answers `approval_required` under the default policy; this is the approved run's result.

```http
POST /api/v1/tasks/task_01m4ttwd3veh9apbewxheq5xa9/submit
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "reference": "HR/HR12345678901/Q3.2026",
  "authorizationId": "atz_01m4ttwd3veh9apbewxheq5xa3",
  "outputs": {
    "files": [
      "file_01m4ttwd3veh9apbewxheq5xah"
    ],
    "submittedAt": "2026-10-15T09:10:00.000Z"
  }
}
```

Response (`200`):

```json
{
  "id": "task_01m4ttwd3veh9apbewxheq5xa9",
  "object": "task",
  "type": "filing.submit",
  "entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
  "livemode": true,
  "regimeId": "EU_OSS_UNION",
  "registrationId": "regn_01m4ttwd3veh9apbewxheq5xa8",
  "filingPeriodId": "fp_01m4ttwd3veh9apbewxheq5xa7",
  "prerequisiteCode": null,
  "title": "File the One-Stop Shop, Union scheme 2026-Q3 return",
  "description": "File the One-Stop Shop, Union scheme 2026-Q3 return with the authority using the filing package, by 2026-10-31. Then submit this task with the return's reference, the portal's confirmation and the authorization you acted under: the period becomes submitted.",
  "priority": "high",
  "status": "done",
  "reason": "period_ended",
  "dueAt": "2026-10-31T22:59:59.000Z",
  "overdue": false,
  "assignee": {
    "type": "agent",
    "id": "agt_01m4ttwd3veh9apbewxheq5xa6"
  },
  "claimedUntil": null,
  "leaseActive": false,
  "completeWith": "tasks.submit",
  "needsAuthorization": true,
  "inputs": [
    {
      "kind": "filing_period",
      "fileId": null,
      "data": {
        "filingPeriodId": "fp_01m4ttwd3veh9apbewxheq5xa7",
        "regimeId": "EU_OSS_UNION",
        "periodKey": "2026-Q3",
        "dueDate": "2026-10-31",
        "dueAt": "2026-10-31T22:59:59.000Z"
      }
    },
    {
      "kind": "filing_package",
      "fileId": null,
      "data": {
        "filingPeriodId": "fp_01m4ttwd3veh9apbewxheq5xa7"
      }
    },
    {
      "kind": "playbook",
      "fileId": null,
      "data": {
        "regimeId": "EU_OSS_UNION",
        "playbookKind": "filing"
      }
    }
  ],
  "outputs": {
    "references": {
      "return": "HR/HR12345678901/Q3.2026"
    },
    "submittedAt": "2026-10-15T09:10:00.000Z",
    "files": ["file_01m4ttwd3veh9apbewxheq5xah"],
    "notes": null
  },
  "authorizationId": "atz_01m4ttwd3veh9apbewxheq5xa3",
  "approvalRequestId": "apr_01m4ttwd3veh9apbewxheq5xa1",
  "failure": null,
  "checklist": [
    {
      "text": "Download the filing package",
      "done": false
    },
    {
      "text": "File the return in the authority's portal",
      "done": false
    },
    {
      "text": "Submit this task with the reference, the confirmation and the authorization",
      "done": false
    }
  ],
  "createdAt": "2026-10-01T00:23:00.000Z",
  "updatedAt": "2026-10-15T11:02:00.000Z",
  "completedAt": "2026-10-15T11:02:00.000Z",
  "completedBy": "agt_01m4ttwd3veh9apbewxheq5xa6",
  "version": 5
}
```

## Errors

| Code                                                                                                               | HTTP status | When                                                                                          | What to do                                                                                                                                                                                                                                                                            |
| ------------------------------------------------------------------------------------------------------------------ | ----------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed)                             | 400         | A field is malformed, a required reference or date is missing, or a date is in the future.    | 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 task with this ID in this organization, entity and mode.                                   | Check the ID and that your credentials are scoped to the right organization, entity, brand and mode.                                                                                                                                                                                  |
| [`task_complete_required`](https://ownrecord.io/docs/reference/errors.md#task_complete_required)                   | 400         | The task doesn't change a registration or filing period: use `tasks.complete`.                | Call `tasks.complete` with the task's outputs.                                                                                                                                                                                                                                        |
| [`task_status_invalid`](https://ownrecord.io/docs/reference/errors.md#task_status_invalid)                         | 409         | The task is finished, or it waits for another approval.                                       | Reload the task: finished tasks (`done`, `failed`, `cancelled`) don't change, and a task waiting for an approval changes only through that approval. `details.status` is the task's status.                                                                                           |
| [`task_claimed`](https://ownrecord.io/docs/reference/errors.md#task_claimed)                                       | 409         | Someone else holds the task's lease.                                                          | Work on another task (`tasks.list` with `claimable: true`), or try again after `details.claimedUntil`: an expired lease frees the task. `details.assignee` is who holds it.                                                                                                           |
| [`task_authorization_required`](https://ownrecord.io/docs/reference/errors.md#task_authorization_required)         | 400         | A `*.submit` task without `authorizationId`.                                                  | Record who may act for the entity under this regime (`authorizations.create`) and pass its ID as `authorizationId`. Ownrecord records the authorization; it doesn't grant it.                                                                                                         |
| [`task_authorization_invalid`](https://ownrecord.io/docs/reference/errors.md#task_authorization_invalid)           | 400         | The authorization isn't valid now for this entity, mode and regime (`details.problem`).       | Use an authorization of this legal entity and mode that is valid now and covers the task's regime. `details.problem` is `revoked`, `expired`, `not_yet_valid`, `regime_not_covered`, `other_entity` or `other_mode`.                                                                  |
| [`task_output_file_not_found`](https://ownrecord.io/docs/reference/errors.md#task_output_file_not_found)           | 400         | A receipt isn't a document of the task (upload it with `tasks.documents.upload`).             | Upload the receipt to the task first (`tasks.documents.upload`) and pass its `file_…` ID, or record the receipt number as a reference instead. `details.fileId` is the ID that wasn't found.                                                                                          |
| [`filing_period_status_invalid`](https://ownrecord.io/docs/reference/errors.md#filing_period_status_invalid)       | 409         | The period isn't `prepared` (submit) or `submitted` (pay).                                    | Reload the period and check its `status`: `details.allowed_from` lists the statuses the action needs. Periods go open → locked → prepared → submitted → paid.                                                                                                                         |
| [`registration_transition_invalid`](https://ownrecord.io/docs/reference/errors.md#registration_transition_invalid) | 409         | The registration can't make this change now (e.g. it isn't registered, for a deregistration). | 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`](https://ownrecord.io/docs/reference/errors.md#registration_details_invalid)       | 400         | The registration number, effective date or proof is missing.                                  | Fill in the field named in `param`: the registration number, the date it is effective from, or at least one proof file.                                                                                                                                                               |
| [`approval_required`](https://ownrecord.io/docs/reference/errors.md#approval_required)                             | 202         | Your approval policy needs a person to approve the submission first (HTTP 202).               | 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. |
| [`fresh_auth_required`](https://ownrecord.io/docs/reference/errors.md#fresh_auth_required)                         | 403         | Your last sign-in is older than 15 minutes.                                                   | Sign in again, then repeat the action within 15 minutes.                                                                                                                                                                                                                              |
| [`version_conflict`](https://ownrecord.io/docs/reference/errors.md#version_conflict)                               | 409         | The task changed since `expectedVersion`, or at the same moment.                              | 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 tasks here, or can't change the linked registration or filing period.       | 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_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).
