Endpoints de la API. Especificación exacta de cada operación de la API v1 (parámetros, cuerpo, respuestas y ejemplos), generada del documento OpenAPI con el que se valida cada respuesta real. Los procedimientos completos están en Guías.
/transfer-orders
Crear una orden de transferencia
Crea una orden en borrador o, con release: true, la libera para surtido de inmediato. Con un cliente de
integración, liberar exige picker_id (el surtidor). Un external_ref que ya existe responde 200 con esa orden.
- Alcance (cliente de integración)
transfers:write- Permiso (token de usuario)
transfer-orders.manage- Idempotency-Key
- Opcional
- Requisitos
- Órdenes de transferencia activas
Cabeceras
-
Idempotency-KeystringLlave única por operación (se recomienda un UUID v4). Reenviar la misma solicitud con la misma llave en las siguientes 24 horas devuelve la respuesta original sin repetir la operación.
Cuerpo de la solicitud application/json
-
from_warehousestring obligatorioCódigo del almacén de origen.
-
to_warehousestring obligatorioCódigo del almacén de destino.
-
priorityinteger | null -
reasonstring | null -
due_atstring (date-time) | null -
external_refstring | nullReferencia externa; no se crea dos veces.
-
releaseboolean | nulltruelibera la orden para surtido al crearla. -
picker_idinteger | nullEl surtidor al liberar. Obligatorio con
releasey un cliente de integración. -
linesarray de objetos obligatorio5 campos de
lines-
item_codestring obligatorio -
qtynumber obligatorio -
batch_numstring | null -
expected_seriesarray de textos | null -
expected_batchesarray de textos | null
-
Respuestas
200
Ya existía una orden con ese external_ref; se devuelve esa.
-
dataobjeto obligatorio26 campos de
data-
objectstring «transfer_order» obligatorio -
idinteger obligatorio -
codestring obligatorio -
statusstring obligatorioValores:draft,released,picking,picked,in_transit,receiving,received,closed,cancelled -
status_labelstring -
headlinestring | null -
has_discrepancybooleanLo recibido no coincide con lo despachado.
-
fromobjeto obligatorio3 campos de
from-
idinteger | null -
codestring | null -
namestring | null
-
-
toobjeto obligatorio3 campos de
to-
idinteger | null -
codestring | null -
namestring | null
-
-
priorityinteger -
reasonstring | null -
due_atstring (date-time) | null -
lines_countinteger -
unitsobjeto obligatorio4 campos de
units-
requestednumber -
pickednumber -
dispatchednumber -
receivednumber
-
-
dispatched_atstring (date-time) | null -
received_atstring (date-time) | null -
closed_atstring (date-time) | null -
seal_numberstring | null -
vehicle_platestring | null -
carrier_idinteger | null -
external_refstring | null -
sourcestringValores:web,api,import,sap -
picking_idinteger | null -
receipt_idinteger | null -
sapobjeto | nullEstado del envío al ERP cuando aplica.
-
linesarray de objetos | nullnullen el listado; en el detalle, las líneas.11 campos de
lines-
idinteger -
line_numinteger -
product_idinteger | null -
item_codestring | null -
qtynumber -
picked_qtynumber -
dispatched_qtynumber -
received_qtynumber -
batch_numstring | null -
serial_numbersarray de textos -
statusstring
-
-
201
Orden creada. Location apunta al nuevo recurso.
-
dataobjeto obligatorio26 campos de
data-
objectstring «transfer_order» obligatorio -
idinteger obligatorio -
codestring obligatorio -
statusstring obligatorioValores:draft,released,picking,picked,in_transit,receiving,received,closed,cancelled -
status_labelstring -
headlinestring | null -
has_discrepancybooleanLo recibido no coincide con lo despachado.
-
fromobjeto obligatorio3 campos de
from-
idinteger | null -
codestring | null -
namestring | null
-
-
toobjeto obligatorio3 campos de
to-
idinteger | null -
codestring | null -
namestring | null
-
-
priorityinteger -
reasonstring | null -
due_atstring (date-time) | null -
lines_countinteger -
unitsobjeto obligatorio4 campos de
units-
requestednumber -
pickednumber -
dispatchednumber -
receivednumber
-
-
dispatched_atstring (date-time) | null -
received_atstring (date-time) | null -
closed_atstring (date-time) | null -
seal_numberstring | null -
vehicle_platestring | null -
carrier_idinteger | null -
external_refstring | null -
sourcestringValores:web,api,import,sap -
picking_idinteger | null -
receipt_idinteger | null -
sapobjeto | nullEstado del envío al ERP cuando aplica.
-
linesarray de objetos | nullnullen el listado; en el detalle, las líneas.11 campos de
lines-
idinteger -
line_numinteger -
product_idinteger | null -
item_codestring | null -
qtynumber -
picked_qtynumber -
dispatched_qtynumber -
received_qtynumber -
batch_numstring | null -
serial_numbersarray de textos -
statusstring
-
-
401 Falta el token o no es válido.
Cuerpo: el sobre de error.
402 La función no está en el plan de la empresa, o la cuenta está suspendida o cancelada.
Cuerpo: el sobre de error.
403
Al cliente le falta el alcance (missing_scope), al usuario el permiso (forbidden), o el token de usuario no
tiene acceso a la ruta (client_not_allowed: aplicación móvil o usuario con verificación en dos pasos).
Cuerpo: el sobre de error.
404 El módulo no está activo en la empresa.
Cuerpo: el sobre de error.
409
Otra solicitud con la misma Idempotency-Key sigue en proceso.
Cuerpo: el sobre de error.
422
Datos no válidos (validation_failed), una llave de idempotencia reutilizada con otra solicitud
(idempotency_key_reused) o una regla de negocio que bloquea la operación (rule_blocked).
Cuerpo: el sobre de error.
429
Se superó el límite por minuto. Reintente después de los segundos de Retry-After.
Cuerpo: el sobre de error.
Probar
Probar con una instancia
curl -X POST "https://empresa.chainlink.mx/api/v1/transfer-orders" \
-H "Authorization: Bearer $CHAINLINK_TOKEN" \
-H "Accept: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"from_warehouse": "CEDIS-GDL",
"to_warehouse": "TDA-MTY",
"priority": 50,
"reason": "Reabasto semanal",
"due_at": "2026-10-08T18:00:00-06:00",
"external_ref": "TR-2026-0107",
"lines": [
{
"item_code": "P-1001",
"qty": 24
}
]
}'
<?php
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://empresa.chainlink.mx/api/v1/transfer-orders', [
'headers' => [
'Authorization' => 'Bearer ' . getenv('CHAINLINK_TOKEN'),
'Accept' => 'application/json',
'Idempotency-Key' => (string) \Ramsey\Uuid\Uuid::uuid4(),
],
'json' => [
'from_warehouse' => 'CEDIS-GDL',
'to_warehouse' => 'TDA-MTY',
'priority' => 50,
'reason' => 'Reabasto semanal',
'due_at' => '2026-10-08T18:00:00-06:00',
'external_ref' => 'TR-2026-0107',
'lines' => [
[
'item_code' => 'P-1001',
'qty' => 24,
],
],
],
]);
$data = json_decode((string) $response->getBody(), true);
const response = await fetch('https://empresa.chainlink.mx/api/v1/transfer-orders', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.CHAINLINK_TOKEN}`,
Accept: 'application/json',
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID(),
},
body: JSON.stringify({
"from_warehouse": "CEDIS-GDL",
"to_warehouse": "TDA-MTY",
"priority": 50,
"reason": "Reabasto semanal",
"due_at": "2026-10-08T18:00:00-06:00",
"external_ref": "TR-2026-0107",
"lines": [
{
"item_code": "P-1001",
"qty": 24
}
]
}),
});
const data = await response.json();
import os
import uuid
import requests
response = requests.post(
"https://empresa.chainlink.mx/api/v1/transfer-orders",
headers={
"Authorization": f"Bearer {os.environ['CHAINLINK_TOKEN']}",
"Accept": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"from_warehouse": "CEDIS-GDL",
"to_warehouse": "TDA-MTY",
"priority": 50,
"reason": "Reabasto semanal",
"due_at": "2026-10-08T18:00:00-06:00",
"external_ref": "TR-2026-0107",
"lines": [
{
"item_code": "P-1001",
"qty": 24
}
]
},
)
data = response.json()
{
"data": {
"object": "transfer_order",
"id": 1,
"code": "TR-000001",
"status": "draft",
"status_label": "Borrador",
"headline": "TR-000001 · De CEDIS-GDL a TDA-MTY · Borrador",
"has_discrepancy": false,
"from": {
"id": 1,
"code": "CEDIS-GDL",
"name": "CEDIS Guadalajara"
},
"to": {
"id": 2,
"code": "TDA-MTY",
"name": "Tienda Monterrey"
},
"priority": 0,
"reason": null,
"due_at": null,
"lines_count": 1,
"units": {
"requested": 24,
"picked": 0,
"dispatched": 0,
"received": 0
},
"dispatched_at": null,
"received_at": null,
"closed_at": null,
"seal_number": null,
"vehicle_plate": null,
"carrier_id": null,
"external_ref": "TR-2026-0107",
"source": "api",
"picking_id": null,
"receipt_id": null,
"sap": {
"dispatch": null,
"receipt": null
},
"lines": [
{
"id": 1,
"line_num": 1,
"product_id": 1,
"item_code": "P-1001",
"qty": 24,
"picked_qty": 0,
"dispatched_qty": 0,
"received_qty": 0,
"batch_num": null,
"serial_numbers": [],
"status": "open"
}
]
}
}
{
"data": {
"object": "transfer_order",
"id": 1,
"code": "texto",
"status": "draft",
"status_label": "texto",
"headline": "texto",
"has_discrepancy": true,
"from": {
"id": 1,
"code": "texto",
"name": "texto"
},
"to": {
"id": 1,
"code": "texto",
"name": "texto"
},
"priority": 1,
"reason": "texto",
"due_at": "2026-10-06T16:20:11.000000Z",
"lines_count": 1,
"units": {
"requested": 1.0,
"picked": 1.0,
"dispatched": 1.0,
"received": 1.0
},
"dispatched_at": "2026-10-06T16:20:11.000000Z",
"received_at": "2026-10-06T16:20:11.000000Z",
"closed_at": "2026-10-06T16:20:11.000000Z",
"seal_number": "texto",
"vehicle_plate": "texto",
"carrier_id": 1,
"external_ref": "texto",
"source": "web",
"picking_id": 1,
"receipt_id": 1,
"sap": [],
"lines": [
{
"id": 1,
"line_num": 1,
"product_id": 1,
"item_code": "texto",
"qty": 1.0,
"picked_qty": 1.0,
"dispatched_qty": 1.0,
"received_qty": 1.0,
"batch_num": "texto",
"serial_numbers": [
"texto"
],
"status": "texto"
}
]
}
}
{
"error": {
"code": "unauthenticated",
"message": "Falta el token de acceso o ya no es válido.",
"doc_url": "https://chainlink.mx/developers/errores#unauthenticated",
"request_id": "req_01j9x2m4k7q8r5t6v3w0y1z2a3"
},
"errors": [],
"message": "Falta el token de acceso o ya no es válido."
}
{
"error": {
"code": "feature_not_in_plan",
"message": "Función no disponible en tu plan actual.",
"feature": "webhooks.enabled",
"upgrade_url": "/billing/plans",
"doc_url": "https://chainlink.mx/developers/errores#feature_not_in_plan",
"request_id": "req_01j9x2m4k7q8r5t6v3w0y1z2a3"
},
"errors": [],
"message": "Función no disponible en tu plan actual."
}
{
"error": {
"code": "missing_scope",
"message": "El cliente no tiene el alcance products:write.",
"scope": "products:write",
"doc_url": "https://chainlink.mx/developers/errores#missing_scope",
"request_id": "req_01j9x2m4k7q8r5t6v3w0y1z2a3"
},
"errors": [],
"message": "El cliente no tiene el alcance products:write."
}
{
"error": {
"code": "transfer_orders_disabled",
"message": "Las órdenes de transferencia no están activas en tu empresa.",
"doc_url": "https://chainlink.mx/developers/errores#transfer_orders_disabled",
"request_id": "req_01j9x2m4k7q8r5t6v3w0y1z2a3"
},
"errors": [],
"message": "Las órdenes de transferencia no están activas en tu empresa."
}
{
"error": {
"code": "duplicate_in_flight",
"message": "Esta solicitud ya se está procesando.",
"doc_url": "https://chainlink.mx/developers/errores#duplicate_in_flight",
"request_id": "req_01j9x2m4k7q8r5t6v3w0y1z2a3"
},
"errors": [],
"message": "Esta solicitud ya se está procesando."
}
{
"error": {
"code": "validation_failed",
"message": "El campo name es obligatorio.",
"field": "name",
"doc_url": "https://chainlink.mx/developers/errores#validation_failed",
"request_id": "req_01j9x2m4k7q8r5t6v3w0y1z2a3"
},
"errors": [
{
"field": "name",
"message": "El campo name es obligatorio."
}
],
"message": "El campo name es obligatorio."
}
{
"error": {
"code": "rate_limited",
"message": "Superaste el límite de solicitudes por minuto. Espera los segundos que indica Retry-After.",
"doc_url": "https://chainlink.mx/developers/errores#rate_limited",
"request_id": "req_01j9x2m4k7q8r5t6v3w0y1z2a3"
},
"errors": [],
"message": "Superaste el límite de solicitudes por minuto. Espera los segundos que indica Retry-After."
}