*Overview › Further reading*

# Capabilities and limits of v1

> The API covers most day-to-day work on orders, contacts, items, invoices and the schedule, and leaves a short list of things to the app. Check it here before you design an integration around a feature.

Filmo is rental software, and the API exposes the same records the team sees in the app, with a few deliberate omissions. This page has four parts: what each resource supports, what is not available, the limits a request must respect, and the gaps that are known today.

## What each resource supports

The endpoint reference lists every operation of a resource: whether you can list, read, create, update and delete it, and which actions it has (reserve, cancel, validate, void…). Every operation is also an MCP tool with the same scope and the same limits; see [the MCP overview](https://docs.filmo.io/mcp/overview). The matrix below summarises them for every resource: the operations for list, read, create, update and delete, the number of other actions, and the number of MCP tools. It is generated from the OpenAPI document, so it is always the current contract.

| Resource | List | Read | Create | Update | Delete | Actions | MCP tools |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Account | — | — | — | — | — | 1 | 1 |
| AI | — | — | — | — | — | 1 | 1 |
| Availability | Yes | — | Yes | Yes | Yes | 1 | 5 |
| Collections | Yes | — | Yes | Yes | — | 0 | 3 |
| Contacts | Yes | Yes | Yes | Yes | Yes | 9 | 14 |
| Contracts | Yes | Yes | — | — | — | 4 | 6 |
| Credit notes | Yes | Yes | — | — | — | 2 | 4 |
| CRM | Yes | Yes | Yes | Yes | — | 3 | 9 |
| Custom fields | Yes | — | — | — | — | 0 | 1 |
| Incidents | Yes | Yes | Yes | Yes | — | 2 | 6 |
| Internal services | Yes | Yes | Yes | Yes | — | 0 | 4 |
| Invoices | Yes | Yes | — | — | — | 5 | 7 |
| Items | Yes | Yes | Yes | Yes | Yes | 5 | 13 |
| Kits | Yes | Yes | Yes | Yes | — | 0 | 4 |
| Notes | Yes | — | Yes | — | — | 0 | 2 |
| Orders | Yes | Yes | Yes | Yes | — | 6 | 10 |
| Planner | Yes | — | — | — | — | 2 | 4 |
| Proformas | Yes | Yes | — | — | — | 1 | 3 |
| Projects | Yes | Yes | Yes | Yes | — | 3 | 8 |
| Purchase orders | Yes | Yes | — | Yes | — | 2 | 5 |
| Quotes | Yes | Yes | — | — | — | 2 | 4 |
| Repair tickets | Yes | Yes | Yes | Yes | — | 0 | 4 |
| Schedule | — | — | — | — | — | 1 | 1 |
| Services | Yes | Yes | Yes | Yes | — | 0 | 4 |
| Spaces | Yes | Yes | — | Yes | Yes | 2 | 6 |
| Staff | Yes | Yes | Yes | Yes | Yes | 1 | 6 |
| Subrents | Yes | Yes | — | Yes | — | 0 | 3 |
| Supplier invoices | Yes | Yes | — | — | — | 2 | 4 |
| Tags | Yes | — | Yes | — | Yes | 2 | 5 |
| Task types | Yes | — | — | — | — | 0 | 1 |
| Tasks | Yes | Yes | Yes | Yes | Yes | 0 | 5 |
| Treasury | Yes | Yes | Yes | Yes | — | 1 | 8 |
| Users | Yes | — | — | — | — | 0 | 1 |
| Vehicles | Yes | Yes | Yes | Yes | Yes | 1 | 6 |
| Workflows | Yes | — | — | — | — | 1 | 2 |

## Not available in v1

These are things you might expect from the API that it does not do. Each row names where the spec says so and what to do instead.

| Not available | Where the spec says so | What to do instead |
| --- | --- | --- |
| Prices, discounts, insurance, deposits, status, serialized units and notes when creating an order. The order is created at zero. | `POST /api/v1/orders`: "the order is born at zero and the team prices it from the application" | Complete the order in the app. |
| Adding, removing or editing the lines of an existing order. | `PATCH /api/v1/orders/{orderId}`: "It does NOT add, remove or edit lines" | Use the order editor in the app. |
| Setting your own reference on an order. `OrderDto` has an external reference field; the create and update bodies do not. | `OrderCreateBody` and `OrderUpdateBody` compared with `OrderDto` | Keep your own table of your id against the Filmo `id`, or put the reference in the app. |
| Uploading files, for example to an incident. | `POST /api/v1/incidents/{incidentId}/comments`: "v1 has no file upload" | Attach files in the app. |
| PDFs of invoices and other documents. | No operation in the spec returns a PDF. | Download the document from the app. |
| Composing an invoice, or editing a quote. Invoices can be validated or voided; quotes and proformas only change status. | Tags Invoices, Quotes and Proformas; `POST /api/v1/invoices/{invoiceId}/validate`, `PATCH /api/v1/quotes/{quoteId}/status`, `PATCH /api/v1/proformas/{proformaId}/status` | Compose in the app. To mirror an invoice issued in another system, use `PUT /api/v1/invoices/external/{originSystem}/{originExternalId}`. |
| Webhooks. Filmo does not send webhooks: the API sends no events. | The spec declares no event subscriptions. | Poll incrementally; see the syncing guide. |
| Reading the status of a workflow run. You can start a run and get its identifier; there is no operation to read it afterwards. | `POST /api/v1/workflows/{workflowId}/runs`; the only other workflow operation is `GET /api/v1/workflows` | Check the result in the app. |
| A record of deletions. Deletes are final and leave no trace, and there is no filter for deleted records. | The descriptions of the delete operations, such as `DELETE /api/v1/contacts/{contactId}`: "It is NOT reversible" | Reconcile with windowed sweeps and confirm with a GET before you delete on your side. |
| The tax breakdown, lines and correction reason of a credit note. | `GET /api/v1/credit-notes/{creditNoteId}`: "the tax breakdown, the lines and the reason for the correction are not published" | Register the credit note by its totals and complete the breakdown in the app. |
| The tax id of the customer as it was when the invoice was issued. `InvoiceDto.contact` carries only `id` and `name`; the current tax id lives on the contact. | `InvoiceDto` and `ContactDto` | Store the tax id on your side when you receive the invoice. |
| Tax rate per invoice line, and the invoice series. | `DocumentLineDto` and `InvoiceDto` have no such fields. | Use `taxBreakdown` of the invoice detail for totals per tax; read the series in the app. |
| Reading an archived order. It answers 404 and is left out of lists. | `PUT /api/v1/orders/{orderId}/archive`: "an archived order is no longer visible to the API (its GET responds 404)" | Restore it with `PUT /api/v1/orders/{orderId}/archive` and `archived: false`, using the id you kept. In a sync, treat a 404 as "archived or deleted". |
| Storing your own id on a contact. Contacts have no dedicated external reference field; `contactNumber` is the account's internal reference. | `ContactCreateBody`, `ContactUpdateBody` and `ContactDto` | You can use `contactNumber` (up to 50 characters, not unique) with `POST /api/v1/contacts/lookup`, and also keep your own table of your id against the Filmo contact `id`. |
| Knowing who or what changed a record. No object has an `updatedBy` field, and everything a key writes is attributed to the administrator who owns it. | The Errors section of the API description ("About the person behind the key") | Keep a hash of the last state you wrote, so you can ignore your own changes when you sync. |

Some of these have a longer treatment elsewhere: [syncing data](https://docs.filmo.io/rest-api/guides/syncing-data) for deletes and archived records, and [data left out by design](https://docs.filmo.io/further-reading/excluded-data) for costs, margins and personal data.

The same list is also generated from the spec, so a gap that a new release closes disappears from it:

| Id | Workaround |
| --- | --- |
| Amounts, status, serialized units and notes when creating an order | `POST /api/v1/orders` creates a draft at zero from the customer, the dates and the requested items. Prices, discounts, insurance, deposits, status, specific serialized units, accessories and notes are completed by the team in the Filmo app. Reserving the order with `POST /api/v1/orders/{orderId}/reserve` is possible once it exists. |
| Adding, removing or editing the lines of an order | `PATCH /api/v1/orders/{orderId}` changes the customer, the project and the dates only. Edit the lines in the order editor of the Filmo app. `GET /api/v1/orders/{orderId}/lines` reads them. |
| Setting an external reference when creating an order | `externalReference` is returned on reads, but the body of `POST /api/v1/orders` does not accept it, and neither does the body of `PATCH /api/v1/orders/{orderId}`. Store your reference where the API can write it: a note on the order with `POST /api/v1/notes`, or a tag assigned with `POST /api/v1/tags/{tagId}/assignments`. Or set it in the Filmo app. Projects are different: `externalReference` is writable. |
| Uploading files | `POST /api/v1/incidents/{incidentId}/comments` takes text only because v1 has no file upload. Attach files in the Filmo app. |
| PDF of invoices and other documents | No operation returns a PDF or any other file: every response is `application/json`. Read the data of the document with `GET /api/v1/invoices/{invoiceId}` or `GET /api/v1/quotes/{quoteId}` and render it yourself, or download the PDF from the Filmo app. |
| Composing draft invoices and editing quotes | Invoices can be validated (`POST /api/v1/invoices/{invoiceId}/validate`), voided (`POST /api/v1/invoices/{invoiceId}/void`) or mirrored from an ERP (`PUT /api/v1/invoices/external/{originSystem}/{originExternalId}`); quotes and proformas change status only (`PATCH /api/v1/quotes/{quoteId}/status`, `PATCH /api/v1/proformas/{proformaId}/status`). Compose and edit drafts in the Filmo app. |
| Events pushed to your server (Filmo does not send webhooks) |  |
| Reading the status of a workflow run | `POST /api/v1/workflows/{workflowId}/runs` returns the identifier of the run and the status it is born with (`queued`) and does not wait for it to finish. The API has no operation that reads a run afterwards. Check the result in the Filmo app, or from the data the workflow changes. |
| A log of deleted records |  |
| Tax breakdown, lines and reason of a credit note | `GET /api/v1/credit-notes/{creditNoteId}` says that the signed tax document, the tax breakdown, the lines and the reason for the correction are not published; `netPrice` and the other totals are. Record the credit note by its totals, and complete the breakdown from the Filmo app. |
| The customer's tax ID at the time an invoice was issued | `contact` holds only the `id` and the `name` of the customer. The tax ID exists only as the current `nif`, which can change after the invoice. Store the tax ID on your side when you first receive the invoice. |
| Tax type per line and the series of an invoice | The lines of `GET /api/v1/invoices/{invoiceId}/lines` and `GET /api/v1/quotes/{quoteId}/lines` carry no tax type, and no invoice schema has a series field. The taxes of an invoice are in `taxBreakdown`, per tax type for the whole document. Read the series from the Filmo app. |
| Reading archived orders | An archived order is not visible to the API: its GET answers 404, like a deleted one, no list includes it and `PATCH /api/v1/orders/{orderId}` rejects it. To bring an order back, call `PUT /api/v1/orders/{orderId}/archive` with `archived: false` (it answers 204, and the order is readable again with its GET), or restore it in the Filmo app. In a sync, treat a 404 on an order you hold as archived or deleted, and do not delete on your side without confirming. |
| A dedicated external identifier on a contact | Contacts have no dedicated external-id field. `contactNumber` is writable on `POST /api/v1/contacts` and `PATCH /api/v1/contacts/{contactId}`, but it is not unique and Filmo does not generate it. If you use it as your key, agree a prefix, check for duplicates before writing and treat more than one match in `POST /api/v1/contacts/lookup` as a conflict to resolve. Or keep a table on your side that maps your identifier to the Filmo contact `id`. |
| Knowing who or what made a change |  |

## Hard limits

The schema of each request sets maximum sizes. A request over a limit is rejected with [`validation_error`](https://docs.filmo.io/rest-api/errors/validation_error), and `errors[]` names the offending field. The table below is generated from the spec, so it is always current.

| Where | Limit | Value |
| --- | --- | --- |
| `limit` | maximum | 500 |
| `cursor` | maxLength | 200 |
| `sort` | maxLength | 200 |
| `ContactUpdateBody.emails` | maxItems | 20 |
| `ContactUpdateBody.phoneNumbers` | maxItems | 20 |
| `ContactUpdateBody.websites` | maxItems | 20 |
| `ContactUpdateBody.addresses` | maxItems | 20 |
| `stockTypes` | maxItems | 50 |
| `collectionIds` | maxItems | 50 |
| `ItemCreateBody.tags` | maxItems | 50 |
| `ItemUpdateBody.tags` | maxItems | 50 |
| `AvailabilityCheckBody.items` | maxItems | 100 |
| `statuses` | maxItems | 50 |
| `contactIds` | maxItems | 50 |
| `projectIds` | maxItems | 50 |
| `OrderCreateBody.lines` | maxItems | 100 |
| `paymentStatuses` | maxItems | 50 |
| `orderIds` | maxItems | 50 |
| `operativeStatuses` | maxItems | 50 |
| `itemIds` | maxItems | 50 |
| `spaceIds` | maxItems | 50 |
| `inventoryTypes` | maxItems | 50 |
| `VehicleCreateBody.tags` | maxItems | 50 |
| `staffTypes` | maxItems | 50 |
| `StaffMemberCreateBody.tags` | maxItems | 50 |
| `types` | maxItems | 50 |
| `supplierIds` | maxItems | 50 |
| `StaffAvailabilityBody.tags` | maxItems | 50 |
| `StaffAvailabilityBody.staffIds` | maxItems | 100 |
| `VehicleAvailabilityBody.tags` | maxItems | 50 |
| `VehicleAvailabilityBody.vehicleIds` | maxItems | 100 |
| `tagIds` | maxItems | 50 |
| `entityTypes` | maxItems | 50 |
| `ServiceCreateBody.tags` | maxItems | 50 |
| `ServiceCreateBody.requirements` | maxItems | 20 |
| `ServiceCreateBody.requirements[].requiredTags` | maxItems | 20 |
| `ServiceUpdateBody.requirements[].requiredTags` | maxItems | 20 |
| `layers` | maxItems | 50 |
| `projectStatus` | maxItems | 50 |
| `orderStatus` | maxItems | 50 |
| `assignedToStaffIds` | maxItems | 200 |
| `scopes` | maxItems | 50 |
| `priorities` | maxItems | 50 |
| `severities` | maxItems | 50 |
| `assignedStaffIds` | maxItems | 50 |
| `relatedDocumentIds` | maxItems | 50 |
| `TaskCreateBody.assignedStaffIds` | maxItems | 50 |
| `TaskUpdateBody.assignedStaffIds` | maxItems | 50 |
| `invoiceIds` | maxItems | 50 |
| `ContactsLookupBody.references` | maxItems | 200 |
| `OrderLineItemsReturnBody.items` | maxItems | 500 |
| `triggerTypes` | maxItems | 50 |
| `InvoiceExternalUpsertBody.lines` | maxItems | 500 |

- Lists that paginate return at most 500 records per page (`limit`, default 50). `cursor` and `sort` accept at most 200 characters. A few small lists have no pagination and return everything in one response: check the operation for a `cursor` parameter.
- A question to [`POST /api/v1/ai/ask`](https://docs.filmo.io/rest-api/endpoint-reference/ai/ask-the-ai-about-your-data) is at most 4000 characters, and the only mode today is a single pass: there is no conversation to continue.
- A contact update accepts at most 20 addresses, 20 emails, 20 phone numbers and 20 websites.
- Creating an order accepts at most 100 lines, and an availability check at most 100 items. Checking the availability of staff or vehicles accepts at most 100 identifiers.
- A contact lookup accepts at most 200 references.
- A line-item return and an external invoice each accept at most 500 lines.
- List filters that accept several values, such as `statuses`, take up to 50 of them; [`assignedToStaffIds`](https://docs.filmo.io/rest-api/endpoint-reference/schedule/get-the-schedule-for-a-range#param-assignedToStaffIds) takes up to 200.

Rate limits are a separate matter: 120 requests per minute per key, and 30 per minute shared by the three availability queries. See [rate limits](https://docs.filmo.io/rest-api/guides/rate-limits).

## Platform limits

Filmo runs the API on a hosting platform, and the platform bounds how large a request or a response can be and how long one call may last. Filmo does not publish the size limits as part of the contract, and apart from one operation it documents no duration limit either, so do not design around a specific size or duration.

- Keep requests small. Send large changes as several writes, each with its own `Idempotency-Key`.
- Keep pages at a size you have measured. A page of 500 records of a large object is a big response; if you see failures, lower `limit`.
- Over REST, [`POST /api/v1/ai/ask`](https://docs.filmo.io/rest-api/endpoint-reference/ai/ask-the-ai-about-your-data) is allowed to run for up to 300 seconds and can take tens of seconds on questions that chain several queries. Allow a long client timeout, above 300 seconds, and do not retry before it expires. Through MCP, do not assume the same allowance. For every other operation there is no documented duration limit: set your own timeouts and handle a 504.
- The platform itself generates the 413, 502 and 504 responses; they are never `application/problem+json` and have no `code`. Branch on the HTTP status, not on the body. A 502 or a 504 on a write does not tell you whether the write happened: retry it with the same `Idempotency-Key`.

## Known gaps

This table lists the documented limitations and the information or functionality needed to resolve each one. Entries are removed as they are resolved.

| Gap | What would close it | Expected |
| --- | --- | --- |
| Field codes of validation errors | The codes in `errors[].code` of a `validation_error` are not a closed list; until the contract closes it, treat a code you do not know as a generic validation failure. | — |
| Synchronisation semantics | Whether a change in lines, payments or status updates the parent's `updatedAt`, the delay between writing and committing it, the filter precision, what archiving or restoring does to `updatedAt`, and a tombstone or `deletedSince`; until then the guides recommend the conservative option. | — |
| The OAuth contract | Whether the OAuth contract will gain audience binding (`resource`), a revocation endpoint (RFC 7009) and confidential clients. Today a token has no audience, there is no revocation endpoint (the administrator revokes the connection in the settings) and every client is public; the OAuth pages describe it as it works. | — |
| Platform limits | The platform's limits on the size of a request and of a response, and on the duration of a call, which Filmo documents only for `askAi`; until then the pages say so and advise small requests and pages you have measured. | — |
| External key for contacts and orders | The field `POST /contacts/lookup` compares, a writable external reference on contacts and orders, and optionally a change-origin field; until then the guides match on `email` or `contactNumber` and keep a correspondence table. | — |
| Events fired by writes through the API | The exact correspondence between every endpoint and its workflow events, whether a request will ever be able to suppress them, and loop protection for a workflow that calls the API with a key. Known from the code: writes through the REST API and MCP fire the same events as the app, with `origin` set to API or MCP; a workflow trigger can filter by origin, but a request cannot suppress events; a chain of workflows is cut at ten hops. The pages say what is known and mark the rest as an inference. | — |
| Integrators with many accounts | Partner or development accounts, and the process to appear in /integrations; until then the page is reduced. | — |
| Fiscal data for accounting | `taxBreakdown`, lines and credit-note reasons, a fiscal snapshot of the invoice and the tax type per line; until then they are listed under "Not available in v1". | — |
| MCP client requirements the vendor does not document | The vendors' own documentation (plans, tool limits, organisation settings); the pages say "not documented by the vendor" where it is not. | — |

---

Canonical URL: https://docs.filmo.io/further-reading/capabilities-and-limits  
Last updated: 2026-10-09