Mark a return submitted
The filing_periods.submit operation: POST /api/v1/filing_periods/{id}/submit in the REST API and the filing_periods_submit tool in the MCP server.
/api/v1/filing_periods/{id}/submitRecords that the period's return was filed with the tax authority (spec §21.1): the authority's reference
(for the EU One-Stop Shop, the return's reference number), when it was submitted (submittedAt, default
now) and optionally the portal's confirmation as receipts: documents uploaded to the period
(filing_periods.documents.upload) or references. The period becomes submitted; mark it paid once the
tax is paid.
Ownrecord doesn't log into government portals: a person or an authorized agent files the return with the
report files (spec §41.5). Works on a prepared period. Compliance tier (spec §41.4): an agent's call needs
approval under the default policy.
At a glance
- REST:
POST /api/v1/filing_periods/{id}/submit - MCP tool:
filing_periods_submit - Operation ID:
filing_periods.submit - 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 |
|---|---|---|---|
reference | string | Yes | The authority's reference of the filed return. |
submittedAt | date-time | No | When the return was filed (ISO 8601). Default: now. |
receipts | array of object | No | The portal's confirmation: uploaded documents or references (optional). |
receipts[].reference | string | Yes | A document uploaded to this period (file_…, filing_periods.documents.upload), or the portal's confirmation number or a link to it. |
receipts[].label | string | No | What the document is. |
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
The Q3 OSS return was filed
POST /api/v1/filing_periods/fp_01m4tx5nj8emwbyf7y9vcf47y0/submit
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json
{
"reference": "HR/HR12345678901/Q3.2026",
"submittedAt": "2026-10-15T09:00:00.000Z",
"receipts": [
{
"reference": "file_01m4tx5nj8emwbyf7y9vcf47y4",
"label": "OSS portal confirmation"
}
]
}
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": "submitted",
"statusChangedAt": "2026-10-15T09:00:00.000Z",
"lockedAt": "2026-10-02T08:00:00.000Z",
"preparedAt": "2026-10-02T08:05:00.000Z",
"submittedAt": "2026-10-15T09:00:00.000Z",
"reference": "HR/HR12345678901/Q3.2026",
"paidAt": null,
"paymentRef": null,
"totals": {
"currency": "EUR",
"taxable": "1500000000",
"tax": "290000000",
"corrections": "-19000000",
"due": "271000000",
"refundable": "0"
},
"createdAt": "2026-07-01T03:00:00.000Z",
"updatedAt": "2026-10-15T09:00:00.000Z",
"registration": {
"id": "regn_01m4tx5nj8emwbyf7y9vcf47xk",
"state": "registered",
"registrationNumber": "HR12345678901",
"effectiveFrom": "2026-03-31T22:00:00.000Z"
},
"endsBeforeRegistration": false,
"report": {
"kind": "eu_oss",
"currency": "EUR",
"rounding": "half_up",
"fxRule": null,
"generatedAt": "2026-10-02T08:05:00.000Z",
"fx": [],
"sections": [
{
"id": "supplies",
"title": "Supplies by member state of consumption and rate",
"columns": [
{
"key": "memberState",
"label": "Member state",
"type": "text"
},
{
"key": "rate",
"label": "VAT rate",
"type": "rate"
},
{
"key": "rateKind",
"label": "Rate type",
"type": "text"
},
{
"key": "taxable",
"label": "Taxable amount",
"type": "money"
},
{
"key": "vat",
"label": "VAT",
"type": "money"
},
{
"key": "lines",
"label": "Lines",
"type": "count"
}
],
"rows": [
{
"memberState": "DE",
"rate": "190000",
"rateKind": "standard",
"taxable": "1000000000",
"vat": "190000000",
"lines": 8
},
{
"memberState": "FR",
"rate": "200000",
"rateKind": "standard",
"taxable": "500000000",
"vat": "100000000",
"lines": 3
}
]
},
{
"id": "corrections",
"title": "Corrections of earlier periods",
"columns": [
{
"key": "originalPeriod",
"label": "Period corrected",
"type": "text"
},
{
"key": "memberState",
"label": "Member state",
"type": "text"
},
{
"key": "taxable",
"label": "Taxable amount",
"type": "money"
},
{
"key": "vat",
"label": "VAT",
"type": "money"
},
{
"key": "lines",
"label": "Lines",
"type": "count"
}
],
"rows": [
{
"originalPeriod": "2026-Q2",
"memberState": "DE",
"taxable": "-100000000",
"vat": "-19000000",
"lines": 1
}
]
},
{
"id": "balances",
"title": "VAT due per member state",
"columns": [
{
"key": "memberState",
"label": "Member state",
"type": "text"
},
{
"key": "supplies",
"label": "VAT on supplies",
"type": "money"
},
{
"key": "corrections",
"label": "Corrections",
"type": "money"
},
{
"key": "balance",
"label": "Balance",
"type": "money"
}
],
"rows": [
{
"memberState": "DE",
"supplies": "190000000",
"corrections": "-19000000",
"balance": "171000000"
},
{
"memberState": "FR",
"supplies": "100000000",
"corrections": "0",
"balance": "100000000"
}
]
},
{
"id": "reconciliation",
"title": "Reconciliation with the ledger",
"columns": [
{
"key": "jurisdiction",
"label": "Jurisdiction",
"type": "text"
},
{
"key": "currency",
"label": "Currency",
"type": "text"
},
{
"key": "reportTax",
"label": "Report tax",
"type": "money"
},
{
"key": "ledgerTax",
"label": "Ledger tax payable",
"type": "money"
},
{
"key": "difference",
"label": "Difference",
"type": "money"
}
],
"rows": [
{
"jurisdiction": "DE",
"currency": "EUR",
"reportTax": "171000000",
"ledgerTax": "171000000",
"difference": "0"
},
{
"jurisdiction": "FR",
"currency": "EUR",
"reportTax": "100000000",
"ledgerTax": "100000000",
"difference": "0"
}
]
}
],
"reconciliation": {
"matches": true,
"rows": [
{
"jurisdictionId": "DE",
"currency": "EUR",
"reportTax": "171000000",
"ledgerTax": "171000000",
"difference": "0"
},
{
"jurisdictionId": "FR",
"currency": "EUR",
"reportTax": "100000000",
"ledgerTax": "100000000",
"difference": "0"
}
]
},
"counts": {
"lines": 12,
"corrections": 1,
"notReported": 0,
"documents": 12
}
},
"files": [
{
"format": "csv",
"fileId": "file_01m4tx5nj8emwbyf7y9vcf47y2",
"filename": "EU_OSS_UNION-2026-Q3.csv",
"contentType": "text/csv; charset=utf-8",
"size": 2381,
"sha256": "5d1c9d6b7f3e0a4c8b2f1e6d9a7c3b5e0f4d8a2c6b1e9f7d3a5c0b8e2f6d4a1c"
},
{
"format": "xlsx",
"fileId": "file_01m4tx5nj8emwbyf7y9vcf47y3",
"filename": "EU_OSS_UNION-2026-Q3.xlsx",
"contentType": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"size": 9184,
"sha256": "8a3f6c1e9d4b7a2f5c0e8d3b6a1f4c9e7d2b5a0f3c8e6d1b4a9f7c2e5d0b3a6f"
}
],
"receipts": [
{
"kind": "file",
"reference": "file_01m4tx5nj8emwbyf7y9vcf47y4",
"label": "OSS portal confirmation",
"addedAt": "2026-10-15T09:00:00.000Z",
"addedBy": "usr_01m4tx5nj8emwbyf7y9vcf47xa"
}
],
"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
},
{
"from": "locked",
"to": "prepared",
"at": "2026-10-02T08:05:00.000Z",
"by": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
"note": null
},
{
"from": "prepared",
"to": "submitted",
"at": "2026-10-15T09:00:00.000Z",
"by": "usr_01m4tx5nj8emwbyf7y9vcf47xa",
"note": null
}
],
"actions": {
"lock": {
"allowed": false,
"code": "filing_period_status_invalid",
"message": "This period is submitted: \"lock\" needs open."
},
"prepare": {
"allowed": false,
"code": "filing_period_status_invalid",
"message": "This period is submitted: \"prepare\" needs locked or prepared."
},
"submit": {
"allowed": false,
"code": "filing_period_status_invalid",
"message": "This period is submitted: \"submit\" needs prepared."
},
"markPaid": {
"allowed": true,
"code": null,
"message": null
}
}
}
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 prepared (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_receipt_not_found | 400 | A file_… receipt isn't a document of this period (param names it). | Upload the receipt to the period first (filing_periods.documents.upload) and pass its file_… ID, or pass a reference instead. |
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.