Los endpoints de fulfillment cubren la ruta desde un pedido aceptado hasta un paquete listo para salir: preparación, selección de paquetería, generación de guías y actualización de rastreo. Existen dos familias:
Por pedido (/orders/{orderId}/prepare, /orders/{orderId}/fulfill): pensados para flujos interactivos, un pedido a la vez.
En lote (/orders/fulfillment/*): pensados para procesar muchos pedidos en una sola llamada, típicamente desde el dashboard del comerciante o una tarea programada.
Envelope de respuesta
Toda respuesta exitosa de recurso único sigue { "data": {...} }; las listas usan { "data": [...], "meta": { "pagination": {...} } }. Los errores siempre son { "error": { "code", "message", "details?" } } con códigos namespace:snake_case (ej. orders:cannot_fulfill).
Para los eventos posteriores al envío (marcar como entregado, subir evidencia de entrega, adjuntar guía externa) consulta Entrega y Envíos.
Nombre de la paquetería cuando no está en el catálogo.
shippingCost
object
No
{ amount: number, currency: string }.
provider
string
No
Proveedor de envío que originó la cotización.
items es obligatorio
A diferencia de lo que sugiere el nombre, items no es opcional: se requiere al menos un elemento con itemIndex y quantityToPrepare. Enviar el arreglo vacío o solo una lista de SKUs es rechazado.
Cada objeto de capacidades trae más banderas además de las mostradas arriba (en total, alrededor de 13 campos por pedido). Los que se listan aquí están confirmados; para el listado exhaustivo consulta con soporte antes de depender de un campo no documentado.
Tamaño de la guía (relevante para impresoras térmicas).
options va anidado
format y size viajan dentro de options, no en la raíz del body: { "orderIds": [...], "options": { "format": "zpl", "size": "small" } }.
Shape de labels[] no auditado a detalle
summary está confirmado tal como se muestra. El shape exacto de cada elemento de labels[] (y del campo opcional mergedLabel) no fue auditado campo por campo contra el código fuente — confirma el contrato exacto con soporte antes de depender de un campo específico dentro de cada resultado.
Dentro de tracking, solo trackingNumber es requerido; carrierId, carrierName y trackingUrl son opcionales.
Este endpoint procesa un lote, no un pedido
El body no es { "orderId", "trackingNumber", "carrier" } a nivel raíz — es un arreglo updates[], y la información de rastreo va anidada bajo la clave tracking. El campo carrier (a secas) no existe en este endpoint.
Devuelve las paqueterías disponibles, según cómo la consultes: por pedidos, por canal, o el catálogo por defecto.
orderIdsstring[]
IDs de pedido — si los envías, la respuesta se resuelve por pedido.
channelTypestring
Tipo de canal — si lo envías (sin orderIds), la respuesta se resuelve por canal.
credentialsobject
Mapa channelId → credenciales, para uso orquestado.
{ "orderIds": ["65f3a1b2c4d5e6f7a8b9c0d1"]}
200
{ "data": { "mode": "by-orders" }}
Permiso requerido:orders:read
Respuesta discriminada por modo
Todos los parámetros son opcionales. La forma exacta de la respuesta depende del modo resuelto (by-orders, by-channel o default) y no fue auditada campo por campo para cada variante — el campo mode sí está confirmado como discriminador. Antes de parsear la respuesta programáticamente, valida el shape de cada modo con soporte.