Guías

Paginación

Las listas devuelven una página cada vez. Pide una página con limit y, mientras pagination.hasMore sea true, vuelve a llamar con el nextCursor que te dieron.

Tu sistema
API
  1. GET /api/v1/orders?limit=50

    limit vale 50 por defecto y 500 como máximo. Añade includeTotal=true para recibir pagination.total.

  2. data y pagination { hasMore: true, nextCursor }

  3. Mientras hasMore sea true:

  4. GET /api/v1/orders?limit=50&cursor=<nextCursor>

    El mismo limit y el mismo sort: el cursor está ligado a los dos. El cursor es opaco; no lo construyas.

  5. Página siguiente

  6. hasMore: false: has leído todas las páginas.

El bucle de paginación
  1. 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.

  2. Leer la página

    Toma los registros de data. pagination.hasMore te indica si hay más resultados.

  3. Pide la siguiente

    Mientras hasMore sea true, vuelve a llamar con cursor igual a pagination.nextCursor, y con el mismo limit y los mismos filtros.

  4. Detener

    En la última página hasMore es false y nextCursor es null.

# 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
done
PropiedadTipoSignificado
nextCursorstring o nullCursor opaco de la página siguiente. null cuando no hay más resultados.
hasMorebooleanSi existen más resultados después de esta página.
totalintegerEl 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 limit con el que se envía.
  • Algunas listas no están paginadas: devuelven todo en una sola respuesta y no admiten limit, cursor ni sort. Son GET /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 /api/v1/planner/services y GET /api/v1/planner/resources. Las demás listas admiten limit y cursor.
  • Un cursor está ligado al limit y al sort con 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 id como 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 por id.
  • Pide total solo cuando lo necesites, con includeTotal. 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.

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

  • Filtrado y orden reduce lo que tiene que leer una pasada.
  • Errores cubre qué hacer cuando falla una petición de página.
  • Guías

    Filtrado y orden

    La mayoría de las listas aceptan sort y los filtros de tiempo created* y updated*, muchas aceptan filtros con lista de valores como statuses, y algunas aceptan q para 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?