*API REST › Guías*

# Tipos de datos

> El dinero es una cadena decimal, las fechas son ISO 8601, una propiedad puede estar presente y ser null, y los campos personalizados son mapas. Interpreta cada tipo una sola vez, en el borde de tu integración.

## Resumen

| Tipo | En el documento OpenAPI | En JSON | Trátalo como |
| --- | --- | --- | --- |
| Dinero | `string` con patrón `^-?\d+\.\d{2}$` | `"1234.50"` | Un decimal. Nunca un float. |
| Instante | `string`, `format: date-time` | `"2026-10-17T08:00:00.000Z"` | Una marca de tiempo. Las respuestas van en UTC; las escrituras aceptan un desplazamiento. |
| Fecha sin hora | `string`, `format: date` | `"2026-10-17"` | Un día de calendario sin zona horaria. |
| Día o instante | `anyOf` de `format: date` y `format: date-time` | Cualquiera de los dos anteriores | Los filtros aceptan ambos. |
| Admite null | `type: ["string", "null"]` | `null` | Presente, sin valor. |
| Mapear | `object` con `additionalProperties` | `{ "cf_123": "Acme" }` | Un diccionario indexado por identificador. |
| Identificador | `string` | `"5e8d1a9c"` | Opaco. No lo analices nunca. |

## El dinero es una cadena decimal

Todo importe monetario se serializa como una cadena decimal con dos decimales, redondeada al alza en el punto medio (half up): por ejemplo, [`grossPrice`](https://docs.filmo.io/es/rest-api/objects/order#response-grossPrice) es `"1234.50"`. Nunca es un número de coma flotante, así que no se pierde precisión. Haz la aritmética con un tipo decimal o con céntimos enteros, y devuelve los importes como cadenas. La moneda es la del documento, y la predeterminada de la cuenta está en [`currency`](https://docs.filmo.io/es/rest-api/objects/account#response-currency); consulta [Importes y monedas](https://docs.filmo.io/es/further-reading/amounts-and-currencies).

## Fechas y horas

### Instantes

Las fechas con hora son cadenas ISO 8601. Las respuestas usan UTC (`Z`). Una escritura toma un instante con desplazamiento, como `2026-10-17T10:00:00+02:00`, y almacena el instante; las respuestas lo devuelven en UTC. Las escrituras REST necesitan un instante con desplazamiento, no una fecha sin hora: por ejemplo `startDate`.

### Fechas sin hora

Unos pocos sitios aceptan una fecha sin hora (`YYYY-MM-DD`): los filtros de fecha de las listas y el `invoiceDate` y el `dueDate` de [`PUT /api/v1/invoices/external/{originSystem}/{originExternalId}`](https://docs.filmo.io/es/rest-api/endpoint-reference/invoices/create-or-update-the-mirror-of-an-externally-issued-invoice). En los filtros se lee en la zona horaria del negocio de la cuenta, que obtienes de [`timezone`](https://docs.filmo.io/es/rest-api/objects/account#response-timezone). Una fecha sin hora en un filtro se lee en esa zona horaria, no en UTC. Consulta [Filtrado y orden](https://docs.filmo.io/es/rest-api/guides/filtering-and-sorting) y [Fechas y horas](https://docs.filmo.io/es/further-reading/dates-and-times).

### Día o instante

Los filtros de fecha se declaran como una unión de `format: date` y `format: date-time`. En OpenAPI 3.1 eso es un `anyOf`, y un cliente generado suele tiparlo como `string`. Envía cualquiera de las dos formas; el servidor decide por su forma.

## Valores que admiten null

OpenAPI 3.1 escribe una propiedad que admite null como una lista de tipos, `type: ["string", "null"]`. Una propiedad que admite null y figura como obligatoria está siempre presente en la respuesta y puede ser `null`: por ejemplo, el `contact` de un pedido es `null` cuando el pedido no tiene ninguno. Cuando escribas, comprueba el esquema del cuerpo de la operación antes de enviar `null`: una propiedad opcional y una que admite null son cosas distintas.

## Mapas

Los valores de los campos personalizados llegan como un mapa del identificador del campo personalizado al valor, como [`customFields`](https://docs.filmo.io/es/rest-api/objects/order#response-customFields). Los valores pueden ser de cualquier tipo JSON, y las definiciones están en [`GET /api/v1/custom-fields`](https://docs.filmo.io/es/rest-api/endpoint-reference/custom-fields/list-custom-field-definitions). Recorre las claves que recibas en lugar de suponer un conjunto fijo.

*Analiza cada tipo en el borde*

**Node**

```javascript
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);
```

**Python**

```python
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)
```

## Tolera lo desconocido

- Ignora las propiedades que no reconozcas. Filmo añade propiedades a las respuestas dentro de v1 sin previo aviso.
- Acepta valores de enum que no conozcas. Hoy la mayoría de los estados son uniones cerradas, y un valor nuevo es un cambio aditivo documentado. El `status` de algunos esquemas es una cadena simple en la especificación, no un enum: `SerializedItemDto`, `SerializedItemDetailDto`, `InternalServiceDto`, `PlannerServiceDto`, `PlannerAssignResultDto`, `PlannerUnassignResultDto`, `IncidentDto`, `SupplierInvoiceDto`, `CreditNoteDto` y `ProformaDto`. Tolera cualquier valor ahí.
- No rechaces una respuesta porque una propiedad que esperabas como cadena sea `null`.

Las reglas sobre qué puede cambiar están en [Versionado](https://docs.filmo.io/es/rest-api/guides/versioning).

---

URL canónica: https://docs.filmo.io/es/rest-api/guides/data-types  
Última actualización: 2026-10-09