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.

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

GET /api/v1/orders?limit=1 (trimmed to a few fields)
{
  "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 }
}

A detail read, a create and an update return the resource in data. Operations that create a resource answer 201; reads and updates answer 200.

A few operations also tell you what the call did to other records, in meta. POST /api/v1/orders/{orderId}/reserve reports meta.tasksCreated, the delivery and return tasks the reservation created; POST /api/v1/orders/{orderId}/cancel reports meta.tasksDeleted. Both return the full order in data.

Most deletes and the two archive operations (PUT /api/v1/orders/{orderId}/archive and PUT /api/v1/projects/{projectId}/archive) answer 204 with no body. Four deletes answer 200 and return the record they changed instead: DELETE /api/v1/contacts/{contactId}/addresses/{addressId} and DELETE /api/v1/contacts/{contactId}/related-contacts/{relatedContactId} return the contact, DELETE /api/v1/tags/{tagId}/assignments returns the result of the unassignment and DELETE /api/v1/projects/{projectId}/orders/{orderId} returns the project. A conditional read whose ETag is current answers 304, also without a body.

POST /api/v1/orders/line-items/returns 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/problem+json and carry type, title, status, code, detail and requestId, plus errors, requiredScope, requiredAddon or retryAfter when they apply. They are described in Errors.

These headers come from the OpenAPI document, plus the standard Date.

HeaderWhereWhat it tells you
X-Request-IdEvery API response. Not the OAuth endpoints, and not the 401 of the MCP discoveryThe 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-LimitEvery 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-RemainingSameRequests left in the current one-minute window of that quota.
RateLimit-ResetSameSeconds until that window resets.
Retry-After429 responsesSeconds to wait before retrying; the 429 problem repeats the value in retryAfter. See Rate limits.
ETagDetail reads and the writes that return the resourceA strong tag of the representation. Send it back as If-Match on a write, or as If-None-Match on a read.
Content-LanguageError responsesThe language of detail and errors[].message, negotiated from Accept-Language.
Idempotent-ReplayDeclared by the write operations; present on a response replayed for a repeated Idempotency-Keytrue 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.
DateEvery responseThe time on Filmo's servers. Use it, not your own clock, whenever you compute a window for incremental reads.
Deprecation, Sunset, LinkResponses of a deprecated operationAnnounce 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.

Detail 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>"'

An operation marked deprecated carries Deprecation and Sunset headers, and every JSON body it returns carries meta.warnings[] 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" }] } }
StatusMeaning
200Success. Reads, updates, actions and queries.
201A resource was created.
204Success with no body: most deletes and the archive operations. Four deletes answer 200 with the changed record.
207Partial result of a batch: only POST /api/v1/orders/line-items/returns with atomic: false. Read the status of every element.
304Not modified: the ETag you sent in If-None-Match is current.
400validation_error: the query or the body is invalid.
401The key is missing or unusable: unauthorized and the api_key_* codes.
402addon_required: the account lacks the add-on of that module.
403insufficient_scope or forbidden.
404not_found: it does not exist, or it is outside the tenancy of the key.
409conflict (its cause is in errors[0].code), contact_in_use, address_in_use or insufficient_stock.
412precondition_failed: If-Match did not match.
422idempotency_key_reused.
429rate_limited.
500internal_error.
503service_unavailable: the feature is switched off for the account.

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

  • Guides

    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 while pagination.hasMore is true call again with the nextCursor you 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?