# Quickstart

> Get a key, verify it, and list shipments, in curl, TypeScript and Python.

## 1. Get an API key

Create a key at [https://app.gocubic.io/settings/api-keys](https://app.gocubic.io/settings/api-keys) (Cubic app → **Settings → API keys**). It is shown once. Every example reads it from an environment variable:

```bash
export CUBIC_API_KEY="cubic_live_..."
```

## 2. Verify the key

```bash
curl -s https://api.gocubic.io/v1/me \
  -H "Authorization: Bearer $CUBIC_API_KEY"
```

```json
{
  "account": {
    "name": "Brightwell Home Ltd"
  },
  "apiKey": {
    "name": "Inventory sync",
    "prefix": "cubic_live_9f3k",
    "createdAt": "2026-09-01T08:15:00Z"
  }
}
```

A `401` means the key is missing or wrong; the body says which. See [Errors](https://developers.gocubic.io/errors.md).

## 3. List shipments

```bash
curl -s "https://api.gocubic.io/v1/shipments?status=Active&limit=5" \
  -H "Authorization: Bearer $CUBIC_API_KEY"
```

Returns `{ "data": [Shipment, …], "nextCursor": "…" | null }`. Each item is the full [Shipment object](https://developers.gocubic.io/shipment-object.md). For further pages see [Pagination](https://developers.gocubic.io/pagination.md).

## 4. Get one shipment

```bash
curl -s https://api.gocubic.io/v1/shipments/QB10293 \
  -H "Authorization: Bearer $CUBIC_API_KEY"
```

## The same in TypeScript

No dependencies. Run with `npx tsx quickstart.mts` (Node 18+) or `bun quickstart.mts`.

```ts
const BASE_URL = 'https://api.gocubic.io/v1';
const headers = { Authorization: `Bearer ${process.env.CUBIC_API_KEY}` };

async function get(path: string) {
  const response = await fetch(BASE_URL + path, { headers });
  const body = await response.json();
  if (!response.ok) throw new Error(`${body.code}: ${body.detail} Hint: ${body.hint}`);
  return body;
}

const me = await get('/me');
console.log(`Connected to ${me.account.name} with key ${me.apiKey.prefix}`);

const { data, nextCursor } = await get('/shipments?status=Active&limit=5');
for (const shipment of data) {
  console.log(shipment.reference, shipment.status, shipment.serviceType);
}
console.log(nextCursor ? 'More pages available' : 'That is everything');

if (data.length > 0) {
  const shipment = await get(`/shipments/${data[0].reference}`);
  console.log(shipment.milestones.map((milestone: { type: string }) => milestone.type).join(' → '));
}
```

## The same in Python

`pip install requests`, then `python quickstart.py`.

```python
import os

import requests

BASE_URL = "https://api.gocubic.io/v1"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['CUBIC_API_KEY']}"


def get(path, **params):
    response = session.get(BASE_URL + path, params=params, timeout=30)
    body = response.json()
    if not response.ok:
        raise RuntimeError(f"{body['code']}: {body['detail']} Hint: {body['hint']}")
    return body


me = get("/me")
print(f"Connected to {me['account']['name']} with key {me['apiKey']['prefix']}")

page = get("/shipments", status="Active", limit=5)
for shipment in page["data"]:
    print(shipment["reference"], shipment["status"], shipment["serviceType"])
print("More pages available" if page["nextCursor"] else "That is everything")

if page["data"]:
    shipment = get(f"/shipments/{page['data'][0]['reference']}")
    print(" → ".join(milestone["type"] for milestone in shipment["milestones"]))
```

## Next

- [The Shipment object](https://developers.gocubic.io/shipment-object.md)
- [Shipment types](https://developers.gocubic.io/shipment-types.md)
- [Recipes](https://developers.gocubic.io/recipes.md)
