Guías
Paginación
Las listas devuelven una página cada vez. Pide una página con limit y, mientras pagination. sea true, vuelve a llamar con el nextCursor que te dieron.
El bucle
Enlace a esta sección: El bucleGET /api/v1 /orders?limit=50 limitvale 50 por defecto y 500 como máximo. AñadeincludeTotal=truepara recibirpagination..total dataypagination { hasMore: true, nextCursor }Mientras
hasMoreseatrue:GET /api/v1 /orders?limit=50&cursor=<nextCursor> El mismo
limity el mismosort: el cursor está ligado a los dos. El cursor es opaco; no lo construyas.Página siguiente
hasMore: false: has leído todas las páginas.
Pide la primera página
Envía la petición de lista con
limit: de 1 a 500, 50 por defecto. No envíes un cursor.Leer la página
Toma los registros de
data.pagination.te indica si hay más resultados.hasMore Pide la siguiente
Mientras
hasMoreseatrue, vuelve a llamar concursorigual apagination., y con el mismonextCursor limity los mismos filtros.Detener
En la última página
hasMoreesfalseynextCursoresnull.
# Needs curl and jq. Prints one order per line.
base="${FILMO_BASE_URL:-https://app.filmo.io}"
cursor=""
while :; do
# Keep limit and sort identical on every page.
set -- --data-urlencode "limit=100" --data-urlencode "sort=createdAt"
[ -n "$cursor" ] && set -- "$@" --data-urlencode "cursor=$cursor"
page="$(curl -sS --fail-with-body -G "$base/api/v1/orders" \
-H "Authorization: Bearer $FILMO_API_KEY" "$@")" || { echo "$page" >&2; exit 1; }
echo "$page" | jq -c '.data[]'
cursor="$(echo "$page" | jq -r 'if .pagination.hasMore then .pagination.nextCursor else "" end')"
[ -n "$cursor" ] || break
doneconst base = process.env.FILMO_BASE_URL ?? "https://app.filmo.io";
const headers = { Authorization: `Bearer ${process.env.FILMO_API_KEY}` };
const orders = [];
let cursor = null;
do {
const url = new URL("/api/v1/orders", base);
url.searchParams.set("limit", "100"); // keep limit and sort identical on every page
url.searchParams.set("sort", "createdAt");
if (cursor) url.searchParams.set("cursor", cursor);
const res = await fetch(url, { headers });
if (!res.ok) throw new Error(res.status + " " + (await res.text()));
const page = await res.json();
orders.push(...page.data);
cursor = page.pagination.hasMore ? page.pagination.nextCursor : null;
} while (cursor);
console.log(orders.length + " orders");import os
import requests
base = os.environ.get("FILMO_BASE_URL", "https://app.filmo.io")
headers = {"Authorization": f"Bearer {os.environ['FILMO_API_KEY']}"}
orders, cursor = [], None
while True:
# Keep limit and sort identical on every page.
params = {"limit": 100, "sort": "createdAt"}
if cursor:
params["cursor"] = cursor
res = requests.get(base + "/api/v1/orders", headers=headers, params=params, timeout=30)
res.raise_for_status()
page = res.json()
orders += page["data"]
if not page["pagination"]["hasMore"]:
break
cursor = page["pagination"]["nextCursor"]
print(len(orders), "orders")El objeto de paginación
Enlace a esta sección: El objeto de paginación| Propiedad | Tipo | Significado |
|---|---|---|
nextCursor | string o null | Cursor opaco de la página siguiente. null cuando no hay más resultados. |
hasMore | boolean | Si existen más resultados después de esta página. |
total | integer | El número de resultados que coinciden con los filtros en todas las páginas. Solo está presente cuando la petición establece includeTotal en true. |
- Trata el cursor como opaco. No lo construyas, no lo interpretes ni lo guardes durante mucho tiempo; solo continúa el recorrido del que procede. Un cursor tiene como máximo 200 caracteres, y se rechaza uno que se haya alterado o que no coincida con el
limitcon el que se envía. - Algunas listas no están paginadas: devuelven todo en una sola respuesta y no admiten
limit,cursornisort. SonGET /api,/v1 /tags GET /api,/v1 /task-types GET /api,/v1 /crm /pipelines GET /api,/v1 /custom-fields GET /api,/v1 /project-types GET /api,/v1 /contacts /{contactId} /related-contacts GET /apiy/v1 /planner /services GET /api. Las demás listas admiten/v1 /planner /resources limitycursor. - Un cursor está ligado al
limity alsortcon los que se emitió. Mantén ambos idénticos en cada página de un recorrido. Consulta Filtrado y orden. - Cada lista tiene un orden determinista y estable: lo más reciente primero salvo que la operación diga otra cosa, con
idcomo desempate. La misma petición da el mismo orden, pero el cursor es una posición: los registros creados o eliminados mientras paginas pueden hacer que uno se repita o se omita, así que deduplica porid. - Pide
totalsolo cuando lo necesites, conincludeTotal. En otro caso se omite. - Una página más grande significa menos peticiones contra el límite de 120 por minuto. Con el máximo de 500, leer 10,000 registros requiere 20 peticiones. Consulta Límites de peticiones.
Cuando los registros cambian mientras paginas
Enlace a esta sección: Cuando los registros cambian mientras paginasSeguir el cursor puede saltarse registros
El cursor marca una posición en el resultado. Si un registro que ya has leído se actualiza o se borra mientras sigues paginando, los registros posteriores se desplazan, y uno en el límite de una página puede perderse; no se devuelve de nuevo en esa pasada. Una pasada que tolere esto, como una exportación puntual, puede seguir el cursor. El cursor es una posición, no una instantánea: si ordenas por updatedAt y un registro se actualiza mientras paginas, pasa al final de una pasada ascendente (y los registros siguientes pueden saltarse) o al principio de una descendente (y puedes leer un registro dos veces). Para mantener otro sistema sincronizado con Filmo, no te apoyes en el cursor: lee ventanas de tiempo con los filtros updated*. Sincronizar datos explica cómo.
Siguientes pasos
Enlace a esta sección: Siguientes pasos- Filtrado y orden reduce lo que tiene que leer una pasada.
- Errores cubre qué hacer cuando falla una petición de página.
Páginas relacionadas
Enlace a esta sección: Páginas relacionadasGuías
Filtrado y orden
La mayoría de las listas aceptan
sorty los filtros de tiempocreated*yupdated*, muchas aceptan filtros con lista de valores comostatuses, y algunas aceptanqpara búsqueda de texto libre. Los ejemplos usan la lista de pedidos.Guías
Sincronizar datos
Filmo v1 no envía webhooks, así que mantienes otro sistema sincronizado consultando periódicamente: lee lo que cambió en ventanas de tiempo semiabiertas y ejecuta un barrido aparte para encontrar lo que se eliminó. No sigas el cursor de paginación para decidir qué cambió o qué desapareció.
Guías
Límites de peticiones
Cada clave de API tiene 120 peticiones por minuto, y las tres comprobaciones de disponibilidad comparten su propia cuota de 30 por minuto. Al pasar un límite, la API responde 429 con
Retry-After.
¿Te ha resultado útil esta página?