U
UnifullAPI v1

API pública para integraciones externas

Si tu plataforma de venta no es MercadoLibre ni Tienda Nube (WooCommerce, Magento, Shopify Custom App, ERP propio), esta es la forma de conectarla con Unifull. REST clásico, JSON, auth por API key. Esperamos que la integración te lleve menos de una tarde.

1. Cómo empezar

  1. Logueate en /account/api-keys (ruta seller).
  2. Tocá "Crear API key", ponele un nombre (ej: "WooCommerce producción") y elegí los scopes que necesites.
  3. Copiá el secret AHORA — solo aparece una vez. Si lo perdés, hay que generar uno nuevo.
  4. Pegale a los endpoints con el header Authorization: Bearer <tu_secret>.

2. Scopes disponibles

Cada endpoint requiere un scope específico. Si tu API key no lo tiene, vas a recibir 401 con el motivo. Generá keys con el mínimo de permisos necesario (principle of least privilege).

orders:writeCrear y cancelar envíos.
orders:readConsultar envíos por externalRef.
tracking:readLeer eventos de tracking de envíos.
skus:readListar el catálogo de productos del seller.
skus:writeCrear o actualizar SKUs.
inventory:readConsultar stock disponible por SKU.

3. POST /api/v1/orders

Crear un envío en Unifull desde una orden de tu plataforma. Idempotente por externalRef — si tu integración manda 2 veces el mismo, devolvemos el shipment existente (con flag idempotent: true). Auto-crea SKUs nuevos si no existen.

Scope requerido: orders:write.

Request
curl -X POST https://api.unifull.ar/api/v1/orders \
  -H "Authorization: Bearer ufa_xxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "externalRef": "WC-1234",
    "destName": "Juan Pérez",
    "destPhone": "+5491150001234",
    "destEmail": "juan@example.com",
    "destAddress": {
      "street": "Av. Corrientes",
      "number": "1234",
      "floor": "5",
      "dept": "B",
      "city": "Ciudad Autónoma de Buenos Aires",
      "state": "Buenos Aires",
      "zipCode": "C1043"
    },
    "items": [
      { "sku": "ABC-001", "productName": "Remera blanca M", "quantity": 2, "unitPrice": 8500 },
      { "sku": "ABC-002", "productName": "Pantalón negro 32", "quantity": 1, "unitPrice": 14990 }
    ],
    "totalDeclaredValue": 31990,
    "carrier": "ANDREANI",
    "deliveryMode": "HOME",
    "packaging": "BAG_ECOMMERCE"
  }'
Response 201 Created (caso nuevo)
{
  "id": "f4a3b1c2-...",
  "internalRef": "UF-00420",
  "status": "RECEIVED",
  "externalRef": "WC-1234",
  "createdAt": "2026-05-05T14:30:00.000Z",
  "idempotent": false
}
Response 201 Created (idempotente — ya existía)
{
  "id": "f4a3b1c2-...",
  "internalRef": "UF-00420",
  "status": "PACKED",
  "externalRef": "WC-1234",
  "createdAt": "2026-05-05T14:30:00.000Z",
  "idempotent": true
}

4. GET /api/v1/orders/:externalRef

Consultar un envío por la externalRef que vos le pasaste al crearlo. Devuelve el estado actual + tracking code + eventos del timeline.

Scope requerido: orders:read.

Request
curl https://api.unifull.ar/api/v1/orders/WC-1234 \
  -H "Authorization: Bearer ufa_xxxxxxxxxxxxxxxxxxxxxxx"
Response 200
{
  "id": "f4a3b1c2-...",
  "internalRef": "UF-00420",
  "externalRef": "WC-1234",
  "status": "IN_TRANSIT",
  "carrier": "ANDREANI",
  "trackingCode": "20012345678",
  "carrierLabelUrl": "https://andreani.com/tracking/20012345678",
  "createdAt": "2026-05-05T14:30:00.000Z",
  "dispatchedAt": "2026-05-06T09:15:00.000Z",
  "deliveredAt": null,
  "trackingEvents": [
    { "status": "RECEIVED", "description": "Recibido en Unifull", "occurredAt": "2026-05-05T14:30:00.000Z" },
    { "status": "PACKED", "description": "Empaquetado", "occurredAt": "2026-05-06T08:00:00.000Z" },
    { "status": "IN_TRANSIT", "description": "Despachado a Andreani", "occurredAt": "2026-05-06T09:15:00.000Z" }
  ]
}

5. POST /api/v1/orders/:externalRef/cancel

Cancelar un envío. Solo posible si todavía no salió del depósito — estados RECEIVED, IN_WMS, PACKED. Si ya está en tránsito, devuelve 400.

Scope requerido: orders:write.

Request
curl -X POST https://api.unifull.ar/api/v1/orders/WC-1234/cancel \
  -H "Authorization: Bearer ufa_xxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Cliente canceló desde mi tienda" }'

6. Errores

Todos los errores devuelven JSON shape { statusCode, message, error }. Códigos comunes:

  • 401 — API key faltante, malformada, revocada, o sin el scope necesario. El message te dice exactamente qué pasó.
  • 400 — Body inválido (validation errors). El message es array con la lista de campos mal.
  • 404 — externalRef no existe en tu seller.
  • 429 — Rate limit. Bajá el ritmo y reintentá con backoff.

7. /api/v1/skus — Catálogo

Listar / crear / actualizar SKUs del catálogo. Útil si tu plataforma es la fuente de verdad del catálogo y querés sincronizarlo con Unifull.

Scopes: skus:read / skus:write.

GET /api/v1/skus?search=remera&page=1&perPage=50
curl "https://api.unifull.ar/api/v1/skus?search=remera" \
  -H "Authorization: Bearer ufa_xxxxxxxxxxxxxxxxxxxxxxx"
POST /api/v1/skus (upsert por sku)
curl -X POST https://api.unifull.ar/api/v1/skus \
  -H "Authorization: Bearer ufa_xxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "sku": "ABC-001",
    "description": "Remera blanca M",
    "ean": "7791234567890",
    "weightGrams": 200,
    "lengthCm": 30,
    "widthCm": 20,
    "heightCm": 2
  }'

Si el SKU ya existe (mismo sellerId+sku), se actualiza en vez de duplicar. Devuelve created: false en ese caso.

8. /api/v1/inventory — Stock

Consultar stock disponible por SKU. Devuelve totalStock (lo que hay en depósito), reserved (lo que está pickeado para envíos pendientes) y available (totalStock − reserved, lo que podés vender hoy en tu tienda externa sin oversell).

Scope: inventory:read.

GET /api/v1/inventory
curl https://api.unifull.ar/api/v1/inventory \
  -H "Authorization: Bearer ufa_xxxxxxxxxxxxxxxxxxxxxxx"
GET /api/v1/inventory/:sku
curl https://api.unifull.ar/api/v1/inventory/ABC-001 \
  -H "Authorization: Bearer ufa_xxxxxxxxxxxxxxxxxxxxxxx"

9. Próximas mejoras

  • Webhooks salientes: Unifull te avisa por POST a tu URL cuando cambia el estado de un envío. Por ahora, polling de GET /orders/:externalRef cada 15 min funciona bien.
  • Bulk operations: crear múltiples orders / SKUs en una sola request.
  • Rate limiting per-key: ahora todo el back tiene un límite global (100 req/min por IP). Pronto habrá límite por API key específico.

¿Necesitás algo específico que no esté? Escribinos a dev@unifull.com.ar.