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.

KindIn the OpenAPI documentIn JSONHandle it as
Moneystring with pattern ^-?\d+\.\d{2}$"1234.50"A decimal. Never a float.
Instantstring, format: date-time"2026-10-17T08:00:00.000Z"A timestamp. Responses are UTC; writes take an offset.
Bare daystring, format: date"2026-10-17"A calendar day with no time zone.
Day or instantanyOf of format: date and format: date-timeEither of the two aboveFilters accept both.
Nullabletype: ["string", "null"]nullPresent, with no value.
Mapobject with additionalProperties{ "cf_123": "Acme" }A dictionary keyed by identifier.
Identifierstring"5e8d1a9c"Opaque. Never parse it.

Every monetary amount is serialized as a decimal string with two decimals, rounded half up: for example grossPrice is "1234.50". 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 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.

A few places accept a bare day (YYYY-MM-DD): the date filters of lists, and the invoiceDate and dueDate of PUT /api/v1/invoices/external/{originSystem}/{originExternalId}. 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.

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

OpenAPI 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/v1/custom-fields. 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);
  • 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 status of some schemas is a plain string in the spec, not an enum: SerializedItemDto, SerializedItemDetailDto, InternalServiceDto, PlannerServiceDto, PlannerAssignResultDto, PlannerUnassignResultDto, IncidentDto, SupplierInvoiceDto, CreditNoteDto and ProformaDto. 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.

  • Further 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-17 is 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.50", never a floating-point number, with one exception: the prices in the priceConfig and defaultExpenses of a service and the customPrice of 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 add pagination; a few operations add meta; errors are RFC 9457 problems. API responses share one set of headers.

Was this page helpful?