# Getting started

This walks through the core integration flow: authenticate, find a location, create a reservation, and hand your customer the PIN that opens the locker.

## 1. Authenticate

Every request carries `Authorization: Bearer <api_key>`. Create an API key in the dashboard under **Settings → API keys**, or ask your Bob Box contact to issue one with an API user. It never expires:

```bash
curl -G "https://api.bobbox.co.za/v2/account/locations" \
  -H "Authorization: Bearer 4f3c9b1a72e04d5fa9c8e6b0d1a2f3c4"
```

That is all you need for the rest of this guide.

## 2. Find a location

Look up the locker locations available to your account, and check which ones have space for your parcel before you try to reserve.

**Endpoint:** `GET /account/locations`

```bash
curl -G "https://api.bobbox.co.za/v2/account/locations" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "lat=-26.107567" \
  --data-urlencode "lng=28.053040" \
  --data-urlencode "max_distance=10" \
  --data-urlencode "order_closest=true" \
  --data-urlencode "parcel_length=30" \
  --data-urlencode "parcel_width=20" \
  --data-urlencode "parcel_height=10" \
  --data-urlencode "include_availability=true"
```

**Send the parcel dimensions together with `include_availability=true`.** That gives you a `compartment_availability` map per location:

```json
"compartment_availability": { "Small": true, "Medium": true, "Large": false }
```

A size is `true` when a compartment of that size is free **and** your parcel fits it. Without dimensions, `include_availability=true` still reports which compartment sizes are free, but it does not check whether your parcel fits. Skip any location where every size is `false`.

That is enough to finish this guide. What the map does and does not promise about step 3, and what to do when it is wrong, is in the Workflows section under "Checking space before you reserve".

See the Get account locations endpoint in the Locations section for the full parameter and response reference.

## 3. Create a reservation

Reserve a compartment at the chosen location.

**Endpoint:** `POST /bob-box/reservations`

```bash
curl -X POST "https://api.bobbox.co.za/v2/bob-box/reservations" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
    "location_id": 213,
    "reservation_type": "client-pickup",
    "parcel_length": 30,
    "parcel_width": 20,
    "parcel_height": 10,
    "allow_auto_upgrade": true,
    "contact_name": "Jane Customer",
    "contact_number": "+27833771167",
    "reference": "ORDER-1452"
  }'
```

Two things to get right here:

- **`reservation_type` is required.** Leave it out and the call fails.
- **`allow_auto_upgrade` defaults to `false`,** which fails the reservation while bigger compartments stand empty. The sample above sends `true`. Why, and when not to, is on the Create reservation endpoint page under "How the parcel is sized".

The response gives you the reservation's `id`, the `compartment` it claimed, and **all three PINs**. Store the `id` and your own `reference` so you can look the reservation up later.

See the Create reservation endpoint in the Reservations section for the full parameter and response reference.

## 4. Give your customer the PIN

The PINs come back on the create response above — you do not need a second call:

| PIN | Opens the compartment for |
| --- | --- |
| `dropoff_pin` | Putting the parcel in |
| `pickup_pin` | Collecting the parcel |
| `return_pin` | Sending the parcel back to the sender |

Send the customer the one that matches what they are doing. Notifying customers is your side of the integration by default — Bob Box does not SMS or email them unless your account is configured for it. Contact the Bob Box team if you want Bob Box to send the collection SMS instead.

If you ever need the PINs again without pulling the whole reservation, there is a dedicated endpoint:

**Endpoint:** `GET /bob-box/locations/reservations/pins`

```bash
curl -G "https://api.bobbox.co.za/v2/bob-box/locations/reservations/pins" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "id=8931"
```

## 5. Track status

Bob Box can push reservation status changes to your own URL via webhooks — see the Webhooks section. You can also poll the reservation directly.

**Endpoint:** `GET /bob-box/reservations`

```bash
curl -G "https://api.bobbox.co.za/v2/bob-box/reservations" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  --data-urlencode "id=8931"
```

#### Reservation statuses

| Status | Description |
| --- | --- |
| `waiting-for-dropoff` | Reservation created; parcel not yet dropped off. |
| `waiting-for-pickup` | Parcel dropped off; waiting for the recipient to collect it. |
| `complete` | Parcel was collected. |
| `expired` | Legacy status, set only by Bob Box operations. Not part of the normal lifecycle — do not build against it. |
| `cancelled` | The reservation was cancelled. |
| `returned` | The parcel was returned to the sender. |
| `cleared` | The reservation was manually cleared. |

Every reservation also carries `flat_fee_end_time` — the moment the flat-fee window closes and overstay charges start. Watch it if overstay cost matters to you.

See the Get reservations endpoint in the Reservations section for the full field reference.

## 6. Cancel, if needed

If the parcel is no longer being sent, cancel the reservation to free up the compartment.

**Endpoint:** `POST /bob-box/reservations/cancel`

```bash
curl -X POST "https://api.bobbox.co.za/v2/bob-box/reservations/cancel" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{ "reservation_id": 8931 }'
```

**This only works while the reservation is still `waiting-for-dropoff`.** Once the parcel is in the locker it cannot be cancelled — the parcel has to be collected or returned instead.

See the Cancel reservation endpoint in the Reservations section for details.

## Next steps

- **Webhooks section** — get reservation status changes pushed to your own URL instead of polling.
