Guides
Multi-account integrations
Give each customer account its own credential, store it with that account's timezone and currency, and treat a failing credential as the state of one connection, not of your whole product. OAuth is available for a server you run, and API keys are simpler for server-to-server work.
This guide is for teams that build a product, such as a CRM, an accounting package, a booking site or an inventory tool, that connects to many rental companies. That is the case the API was designed for: third-party integrations. If you integrate with one company's account, the quickstart and the sync guide are enough.
One credential per customer account
Link to this section: One credential per customer accountA credential belongs to one Filmo subscription, so one credential can never serve two customers. You can obtain it in two ways.
| API key | OAuth connection | |
|---|---|---|
| Who creates it | An administrator of the customer, in the API and MCP settings of the app (Ajustes → API y MCP). | An administrator of the customer, on the consent screen. That is where the subscription is chosen. Only read permissions start selected; write permissions, workflows:run and ai:ask start unselected even if you ask for them, and the administrator turns on the ones they accept. |
| Lifetime | Until it is revoked, or until the expiry you set when you created it. It has no expiry by default. | The access token lasts 1 hour. The refresh token lasts 30 days, counted again at every rotation, so a connection that is refreshed at least every 30 days lives on. |
| Permissions | The scopes chosen when it was created. | The scopes actually granted, which may differ from the ones requested (fewer, or extra ones the administrator ticked). |
| Revocation | In the same settings (Ajustes → API y MCP). It stops working at once. | The same screen, where it appears as a single connected integration. The access token stops working at once and the refresh token can no longer be exchanged. |
| Fit | Simplest for server-to-server integrations: one secret per customer, nothing to refresh. | Works for REST from your server, at the price of a refresh cycle and a consent by an administrator of each account. |
The token OAuth issues is a short-lived API key that works on the whole REST API and on MCP, and it travels the same way, as a Bearer token. A third-party server can use it today: it registers as a public client, sends the administrator through the authorization code flow with PKCE, and exchanges the code for tokens. OAuth is viable now, and a key is simpler when no person is in front of the flow. See OAuth for the flow.
- There is no
client_credentialsgrant, no confidential client and no client secret. Your client is public: it registers dynamically and authenticates with PKCE alone. - Every connection needs an administrator of that account to consent. You cannot connect an account without one.
- A grant covers one subscription, which the administrator chooses while consenting, and the granted scopes may differ from the ones you requested (fewer, or extra ones the administrator ticked). A customer with several billing accounts needs one grant, or one key, for each of them.
- A subscription can have 50 keys that are not revoked (expired ones count, and so do OAuth connections); the limit blocks creating a new key by hand.
Keep recommending one key or one connection per customer, and never share a credential between two accounts or two environments.
What to store for each customer
Link to this section: What to store for each customerThe first call of any integration is GET /api, with the scope account:read. Call it when a customer connects and keep what it returns.
| Store | Why |
|---|---|
| The credential, encrypted | A key, or the access and refresh tokens of an OAuth connection. It is shown only once. |
timezone | Bare days in filters are read in this timezone, and you need it to show times to people the way the customer sees them. |
currency | The account's currency. A document may carry its own. |
apiKey | The key's id, name and granted scopes. Compare the scopes with the ones you need whenever a call answers 403. |
addons | A resource behind an add-on that is not listed answers 402. |
| The state of the connection | Active, or needs attention, with the time of the last good call and the last X-Request-Id you saw. |
| One watermark per list | See the sync guide. Watermarks belong to the customer, not to your product. |
Tenancy across a customer's accounts
Link to this section: Tenancy across a customer's accountsWhat a credential can see depends on how Filmo models each resource (Accounts and tenancy). Two rules matter for an integration.
| Semantics | Resources | What the credential sees |
|---|---|---|
| Inherited from the parent account | Contacts, projects, tags and custom fields, and reading an order by id. | A billing account also sees these resources of its parent account. A full account, or a subscription outside any organization, sees its own. |
| Strict subscription equality | Everything else, including items, spaces, invoices, quotes, tasks, vehicles, staff, subrents, purchase orders, contracts, the order list and availability. | Exactly the subscription that owns the credential. |
Nothing widens between sibling billing accounts, nor from a parent to its billing accounts, and no operation crosses data between organizations. So, to read the orders and invoices of every billing account of one organization, connect each of them. When you merge their data, deduplicate the inherited resources by id: the same contact appears through every billing account that inherits it.
Request budget
Link to this section: Request budgetEach key has 120 requests per minute, and the three availability queries share a further 30 per minute on the same key. The limits are the same for every plan (Rate limits). A credential is the unit of the limit, so give each customer its own queue, read RateLimit-Remaining and RateLimit-Reset to pace it, and wait Retry-After seconds after a 429. Workers that serve the same customer share one budget.
OAuth has its own limits, counted per IP address and not per credential. Registering a client allows 5 requests per minute per IP, and the token endpoint 120 per minute per IP, so the refreshes of all your customers share that budget when they leave from the same server. A 429 from an OAuth endpoint carries Retry-After: wait that long, and decide by the status and the header, not by the body, because the body does not always name the limit.
OAuth: refreshing without breaking the connection
Link to this section: OAuth: refreshing without breaking the connectionThis section applies if you use OAuth connections. With API keys there is nothing to refresh.
The access token expires in 1 hour and the refresh token rotates on every use: each exchange returns a new refresh token, and the previous access token stops working at once. If a worker presents a refresh token that was already rotated, Filmo answers with the same pair when the request comes from the same client within 10 seconds of the rotation. After that window, reusing it revokes the whole chain, the access token and every refresh token, and answers invalid_grant. The customer then has to consent again. Two workers that refresh at the same moment usually receive the same pair, but a worker that arrives later than 10 seconds destroys the connection for everyone, so serialize the refresh anyway.
OAuth endpoints answer in the flat OAuth format, { "error", "error_description" }, not in the problem format of the rest of the API. The error_description is in Spanish: branch on error and show your own text.
Serialize the refresh per customer
Take a lock for that customer's connection around the whole refresh: a database row lock, an advisory lock, or a lock with an expiry in a shared store. Never refresh outside it.
Read the stored tokens after you get the lock
Another worker may have refreshed while you waited. If the stored access token is still valid, use it and release the lock.
Refresh with the stored refresh token
Call
POST /apiwith/v1 /oauth /token grant_type=refresh_token, therefresh_tokenand yourclient_id. The response carries a newrefresh_token, valid for another 30 days.Persist both new tokens before anything else
Write the new access token and the new refresh token to storage before you use the access token and before you release the lock. If you lose the new refresh token, the connection is lost.
Refresh before expiry, not on a 401
Refresh a few minutes before the hour is up, so that request threads rarely race for the lock.
Treat invalid_grant as final: the refresh token is expired, revoked or already used, or the administrator who consented is no longer an administrator. Do not retry it. Mark the connection as needing attention and ask the customer's administrator to consent again.
When a customer's connection stops working
Link to this section: When a customer's connection stops workingHandle each failure as the state of one connection: stop calling with that credential, keep the watermarks, tell the customer's administrator, and resume after they reconnect. Do not retry in a loop.
| Response | Meaning | What to do |
|---|---|---|
401 api_key_invalid, api_key_revoked, api_key_expired | The key is not recognised (a key copied wrongly or truncated lands here too: check your value first), was revoked or has expired. | Check that the value you send is complete. If it is, ask the administrator for a new key, or to consent again. For an OAuth connection, a 401 api_key_expired means the access token ran out: refresh it before you conclude that anything is wrong. |
401 api_key_owner_inactive, api_key_owner_not_admin | The key is fine; the person who owns it left the account, was deactivated, or stopped being an administrator. | Ask an administrator who is still one to reissue the key, or to consent again. The same applies to OAuth connections. |
401 unauthorized | The Authorization: Bearer header is missing. | Fix your request. Nothing is wrong on the customer's side. |
403 insufficient_scope | The credential lacks the scope named in requiredScope. | Ask for a new key or a new consent with that scope. |
403 forbidden | The owner of the credential lacks a permission that the operation requires. | An administrator of the account grants it. |
402 addon_required | The customer's account has not contracted the add-on named in requiredAddon. | Turn the feature off for that customer and say why. |
429 rate_limited | The key's quota ran out. | Wait Retry-After seconds (the problem body repeats the value in retryAfter). |
Handover checklist for the customer's administrator
Link to this section: Handover checklist for the customer's administratorGive this list to the administrator who connects your product. Fill in the scopes from your own needs, and ask for no more.
Choose a dedicated owner
A key acts as the administrator who creates it, and what it writes is attributed to that person. It hangs from that administrator, who already has a seat in the account, and it stops working if that person leaves or stops being an administrator. Create it from an administrator account that will last, not from a person who may move on.
Open the API and MCP settings
In the app it is Ajustes → API y MCP. Only administrators can create keys.
Create one key for the integration
Name it after your product and give it only the scopes you list, for example
account:readplus the read and write scopes of the resources you sync. The scopes are in the scopes reference.Hand it over once, through a secure channel
The key is shown only once. Receive it in your onboarding form or a shared secrets manager, never by email or chat.
Explain revocation
Revoking the key in the same settings cuts access at once. Tell the administrator what stops working when they do, and what to do if the owner of the key leaves.
Development accounts
Link to this section: Development accountsFilmo offers no sandbox and no test key, and this guide describes no partner or developer account type. Develop and run your tests against a separate Filmo account that holds fictitious data (contacts at example., made-up item names), with its own key stored apart from any customer's. A free trial of 14 days, with no card, can serve for that. Never develop against a customer's account. Writes fire the account's event workflows, so check which are active before you write; see Testing and the sync guide.
If you are building a product for many Filmo customers and want to talk to Filmo about it, see Support.
Related pages
Link to this section: Related pagesGuides
Authentication
Every operation requires an API key sent as a bearer token. Only an administrator can create a key, and the key acts as that administrator, so decide who owns it before you create it.
Guides
OAuth
Filmo implements OAuth 2.1 for public clients: authorization code with PKCE, no client secret. The token it issues is an API key of kind OAuth, so it works on the whole REST API and on MCP, with the scopes the administrator granted.
Guides
Scopes
A key carries scopes; each operation requires exactly one. Grant the fewest you need.
Guides
Rate limits
Each API key has 120 requests per minute, and the three availability checks share their own quota of 30 per minute. Past a limit the API answers 429 with
Retry-After.Guides
Syncing data
Filmo v1 does not send webhooks, so you keep another system in step by polling: read what changed in half-open time windows, and run a separate sweep to find what was deleted. Do not follow the pagination cursor to decide what changed or what disappeared.
Guides
Testing your integration
Start with a read-only key, check the account's automations before the first write, and keep irreversible operations out of any account that holds real data.
Guides
Going live checklist
Go through these eight checks before your integration runs against production data. Each one points to the guide that explains it.
Core concepts
Accounts and tenancy
A key is bound to one subscription. Most resources are limited to exactly that subscription; contacts, projects, tags and custom fields are also visible from a billing account's parent.
Was this page helpful?