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.
| Kind | In the OpenAPI document | In JSON | Handle it as |
|---|---|---|---|
| Money | string with pattern ^-?\d+\. | "1234. | A decimal. Never a float. |
| Instant | string, format: date-time | "2026-10-17T08:00:00. | A timestamp. Responses are UTC; writes take an offset. |
| Bare day | string, format: date | "2026-10-17" | A calendar day with no time zone. |
| Day or instant | anyOf of format: date and format: date-time | Either of the two above | Filters accept both. |
| Nullable | type: ["string", "null"] | null | Present, with no value. |
| Map | object with additionalProperties | { "cf_123": "Acme" } | A dictionary keyed by identifier. |
| Identifier | string | "5e8d1a9c" | Opaque. Never parse it. |
Money is a decimal string
Link to this section: Money is a decimal stringEvery monetary amount is serialized as a decimal string with two decimals, rounded half up: for example grossPrice is "1234.. It is never a floating-point number, so no precision is lost. Do the arithmetic with a decimal type or with integer cents, and send amounts back as strings. The currency is that of the document, and the account's default is in currency; see Amounts and currencies.
Dates and times
Link to this section: Dates and timesInstants
Link to this section: InstantsDates with a time are ISO 8601 strings. Responses use UTC (Z). A write takes an instant with an offset, such as 2026-10-17T10:00:00+02:00, and stores the instant; responses return it in UTC. REST writes need an instant with an offset, not a bare day: for example startDate.
Bare days
Link to this section: Bare daysA few places accept a bare day (YYYY-MM-DD): the date filters of lists, and the invoiceDate and dueDate of PUT /api. In filters it is read in the business timezone of the account, which you get from timezone. A bare day in a filter is read in that timezone, not in UTC. See Filtering and sorting and Dates and times.
Day or instant
Link to this section: Day or instantDate filters are declared as a union of format: date and format: date-time. In OpenAPI 3.1 that is an anyOf, and a generated client usually types it as string. Send either form; the server decides by its shape.
Nullable values
Link to this section: Nullable valuesOpenAPI 3.1 writes a nullable property as a type list, type: ["string", "null"]. A nullable property that is listed as required is always present in the response and may be null: for example the contact of an order is null when the order has none. When you write, check the body schema of the operation before you send null: an optional property and a nullable one are different things.
Custom field values come back as a map from custom field identifier to value, such as customFields. The values can be of any JSON type, and the definitions are in GET /api. Iterate the keys you receive instead of assuming a fixed set.
const order = {
grossPrice: "1234.50",
startDate: "2026-10-17T08:00:00.000Z",
customFields: { cf_123: "Acme", cf_456: 3 },
contact: null,
};
// Money: keep it as a string, or count in cents. Never Number("1234.50") for arithmetic.
const toCents = (amount) => BigInt(amount.replace(".", ""));
const fromCents = (cents) => {
const sign = cents < 0n ? "-" : "";
const digits = (cents < 0n ? -cents : cents).toString().padStart(3, "0");
return sign + digits.slice(0, -2) + "." + digits.slice(-2);
};
console.log(fromCents(toCents(order.grossPrice) + toCents("0.05"))); // 1234.55
// Instants: parse them and keep working in UTC; format for people only at the edge.
const start = new Date(order.startDate);
console.log(start.toISOString());
// Nullable: the property is there, the value may be null.
console.log(order.contact?.name ?? "no contact");
// Maps: iterate the keys you get, whatever they are.
for (const [fieldId, value] of Object.entries(order.customFields)) console.log(fieldId, value);from datetime import datetime
from decimal import Decimal
order = {
"grossPrice": "1234.50",
"startDate": "2026-10-17T08:00:00.000Z",
"customFields": {"cf_123": "Acme", "cf_456": 3},
"contact": None,
}
# Money: Decimal from the string, never float.
total = Decimal(order["grossPrice"]) + Decimal("0.05")
print(f"{total:.2f}") # 1234.55
# Instants: parse them and keep working in UTC; format for people only at the edge.
start = datetime.fromisoformat(order["startDate"].replace("Z", "+00:00"))
print(start.isoformat())
# Nullable: the key is there, the value may be None.
print((order["contact"] or {}).get("name", "no contact"))
# Maps: iterate the keys you get, whatever they are.
for field_id, value in order["customFields"].items():
print(field_id, value)Tolerate the unknown
Link to this section: Tolerate the unknown- Ignore properties you do not recognize. Filmo adds properties to responses within v1 without notice.
- Accept enum values you do not know. Most statuses are closed unions today, and a new value is a documented additive change. The
statusof some schemas is a plain string in the spec, not an enum:SerializedItemDto,SerializedItemDetailDto,InternalServiceDto,PlannerServiceDto,PlannerAssignResultDto,PlannerUnassignResultDto,IncidentDto,SupplierInvoiceDto,CreditNoteDtoandProformaDto. Tolerate any value there. - Do not reject a response because a property you expected to be a string is
null.
The rules for what may change are in Versioning.
Related pages
Link to this section: Related pagesFurther reading
Dates and times
Responses give dates in UTC. When you write, send an ISO 8601 instant with an offset. A bare day such as
2026-10-17is read in the business time zone of the account when it is in a filter; a write takes one only in a field that is a plain date.Further reading
Amounts and currencies
Every monetary amount is a decimal string with two decimals, such as
"1234., never a floating-point number, with one exception: the prices in the50" priceConfiganddefaultExpensesof a service and thecustomPriceof an accessory are JSON numbers. Each document carries its own currency, which can differ from the account's.Guides
Responses
Successful responses wrap their payload in
data; lists addpagination; a few operations addmeta; errors are RFC 9457 problems. API responses share one set of headers.
Was this page helpful?