# Consignment notes

> Follow the CMR or German Frachtbrief of a delivery: its state, who signed, the reservations, and the signed PDF and sealed evidence.

When a carriage needs a consignment note, the carrier prepares it in Maxmove: a CMR for cross-border carriage, a German Frachtbrief within Germany, electronic or on paper. Sender, carrier, and consignee sign it at pickup and delivery. You can read the note and download the signed documents through the API.

Code examples use `BASE_URL` and `headers` from the [Quickstart](https://maxmove.com/en/developers/docs/quickstart).

**1. Wait for the event**

Maxmove sends `delivery.consignment_updated` whenever a note of the delivery changes: it is prepared, corrected, signed, sealed, delivered, cancelled, or replaced by paper. `data.consignment` is the note as the endpoint below returns it, without download links.

**2. Read the notes**

Call [`GET /v1/deliveries/{deliveryId}/consignments`](https://api.maxmove.com/v1/docs#tag/deliveries/GET/v1/deliveries/{deliveryId}/consignments). The key needs `deliveries:read`. The list is empty until the carrier prepares a note, and always empty for test deliveries.

| Field | Meaning |
| --- | --- |
| `number` | The number printed on the note, for example `CMR-027F3C2A41` or `FB-027F3C2A41`. |
| `type` | `international_cmr` or `german_freight_note`. |
| `mode` | `electronic` or `paper`. |
| `state` | `draft`, `awaiting_sender`, `issued`, `delivered`, `delivered_without_consignee`, `cancelled`, or `replaced_by_paper`. |
| `version` | Increases with every change of the particulars, state, or signatures. |
| `signatures[]` | Who signed (`role`, `signer_name`), how (`method`), when (`signed_at`), and whether the signature is `sealed` into the evidence. `decision` is `refused` when a party refused to sign. |
| `reservations[]` | The carrier's reservations about the goods at takeover and the consignee's at delivery. |
| `performing_carrier` | The subcontractor who performs the carriage, when there is one. |
| `delivery_declaration` | Set when the carrier delivered without the consignee's signature, for example when the goods were left at the door. |
| `files_ready` | The current revision's PDF and evidence are sealed and archived. |
| `pdf_url`, `evidence_url` | Short-lived links to the signed PDF and the sealed evidence (JSON). `null` until `files_ready` is `true`. |

**3. Download the files right away**

The links expire after a few minutes. Download the files when you read the list and store them yourself. Call the endpoint again for fresh links.

```ts Node.js
import { writeFile } from 'node:fs/promises';

async function storeConsignmentNotes(deliveryId: string) {
  const res = await fetch(`${BASE_URL}/deliveries/${deliveryId}/consignments`, { headers });
  const { consignments } = await res.json();

  for (const note of consignments) {
    if (!note.files_ready || !note.pdf_url) continue;
    const pdf = await fetch(note.pdf_url);
    await writeFile(`${note.number}-v${note.version}.pdf`, Buffer.from(await pdf.arrayBuffer()));
  }
}
```

```python Python
def store_consignment_notes(delivery_id):
    res = requests.get(f"{BASE_URL}/deliveries/{delivery_id}/consignments", headers=headers)
    for note in res.json()["consignments"]:
        if not note["files_ready"] or not note["pdf_url"]:
            continue
        with open(f"{note['number']}-v{note['version']}.pdf", "wb") as f:
            f.write(requests.get(note["pdf_url"]).content)
```

## How to read events

- **Several events per version.** A signature first arrives unsealed and then sealed, and the files become ready later still. Each of these sends an event with the same `version`.
- **Skip stale events.** Events can arrive out of order. Ignore one whose `data.consignment.version` is lower than the last one you processed.
- **Corrections need new signatures.** When the carrier corrects an issued electronic note, `revision_number` increases and `state` is `awaiting_sender` until the sender signs the corrected version.
- **Paper replacements.** A note in `replaced_by_paper` names its paper replacement in `replacement_id`. Both are in the list.

## Fleet orders

Fleets read the notes of their own orders with [`GET /v1/fleet/orders/{fleetOrderId}/consignments`](https://api.maxmove.com/v1/docs#tag/fleet-orders/GET/v1/fleet/orders/{fleetOrderId}/consignments). The key needs `fleet_orders:read`, and the response has the same `consignments`. Fleet orders don't send webhook events.

## Errors

| Status | Code | Meaning |
| --- | --- | --- |
| 404 | `not_found` | No delivery or fleet order with this id for your key and mode. |
| 403 | `fleet_key_required` | Fleet orders only: the key belongs to a business workspace. |
| 403 | `live_key_required` | Fleet orders only: the key is a test key. |

---

Source: https://maxmove.com/en/developers/docs/guides/consignment-notes
