Envíos (Envia.com)

Cotiza y genera guías de Coordinadora, Servientrega, TCC, Inter Rapidísimo y otras transportadoras desde un contacto, a través de tu cuenta de Envia.com. Esta página resume la API; el detalle de cada campo está en la referencia (sección Shipments).

Qué es

Un envío siempre sale de un contacto: el destino se toma de su dirección y ciudad, y lo que mandes en destination lo reemplaza. El origen es el que la organización configuró en la app (Ajustes → Envíos); no se envía por API. Estados: draft (se intentó generar y falló), created (guía generada, el único cancelable), picked_up, in_transit, out_for_delivery, delivered y los de excepción. El rastreo se actualiza solo por webhook y por una revisión periódica.

Requisitos

  • • El módulo Envíos activo en el plan (sin él, 403 PLAN_MODULE_REQUIRED).
  • • La API key de Envia.com en Configuración → Integraciones, con saldo en esa cuenta.
  • • La dirección de origen en Ajustes → Envíos.
  • • Un token con shipments:read para cotizar y consultar, y shipments:write para generar, rastrear y cancelar.

Endpoints y permisos

OperaciónPermisoQué hace
GET /shipmentsshipments:readLista los envíos (filtros contactId y status; limit por defecto 20, máximo 100).
POST /shipments/ratesshipments:readCotiza en todas las transportadoras de tu cuenta. No escribe ni cobra.
POST /shipmentsshipments:writeGenera la guía. Cobra saldo de tu cuenta de Envia.
GET /shipments/{id}shipments:readConsulta un envío con su estado y eventos.
POST /shipments/{id}/trackshipments:writeRefresca el rastreo contra Envia.
POST /shipments/{id}/cancelshipments:writeCancela una guía en estado created y devuelve el saldo si Envia lo informa.

No hay borrado de envíos ni programación de recogidas por separado: la recogida se pide al generar (pickup).

Cotizar y generar

Primero cotiza: la respuesta trae rates ordenadas por precio y failed con las transportadoras que no respondieron (una caída no tumba la cotización). De la tarifa elegida tomas carrier y service.

1. Cotizar al contacto

curl -X POST "https://api.fusioncol.com/api/shipments/rates" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "contactId": "66c74b4f66baaf700d2f13e4",
    "packages": [{ "content": "manillas", "weight": 1,
      "dimensions": { "length": 20, "width": 15, "height": 10 }, "declaredValue": 50000 }]
  }'

2. Generar la guía (cobra saldo)

curl -X POST "https://api.fusioncol.com/api/shipments" \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{
    "contactId": "66c74b4f66baaf700d2f13e4",
    "carrier": "serviEntrega",
    "service": "premier",
    "packages": [{ "content": "manillas", "weight": 1,
      "dimensions": { "length": 20, "width": 15, "height": 10 }, "declaredValue": 50000 }],
    "idempotencyKey": "pedido-4521-1"
  }'

Opcionales: destination (pisa lo del contacto), insurance, cod (contra entrega, si el servicio lo soporta), pickup y dealId/quotationId/invoiceId para vincular el envío. Pesos en kg y medidas en cm.

Idempotencia y cobro de saldo

Generar una guía cobra saldo de tu cuenta de Envia, y FusionCRM llama a Envia una sola vez por intento: nunca reintenta un generate por su cuenta. Para que tus reintentos no cobren dos veces, manda siempre idempotencyKey (1-100 caracteres, única en la organización):

  • • Misma clave y el envío ya tiene guía → 200 con reused: true, sin llamar a Envia (el body se ignora).
  • • Misma clave y el intento anterior falló (Envia rechazó la guía) → se vuelve a intentar sobre el mismo envío: 201 o de nuevo 422.
  • • Misma clave con un generate en curso → 409 SHIPMENT_IN_PROGRESS.
  • • Resultado desconocido (timeout de 25 s, red, 5xx) → 409 SHIPMENT_NEEDS_REVIEW. La guía pudo cobrarse; ese envío nunca se regenera solo. Revisa el panel de Envia y usa una clave nueva solo si no se creó.
Advertencia
Usa una clave por intento de envío (pedido-4521-1), no por pedido: para generar otra guía después de cancelar la anterior necesitas una clave nueva. Sin clave, la protección es solo best-effort (una ventana de 30 segundos por contacto).

Ciudad del destino: 422 INVALID_CITY

La ciudad del destino se resuelve contra el catálogo DANE. Si el contacto ya tiene cityCode, se usa ese. Si no, o si mandas destination.city, tiene que ser inequívoca. Manda destination.cityCode (5 dígitos) para evitar dudas.

El error de Envíos no es el mismo que el CITY_UNRESOLVED de contactos: usa code: INVALID_CITY, reason (ambiguous, fuzzy, none o unsupported_country), input como objeto y candidatos con name, dane8 y la sigla de departamento de Envia (stateIso). Reenvía con el code del candidato como destination.cityCode.

422 INVALID_CITY

{
  "success": false,
  "code": "INVALID_CITY",
  "message": "La ciudad \"Armenia\" es ambigua; indica el departamento o el cityCode.",
  "reason": "ambiguous",
  "input": { "city": "Armenia" },
  "candidates": [
    { "code": "63001", "dane8": "63001000", "name": "Armenia", "stateCode": "63", "stateName": "Quindío" },
    { "code": "05059", "dane8": "05059000", "name": "Armenia", "stateCode": "05", "stateName": "Antioquia" }
  ]
}

Solo se envía dentro de Colombia: un destino con otro país responde 422 INVALID_CITY con reason: unsupported_country.

Otros errores

Todos llevan success: false, code y message; los de Envia agregan error normalizado (nunca la respuesta cruda del proveedor).

HTTPcodeCuándo
409SHIPMENT_IN_PROGRESSOtro POST con la misma idempotencyKey (o del mismo contacto sin clave) está generando la guía. Espera unos segundos y reintenta con la misma clave.
409SHIPMENT_NEEDS_REVIEWNo se sabe si Envia generó la guía (timeout, red). Pudo cobrarse: revisa el panel de Envia y, si hace falta, reintenta con una clave nueva.
400IDEMPOTENCY_KEY_REUSEDEsa idempotencyKey ya se usó con otro contacto.
422ENVIA_GENERATE_FAILEDEnvia rechazó la guía (saldo insuficiente, transportadora caída…). Queda un borrador (shipmentId) que puedes reintentar con la misma clave.
422ENVIA_NOT_CONFIGURED / ORIGIN_NOT_CONFIGUREDFalta la API key de Envia (Integraciones) o la dirección de origen (Ajustes → Envíos).
409SHIPMENT_NOT_CANCELABLE / SHIPMENT_NOT_TRACKABLESolo se cancela un envío en created; un draft no tiene guía que rastrear.
403PLAN_MODULE_REQUIREDEl plan de la organización no tiene el módulo Envíos.
Consejo
Desde una IA, el MCP expone lo mismo con quote_shipment, create_shipment, track_shipment y list_contact_shipments.