> For the complete documentation index, see [llms.txt](https://docs.zipnova.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.zipnova.com/carriers/ciclo-de-vida-de-un-envio.md).

# Ciclo de vida de un envío

Qué pasa con un envío desde que se crea hasta que se entrega, y qué tiene que informar tu Carrier en cada paso.

Este es el recorrido de un envío en una integración `custom`. En una integración con [Zipnova Rutas](/carriers/integracion-con-zipnova-rutas.md), Zipnova se ocupa de la etiqueta, el tracking y los estados.

```mermaid
flowchart LR
    A["Procesando<br/>evento new"] -->|"Subes la etiqueta"| B["Pendiente de preparación"]
    B --> C["Listo para despacho<br/>evento ready_to_ship"]
    C --> D["En manos del Carrier<br/>received, out_for_delivery, soon_deliver"]
    D --> E["delivered"]
    D --> F["failed_delivery"]
    F -->|"receiver_absent, bad_address"| D
    F -->|"rejected, dangerous_area"| G["returned"]
    D --> H["not_delivered"]
```

## Paso a paso

{% stepper %}
{% step %}

### Recibes la notificación `new`

Cuando un seller contrata tu Carrier, Zipnova crea el envío y te avisa en tu URL de notificaciones. El envío queda en **Procesando** hasta que subas la etiqueta.
{% endstep %}

{% step %}

### Consultas el detalle

La notificación es un aviso liviano. Con `GET /shipments/{shipment_id}` obtienes el envío completo: origen, destino, bultos, valor declarado y los datos de cotización (`custom_data`).
{% endstep %}

{% step %}

### Subes la etiqueta

Con `POST /shipments/{shipment_id}/documents` envías la etiqueta de 10x15 en PDF, con una página por bulto. Opcionalmente puedes enviarla también en ZPL y adjuntar una guía de despacho (waybill) en PDF. Zipnova no valida el formato: confía en la homologación de tu Carrier. Al subirla, el envío pasa de **Procesando** a **Pendiente de preparación**.

```bash
curl -X POST https://api.zipnova.com.ar/carrier/v1/shipments/26461102/documents \
  -H "Authorization: Bearer $API_KEY" \
  -F "label=@etiqueta.pdf" \
  -F "label_zpl=@etiqueta.zpl"
```

{% endstep %}

{% step %}

### Informas el tracking

Con `PUT /shipments/{shipment_id}/tracking` informas el número de seguimiento y, opcionalmente, la URL pública de seguimiento de tu Carrier.
{% endstep %}

{% step %}

### Recibes `ready_to_ship` y despachas

Cuando el envío está listo para despacho, Zipnova te lo notifica con el evento `ready_to_ship`.
{% endstep %}

{% step %}

### Informas los estados

A medida que el envío avanza, lo informas con `POST /shipments/{shipment_id}/status`.
{% endstep %}
{% endstepper %}

## Eventos que recibes

| Evento          | Qué significa                                                  |
| --------------- | -------------------------------------------------------------- |
| `new`           | Envío creado. Queda en Procesando hasta que subas la etiqueta. |
| `ready_to_ship` | Listo para despacho.                                           |
| `cancelled`     | Envío anulado.                                                 |
| `expired`       | Envío vencido sin despacharse.                                 |

Un mismo evento puede llegar más de una vez. Procésalo de forma idempotente por `shipment_id` y `event`, o deduplica por `notification_id`, que es el mismo en los reintentos.

## Estados que informas

| Estado             | Significado                                   | ¿Final? |
| ------------------ | --------------------------------------------- | ------- |
| `received`         | Recibido                                      | No      |
| `out_for_delivery` | En reparto                                    | No      |
| `soon_deliver`     | Próximo a entregarse                          | No      |
| `delivered`        | Entregado                                     | Sí      |
| `failed_delivery`  | Intento de entrega fallido. Requiere `reason` | No      |
| `not_delivered`    | No entregado. Requiere `reason: lost`         | Sí      |
| `returned`         | Devuelto                                      | Sí      |

### Motivos de `failed_delivery`

| `reason`                         | Qué pasa con el envío                                                               |
| -------------------------------- | ----------------------------------------------------------------------------------- |
| `receiver_absent`, `bad_address` | Queda como intento de entrega: el envío todavía puede salir a reparto y entregarse. |
| `rejected`, `dangerous_area`     | Pasa a devolución y ya no admite `delivered`.                                       |

```bash
curl -X POST https://api.zipnova.com.ar/carrier/v1/shipments/26461102/status \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status": "failed_delivery", "reason": "receiver_absent", "message": "Nadie atendió en el domicilio"}'
```

{% hint style="warning" %}
Reglas que Zipnova valida al informar estados:

* El envío tiene que estar documentado (con la etiqueta subida). Si no, responde `409`.
* Los estados finales (`delivered`, `not_delivered` y `returned`) no se pueden modificar una vez informados.
* `occurred_at` es opcional y por defecto es el momento actual, pero no puede ser anterior a la creación del envío.
* `message` admite hasta 150 caracteres y queda en el historial del envío.
  {% endhint %}

## Mantener todo sincronizado

Las notificaciones pueden fallar o llegar tarde. Para reconciliar, lista los envíos con `GET /shipments` usando `updated_since` y el `cursor` de `meta.next_cursor`: así no se saltean ni se repiten envíos que cambian entre una página y otra.
