> ## Documentation Index
> Fetch the complete documentation index at: https://docs.reap.global/llms.txt
> Use this file to discover all available pages before exploring further.

# Physical Card Shipping

> Order physical cards and track production and delivery.

Ship one card or a batch of up to 200 cards in a single shipment. Reap handles production, courier handoff, and delivery tracking. You drive the flow with a draft-first API: build the shipment, review it, then submit when ready.

***

## Lifecycle

A shipment moves through production at the factory, courier handoff, and delivery.

```mermaid theme={null}
stateDiagram-v2
  direction LR
  [*] --> DRAFT
  DRAFT --> PLACED : submit
  DRAFT --> CANCELED : delete
  PLACED --> IN_PRODUCTION
  IN_PRODUCTION --> READY_TO_SHIP
  READY_TO_SHIP --> IN_TRANSIT
  IN_TRANSIT --> OUT_FOR_DELIVERY
  OUT_FOR_DELIVERY --> DELIVERED
  DELIVERED --> [*]
```

`DELIVERY_FAILED`, `EXCEPTION`, and `CANCELED` can also occur from most non-terminal states. `DELIVERY_FAILED` and `EXCEPTION` are recoverable - the courier may re-attempt and the shipment can move forward.

### Shipment statuses

| Status             | Meaning                                                      |
| ------------------ | ------------------------------------------------------------ |
| `DRAFT`            | Created locally. Not yet sent to the manufacturer. Editable. |
| `PLACED`           | Submitted to the manufacturer. Awaiting production.          |
| `IN_PRODUCTION`    | At least one card is being personalized.                     |
| `READY_TO_SHIP`    | All cards produced. Awaiting courier pickup.                 |
| `IN_TRANSIT`       | Picked up by the courier.                                    |
| `OUT_FOR_DELIVERY` | Out for final delivery.                                      |
| `DELIVERED`        | Delivered to the recipient.                                  |
| `DELIVERY_FAILED`  | Delivery attempt failed. Courier may re-attempt.             |
| `EXCEPTION`        | Customs hold, weather delay, or similar. May still recover.  |
| `CANCELED`         | Shipment will not continue.                                  |

Only `DELIVERED` and `CANCELED` are terminal. Some carriers skip intermediate states (for example, `OUT_FOR_DELIVERY`), so do not assume every status is visited.

### Per-card production status

Each card in the shipment carries its own `productionStatus`. This lets you tell which cards in a multi-card shipment are still being produced versus already complete.

| Status               | Meaning                                                                                                   |
| -------------------- | --------------------------------------------------------------------------------------------------------- |
| `PENDING`            | Card has not yet been sent to the factory.                                                                |
| `REQUESTED`          | Factory has accepted the production request.                                                              |
| `IN_PRODUCTION`      | Card is being personalized.                                                                               |
| `COMPLETED`          | Production complete.                                                                                      |
| `ACTIVATED`          | Cardholder has activated the card.                                                                        |
| `ON_HOLD`            | Production paused. Contact Reap for details.                                                              |
| `CANCELED`           | Production canceled.                                                                                      |
| `BULK_SHIP_REJECTED` | The manufacturer rejected this specific card at submit time. The rest of the shipment still went through. |

***

## Single card vs multi-card shipments

One endpoint covers both. A shipment with one card and a shipment with up to 200 cards use the same draft-first flow.

|                           | Single card                            | Multi-card                                          |
| ------------------------- | -------------------------------------- | --------------------------------------------------- |
| Cards per shipment        | 1                                      | 2 - 200                                             |
| Box-level destination     | Must match the card's per-card address | Independent of per-card addresses                   |
| Cutoff window             | None                                   | Submit before `cutoffDate` returned at creation     |
| Partial failure on submit | All-or-nothing                         | Surviving cards proceed; rejected cards stay behind |

Use multi-card shipments when you are dispatching cards in bulk to a single hub (a corporate office, a regional distribution point). Use single-card shipments when each card goes directly to the cardholder.

***

## Issue a shipment

<Steps>
  <Step title="Create a draft">
    Call [Create a card shipment](/api-reference/card-shipments/create-shipment-draft) with the destination address, recipient details, courier choice, and one or more cards. The shipment is created with `status: DRAFT`.

    Each card entry includes the `cardId`, `cardDesignId`, and a per-card `shippingAddress`. The per-card address is the final destination printed on the card mailer; it can differ from the box-level destination on multi-card shipments.
  </Step>

  <Step title="Adjust the draft (optional)">
    Use [Update shipment](/api-reference/card-shipments/update-shipping-details), [Add a card](/api-reference/card-shipments/add-card-to-draft), and [Remove a card](/api-reference/card-shipments/remove-card-from-draft) to edit a `DRAFT` shipment. Once submitted, the shipment is frozen.
  </Step>

  <Step title="Submit to the manufacturer">
    Call [Submit shipment](/api-reference/card-shipments/submit-shipment). The shipment transitions to `PLACED` and the manufacturer starts production.

    For multi-card shipments, a `cutoffDate` is returned. Cards submitted after this cutoff roll into the next production batch. Plan submission with this in mind.

    On partial failure (some cards accepted, others rejected), the response returns **HTTP 207 Multi-Status**. The shipment still moves to `PLACED` with the surviving cards. Rejected cards appear in `cards[]` with `productionStatus: BULK_SHIP_REJECTED` and a `rejectedAt` timestamp.
  </Step>

  <Step title="Track production and delivery">
    Subscribe to [`CARD_SHIPMENT_STATUS_UPDATED`](/api-reference/card-shipment-status-updated) for shipment-level status changes. The webhook fires on every transition (`PLACED` → `IN_PRODUCTION`, `IN_TRANSIT`, etc.) and whenever tracking details become available.

    To inspect per-card production progress, call [Get shipment](/api-reference/card-shipments/get-shipment) and read each `cards[i].productionStatus`.
  </Step>
</Steps>

***

## Tracking and webhooks

`CARD_SHIPMENT_STATUS_UPDATED` is the source of truth for shipment status. Do not poll.

When tracking becomes available, `trackingNumber` and `trackingUrl` are populated on the shipment payload. Pass the URL through to the cardholder so they can follow the delivery with the courier directly.

If you need the latest state on demand (e.g. a customer service agent looking up a specific shipment), call [Get shipment](/api-reference/card-shipments/get-shipment). The response includes the full `cards[]` array with per-card production status.

***

## Couriers and destinations

Set the courier on the draft:

| Courier `type` | `name`         | When to use                                                                       |
| -------------- | -------------- | --------------------------------------------------------------------------------- |
| `COURIER`      | `DHL`, `FEDEX` | Tracked international delivery. Some couriers are not available in every country. |
| `POSTAL`       | omitted        | Local postal service. Tracking may be limited.                                    |

Only `DHL`, `FEDEX`, and `POSTAL` can be selected on create or update. After the shipment is placed, the courier on GET responses and shipping webhooks reflects the manufacturer's assignment and may be `SFEXPRESS` for some manufacturer and destination combinations (for example cards shipped to Hong Kong), even if you requested `DHL` or `FEDEX`.

Some countries do not support physical card shipping or require additional fields. The API will reject a draft with a clear error if:

* The destination country is not supported (`SHIPPING_NOT_ALLOWED_FOR_COUNTRY`)
* A zone (state or province) is required for the destination (`ZONE_REQUIRED`) or the supplied zone is invalid (`INVALID_ZONE`)
* The chosen courier does not deliver to the destination (`COURIER_NOT_SUPPORTED`)
* The recipient phone number is invalid or its dial code does not match the destination country (`SHIPPING_PHONE_INVALID`, `SHIPPING_PHONE_DIAL_CODE_MISMATCH`)

Validate addresses up front in your UI when possible. The same checks are run on draft creation and on submission, so a draft that creates successfully will still pass these checks at submit time unless you change the address.

***

## What's next

Once a physical card is delivered, the cardholder activates it with the 6-digit code on the mailer. See [Physical Card Activation](/cards/activation) for the activation flow and lost-code recovery.
