# Get shipments

`GET /v2/shipments?offset=0&limit=10`

**Base URLs:**

- Sandbox: `https://api.sandbox.bobgo.co.za`
- Production: `https://api.bobgo.co.za`

**Authentication:** Bearer token required (see the Authentication page).

## Example request

```bash
curl -X GET 'https://api.sandbox.bobgo.co.za/v2/shipments?offset=0&limit=10' \
  -H "Authorization: Bearer <API_KEY>"
```

Lists shipments on your account, newest first. Standard
[pagination](../1_Introduction/README.md#listing-and-pagination) applies, and
the response carries a `count` of the full result set.

**Without a filter an API key only sees this month.** Unless you send an id, a
reference or a date (`id`, `tracking_reference`, `start_date` or `end_date`, or
one of a few less common filters such as `ids` and
`provider_tracking_reference`), you get the shipments created since the 1st of
the current month (South African time), not the whole history.
On the 1st that is a single day. To reach further back, send a date range.

## Parameters

| Name | Type | Notes |
| --- | --- | --- |
| `id` | integer | Fetch one shipment. |
| `tracking_reference` | string | Fetch by Bob Go's tracking reference. |
| `limit` | integer | Page size. Defaults to 100, capped at 100. |
| `offset` | integer | Rows to skip. |
| `start_date` | timestamp | Filters on the date the shipment was created. Send `end_date` with it: on its own it covers the seven days that follow. |
| `end_date` | timestamp | Filters on the date the shipment was created. On its own it covers the seven days before. |
| `order` | string | `asc` or `desc`. Ignored unless you also send `order_by`. |
| `order_by` | string | Field to sort on. Leave it out for the default, `time_created` descending. Sent without `order`, it sorts ascending. |
| `status` | array of string | The tracking status, e.g. `["in-transit"]`. |
| `submission_status` | array of string | e.g. `["failed-indefinitely"]`. |
| `provider_slug` | array of string | The courier. |
| `service_level_code` | string | One service level, e.g. `ECO`. |
| `service_level_codes` | array of string | Several service levels. |
| `archived` | boolean | `true` returns only archived shipments. |

Array filters are sent as a JSON array in the query string, with no spaces,
e.g. `?status=["in-transit","out-for-delivery"]`. With a space after the comma
the filter matches nothing.

## Response

One shipment, trimmed to the fields most integrations read:

```json
{
  "shipments": [
    {
      "id": 4455123,
      "account_id": 1234,
      "tracking_reference": "UATCG4X7Q2",
      "custom_tracking_reference": null,
      "provider_slug": "tcg",
      "provider_tracking_reference": "TCG1234567",
      "service_level_code": "ECO",
      "status": "in-transit",
      "submission_status": "success",
      "failed_reason": null,
      "charged_amount": 96.45,
      "charged_weight_kg": 2,
      "submitted_weight_kg": 2,
      "declared_value": 1500,
      "parcel_count": 1,
      "collection_address": { "...": "..." },
      "delivery_address": { "...": "..." },
      "parcels": [{ "...": "..." }],
      "meta": { "custom_order_number": "ORD-10045" },
      "time_created": "2026-09-05T08:31:12Z"
    }
  ],
  "count": 1
}
```

Filtering on `submission_status=["failed-indefinitely"]` is the cheap way to
find bookings that never reached a courier, and worth a scheduled sweep if you
are not consuming the submission-status webhook.
