Ejemplos
Ejemplos completos con curl y JavaScript (Node.js 18+, fetch nativo). Reemplazá RUTA_API por el dominio de tu courier.
curl: el ciclo completo en el entorno de prueba
Terminal
export RUTA_API='https://<tu-courier>'
export RUTA_API_KEY='ruta_test_…'
# Crear
ID=$(curl -s -X POST "$RUTA_API/api/v1/deliveries" \
-H "Authorization: Bearer $RUTA_API_KEY" -H "Idempotency-Key: pedido-2001" -H "Content-Type: application/json" \
-d '{"customerName":"Ana Pérez","address":"Av. Italia 1234","externalReference":"2001","amountToCollect":"850"}' \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')
# Corregir la dirección antes de que salga
curl -s -X PATCH "$RUTA_API/api/v1/deliveries/$ID" \
-H "Authorization: Bearer $RUTA_API_KEY" -H "Content-Type: application/json" \
-d '{"address":"Av. Italia 1234, apto 7"}'
# Simular el recorrido (sólo claves de prueba)
for action in ASSIGN PICK_UP START DELIVER SETTLE; do
curl -s -X POST "$RUTA_API/api/v1/deliveries/$ID/simulate" \
-H "Authorization: Bearer $RUTA_API_KEY" -H "Content-Type: application/json" \
-d "{\"action\":\"$action\"}" > /dev/null
done
# Ver el resultado, el comprobante y la etiqueta
curl -s "$RUTA_API/api/v1/deliveries?externalReference=2001" -H "Authorization: Bearer $RUTA_API_KEY"
curl -s "$RUTA_API/api/v1/deliveries/$ID/proof" -H "Authorization: Bearer $RUTA_API_KEY" # necesita proof:read
curl -s -o etiqueta.pdf "$RUTA_API/api/v1/deliveries/$ID/label" -H "Authorization: Bearer $RUTA_API_KEY"JavaScript: un cliente mínimo con reintentos seguros
JavaScript
const API = process.env.RUTA_API
const KEY = process.env.RUTA_API_KEY
async function ruta(method, path, { body, idempotencyKey } = {}) {
for (let attempt = 1; ; attempt++) {
let response
try {
response = await fetch(`${API}${path}`, {
method,
headers: {
Authorization: `Bearer ${KEY}`,
...(body ? { 'Content-Type': 'application/json' } : {}),
...(idempotencyKey ? { 'Idempotency-Key': idempotencyKey } : {}),
},
body: body ? JSON.stringify(body) : undefined,
signal: AbortSignal.timeout(15_000),
})
} catch (error) {
if (attempt >= 5) throw error // red caída: reintentar con la MISMA clave es seguro
await new Promise(resolve => setTimeout(resolve, 500 * 2 ** attempt))
continue
}
if (response.status === 429 || response.status >= 500) {
if (attempt >= 5) throw new Error(`Ruta ${response.status}`)
const wait = Number(response.headers.get('Retry-After') ?? 2 ** attempt)
await new Promise(resolve => setTimeout(resolve, wait * 1000))
continue
}
const text = await response.text()
const json = text ? JSON.parse(text) : null
if (!response.ok) {
const error = new Error(json?.detail ?? `Ruta ${response.status}`)
error.code = json?.code // decidí por code, no por el texto
error.status = response.status
throw error
}
return json
}
}
// Un pedido de la tienda → una entrega. El número de pedido es la clave de idempotencia y la referencia.
export async function shipOrder(order) {
try {
return await ruta('POST', '/api/v1/deliveries', {
idempotencyKey: `pedido-${order.number}`,
body: {
customerName: order.customer.name,
address: order.shipping.address,
recipientPhone: order.customer.phone ?? null,
externalReference: String(order.number),
amountToCollect: order.cashOnDelivery ? order.total.toFixed(2) : null,
},
})
} catch (error) {
if (error.code === 'EXTERNAL_REFERENCE_TAKEN') {
const { deliveries } = await ruta('GET', `/api/v1/deliveries?externalReference=${encodeURIComponent(order.number)}`)
return deliveries[0]
}
throw error
}
}
// Todas las entregas, página por página.
export async function* allDeliveries() {
let cursor = null
do {
const page = await ruta('GET', `/api/v1/deliveries?limit=100${cursor ? `&cursor=${cursor}` : ''}`)
yield* page.deliveries
cursor = page.nextCursor
} while (cursor)
}JavaScript: recibir avisos con Express
JavaScript
import express from 'express'
import { verifyRuta } from './verify-ruta.js' // la función de «Webhooks → Verificar la firma»
const app = express()
const seen = new Set() // en producción, una tabla con índice único por event id
app.post('/webhooks/ruta', express.raw({ type: 'application/json' }), (req, res) => {
if (!verifyRuta(process.env.RUTA_WEBHOOK_SECRET, req.get('Ruta-Signature') ?? '', req.body)) {
return res.status(400).end()
}
const event = JSON.parse(req.body.toString('utf8'))
res.status(204).end() // respondé enseguida y procesá después
if (seen.has(event.id)) return
seen.add(event.id)
if (event.type === 'delivery.delivered') markOrderDelivered(event.data.externalReference)
if (event.type === 'delivery.failed') notifyCustomer(event.data.externalReference, event.data.failureReasonCode)
})
app.listen(3000)Postman e Insomnia
El contrato de la API está en openapi.json (OpenAPI 3.1, sólo /api/v1 y webhooks), con ejemplos en curl, JavaScript, Python y PHP.
- Descargá openapi.json (o copiá su dirección:
https://<tu-courier>/docs/openapi.json). - Postman: Import → elegí el archivo o pegá la dirección → Import. Se crea una colección con cada endpoint.
Insomnia: Create → Import → el archivo o la dirección. - En la colección, definí la variable
baseUrlconhttps://<tu-courier>y en Authorization elegí Bearer Token con tu claveruta_test_…. - Para crear entregas, agregá el encabezado
Idempotency-Keycon un valor nuevo por entrega (Postman:{{$guid}}).
Consejo
Empezá siempre con una clave de prueba: las entregas no llegan a ningún repartidor y no consumen cupo.