# Partner API Quickstart

The Partner API (`/v1/partner`) lets publishers manage screens and lets buyers optimize AI creatives against measured attention and dwell on paid plays. Use the same account for inventory, native creative review, serving, webhooks and reporting.

**Base URL:** `https://api.trillboards.com`

## 1. Get an API key

Register a new partner via `POST /v1/partner/register` (self-service, rate-limited to 5 req/hr per IP) or upgrade an existing earner account via `POST /v2/earner/upgrade-to-partner`. Save the token — the raw key is shown once.

For a new organization, replace the company name, unique lowercase slug and contact email:

```bash
curl -sS -X POST https://api.trillboards.com/v1/partner/register \
  -H 'Content-Type: application/json' \
  -d '{"name":"Your Company","slug":"your-company-unique-slug","contact_email":"developer@your-company.example"}'
```

Save `data.api_key` securely as `TRILLBOARDS_API_KEY` in your server environment. Existing organizations use the upgrade or key-management flow above. Portal access instructions are returned in `data.portal_access`.

**Newly minted partner keys always carry the `tb_prt_` prefix.** The older `trb_partner_` prefix is still *accepted* on existing keys but is no longer *issued*, so a key you mint today will never look like it. Do not hard-code, pattern-match, or validate against any prefix: prefixes are presentation metadata only, and authorization is decided exclusively by the scopes attached to the key (`services/platformApiAuthResolver.js`).

All authenticated endpoints expect:

```
Authorization: Bearer tb_prt_xxxxxxxxxxxx
```

## 2. Make your first call

Verify auth and pull partner info:

```bash
curl -s "https://api.trillboards.com/v1/partner/info" \
  -H "Authorization: Bearer tb_prt_xxxxxxxxxxxx"
```

Success response:

```json
{
  "success": true,
  "data": {
    "partner_id": "65f1c...",
    "name": "Acme Vending",
    "tier": "standard",
    "device_count": 42,
    "created_at": "2026-01-15T09:30:00Z"
  }
}
```

## 3. Handle errors

Every 4xx/5xx follows the canonical envelope and echoes a request ID you can share with support:

```json
{
  "error": {
    "type": "invalid_request_error",
    "code": "screen_not_found",
    "message": "Screen not found or access denied",
    "param": "screen_id",
    "request_id": "req_a1b2c3d4e5f6789012345678901234ab",
    "doc_url": "https://api.trillboards.com/docs/errors#screen_not_found",
    "help": {
      "summary": "Screen IDs are prefixed 'scr_'. List your screens at GET /v1/partner/devices.",
      "portal_url": "https://trillboards.com/earner/screens"
    }
  }
}
```

## 4. Common error codes

All codes below come from `utils/partnerApiErrors.ts` (see the error reference for the full catalog):

> `invalid_api_key_format` is defined in the error catalog but **no auth path ever emits it** — the
> server performs no prefix or format validation. A malformed or unknown token returns `invalid_api_key`.

| `error.code` | HTTP | When you see it |
|---|---|---|
| `authentication_required` | 401 | No `Authorization` header. Add `Bearer tb_prt_...`. |
| `invalid_api_key` | 401 | Token does not resolve to an active partner — rotate via `POST /v1/partner/api-key/rotate`. |
| `partner_inactive` | 403 | Account suspended. Contact support. |
| `screen_not_found` | 404 | `error.param` identifies the bad ID. Fetch the list from the portal or the devices endpoint. |
| `rate_limit_exceeded` | 429 | Honor the `Retry-After` header. The enforced authenticated cap is 1000 req/min per API key, flat across every data-access tier. |
| `tier_insufficient` | 403 | Endpoint requires a higher data-access tier; `error.help.current_tier` and `required_tier` tell you exactly what to upgrade to. |

## 5. Next common operations

- **List devices:** `GET /v1/partner/devices`
- **Register a device:** `POST /v1/partner/device` with `{ "name": "...", "venue_type": "..." }`
- **Record an impression batch:** `POST /v1/partner/impressions/batch` (for offline-sync SDKs)
- **Create a webhook:** `POST /v1/partner/webhooks` with `{ "url", "events" }` — payloads are HMAC-signed
- **Get screen earnings:** `GET /v1/partner/connect/earnings?range=7d`

## 6. Optimize AI creatives on real screens

Follow the [Creative AI Feedback Loop](https://api.trillboards.com/docs/guides/integrations/creative-feedback) to fund inventory, generate or import images, review and serve variants, and use measured attention and dwell to iterate your model through REST, MCP or the TypeScript SDK.

Install `@trillboards/api-client@3.2.1` for typed funding, native MCP buying, creative experiments, historical queries and the live audience tail. The walkthrough includes stable purchase keys, Stripe balance readback and correction-aware reward scans. Purchased HUD packages run locally without company credentials and then use this same account for paid live delivery.

## Next steps

- Full reference: [`/docs/partner`](https://api.trillboards.com/docs/partner)
- Error catalog: [`/docs/errors`](https://api.trillboards.com/docs/errors)
- Partner API client: `npm install @trillboards/api-client`
- Screen playback SDK: `npm install @trillboards/ads-sdk`
