Guides
Responses
Successful responses wrap their payload in data; lists add pagination; a few operations add meta; errors are RFC 9457 problems. API responses share one set of headers.
Envelope variants
Link to this section: Envelope variantsA list returns its records in data and the paging state in pagination. nextCursor is null on the last page. total appears only when you ask for it with includeTotal.
{
"data": [
{
"id": "5e8d1a9c",
"orderNumber": "ORD-0412",
"status": "reserved",
"startDate": "2026-10-17T08:00:00.000Z",
"endDate": "2026-10-19T17:00:00.000Z",
"contact": { "id": "c71f40b2", "name": "Acme Rentals" },
"grossPrice": "1234.50"
}
],
"pagination": { "nextCursor": "opaque-cursor", "hasMore": true }
}Single resource
Link to this section: Single resourceA detail read, a create and an update return the resource in data. Operations that create a resource answer 201; reads and updates answer 200.
Resource with meta
Link to this section: Resource with metaA few operations also tell you what the call did to other records, in meta. POST /api reports meta., the delivery and return tasks the reservation created; POST /api reports meta.. Both return the full order in data.
Most deletes and the two archive operations (PUT /api and PUT /api) answer 204 with no body. Four deletes answer 200 and return the record they changed instead: DELETE /api and DELETE /api return the contact, DELETE /api returns the result of the unassignment and DELETE /api returns the project. A conditional read whose ETag is current answers 304, also without a body.
Batch results
Link to this section: Batch resultsPOST /api is a batch. It answers 200 with one result per element, in request order. With atomic: false it answers 207 and each element carries its own status and error. See the retry table in Errors.
Errors are application and carry type, title, status, code, detail and requestId, plus errors, requiredScope, requiredAddon or retryAfter when they apply. They are described in Errors.
Response headers
Link to this section: Response headersThese headers come from the OpenAPI document, plus the standard Date.
| Header | Where | What it tells you |
|---|---|---|
X-Request-Id | Every API response. Not the OAuth endpoints, and not the 401 of the MCP discovery | The identifier of the request (req_…), generated by the server. Error bodies repeat it as requestId; the 401 of the MCP endpoint carries it only in the body. Log it and quote it to support. |
RateLimit-Limit | Every response that consumed quota (all but a 401 and a 403 insufficient_scope) | Requests allowed per minute by the tightest quota the request consumed. |
RateLimit-Remaining | Same | Requests left in the current one-minute window of that quota. |
RateLimit-Reset | Same | Seconds until that window resets. |
Retry-After | 429 responses | Seconds to wait before retrying; the 429 problem repeats the value in retryAfter. See Rate limits. |
ETag | Detail reads and the writes that return the resource | A strong tag of the representation. Send it back as If-Match on a write, or as If-None-Match on a read. |
Content-Language | Error responses | The language of detail and errors[]., negotiated from Accept-Language. |
Idempotent-Replay | Declared by the write operations; present on a response replayed for a repeated Idempotency-Key | true when this is the stored response of the first attempt, not a new execution. It is absent on the first execution, and a stored error is replayed too. |
Date | Every response | The time on Filmo's servers. Use it, not your own clock, whenever you compute a window for incremental reads. |
Deprecation, Sunset, Link | Responses of a deprecated operation | Announce that the operation is deprecated, the day it will be removed, and where the notice lives (rel="deprecation"). |
The quota headers are explained in Rate limits, Idempotent-Replay in Idempotency and ETag in Concurrency.
Conditional reads
Link to this section: Conditional readsDetail reads return an ETag. Send the one you already hold in If-None-Match: if it is still current, the answer is 304 with no body and the ETag header, and your copy is current. If the resource changed, you get the full 200 with a new ETag.
# First read: note the ETag header.
curl -sS -D - -o /dev/null "https://app.filmo.io/api/v1/account" \
-H "Authorization: Bearer $FILMO_API_KEY"
# Later: ask only for a newer version (paste the ETag you received, quotes included).
curl -sS -i "https://app.filmo.io/api/v1/account" \
-H "Authorization: Bearer $FILMO_API_KEY" \
-H 'If-None-Match: "<the ETag you received>"'Warnings in meta
Link to this section: Warnings in metaAn operation marked deprecated carries Deprecation and Sunset headers, and every JSON body it returns carries meta. with an entry whose code is deprecated. Log those warnings and alert on them: the sunset day is at least six months after the deprecation takes effect. Entries with other codes may be added later; ignore the ones you do not know.
{ "data": { "id": "5e8d1a9c" }, "meta": { "warnings": [{ "code": "deprecated" }] } }Statuses in use
Link to this section: Statuses in use| Status | Meaning |
|---|---|
| 200 | Success. Reads, updates, actions and queries. |
| 201 | A resource was created. |
| 204 | Success with no body: most deletes and the archive operations. Four deletes answer 200 with the changed record. |
| 207 | Partial result of a batch: only POST /api with atomic: false. Read the status of every element. |
| 304 | Not modified: the ETag you sent in If-None-Match is current. |
| 400 | validation_error: the query or the body is invalid. |
| 401 | The key is missing or unusable: unauthorized and the api_key_* codes. |
| 402 | addon_required: the account lacks the add-on of that module. |
| 403 | insufficient_scope or forbidden. |
| 404 | not_found: it does not exist, or it is outside the tenancy of the key. |
| 409 | conflict (its cause is in errors[0].), contact_in_use, address_in_use or insufficient_stock. |
| 412 | precondition_failed: If-Match did not match. |
| 422 | idempotency_key_reused. |
| 429 | rate_limited. |
| 500 | internal_error. |
| 503 | service_unavailable: the feature is switched off for the account. |
Tolerate what you do not know
Link to this section: Tolerate what you do not knowWithin v1, Filmo adds properties to responses and values to unions such as statuses without notice. Ignore properties you do not use, treat an unknown enum value as unknown rather than as an error, and do not validate responses with a schema that rejects extra properties. Generated clients with closed enums break on additive changes: see Versioning.
Related pages
Link to this section: Related pagesGuides
Errors
Errors are RFC 9457 problem documents. Branch on the stable
code, never on the text, and use the retry table to decide whether to try again.Guides
Pagination
Lists return one page at a time. Ask for a page with
limit, and whilepagination.ishasMore truecall again with thenextCursoryou were given.Guides
Data types
Money is a decimal string, dates are ISO 8601, a property can be present and null, and custom fields are maps. Parse each type once, at the edge of your integration.
Guides
Versioning and deprecation
Within v1 Filmo only adds things. Anything that could break your integration is announced first, either as a new major version or as a deprecation with at least six months before the sunset.
Was this page helpful?