# Proof of delivery

> Get signatures, photos, and signed delivery notes for pickup and dropoff, and store them in your own system.

When the courier hands over the goods, they collect proof in the Maxmove driver app: a signature, photos, a signed delivery note, or documents, depending on your settings. You get it through one event and one endpoint.

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.pod_submitted` each time the courier submits proof, at pickup and at dropoff, so up to twice per delivery. Polling is not needed.

**2. Fetch the proof**

Call [`GET /v1/deliveries/{deliveryId}/proof-of-delivery`](https://api.maxmove.com/v1/docs#tag/deliveries/GET/v1/deliveries/{deliveryId}/proof-of-delivery). The response has one checkpoint per handover:

| Field | Meaning |
| --- | --- |
| `kind` | `pickup` or `dropoff`. |
| `recipient_name` | Who signed or received the goods, as entered by the courier. |
| `submitted_at` | When the courier submitted the proof. |
| `artifacts[]` | Files with `kind` (`photo`, `signature`, `signed_delivery_note`, `document`), `file_name`, `content_type`, and `download_url`. |

**3. Download the files right away**

`download_url` links are short-lived. Download the files when you receive the event and store them yourself. If a link has expired, call the endpoint again for fresh ones.

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

async function storeProof(deliveryId: string) {
  const res = await fetch(`${BASE_URL}/deliveries/${deliveryId}/proof-of-delivery`, { headers });
  if (res.status === 404) return; // no proof submitted yet
  const proof = await res.json();

  for (const checkpoint of proof.checkpoints) {
    for (const artifact of checkpoint.artifacts) {
      if (!artifact.download_url) continue;
      const file = await fetch(artifact.download_url);
      await writeFile(
        `${deliveryId}-${checkpoint.kind}-${artifact.file_name ?? artifact.kind}`,
        Buffer.from(await file.arrayBuffer()),
      );
    }
  }
}
```

```python Python
def store_proof(delivery_id):
    res = requests.get(f"{BASE_URL}/deliveries/{delivery_id}/proof-of-delivery", headers=headers)
    if res.status_code == 404:
        return  # no proof submitted yet
    for checkpoint in res.json()["checkpoints"]:
        for artifact in checkpoint["artifacts"]:
            if not artifact["download_url"]:
                continue
            name = artifact["file_name"] or artifact["kind"]
            with open(f"{delivery_id}-{checkpoint['kind']}-{name}", "wb") as f:
                f.write(requests.get(artifact["download_url"]).content)
```

## Errors

| Status | Code | Meaning |
| --- | --- | --- |
| 404 | `no_proof_of_delivery` | The courier has not submitted proof yet. |
| 403 | `pod_not_available` | Your plan does not include proof of delivery. |
| 404 | `not_found` | No delivery with this id for your key and mode. |

---

Source: https://maxmove.com/en/developers/docs/guides/proof-of-delivery
