# HTTP API

Base URL, authentication with API keys, the main endpoints for apps, builds, submissions and OTA updates, and the error format of the Ubriot API.

The `ubriot` CLI and the `ubriot-mcp` server both use this API. Prefer them where they cover the task; use the API directly when you need something they do not do.

## Base URL and auth

- Base URL: `https://api.ubriot.dev/api/v1`
- Health check, no auth: `GET https://api.ubriot.dev/api/v1/health` returns `{"ok":true,...}`.
- Auth: `Authorization: Bearer <token>`, where the token is an API key (`ubk_...`) from [ubriot.dev/dashboard/api-keys](https://ubriot.dev/dashboard/api-keys) or a session token from signing in.
- Request and response bodies are JSON. Wherever a path has `:appId` or `:id` for an app, the numeric id or the app slug both work.

```bash
curl -s https://api.ubriot.dev/api/v1/ubriot/apps \
  -H "Authorization: Bearer $UBRIOT_TOKEN"
```

There is no published OpenAPI document yet. The endpoints below are the stable ones the CLI and MCP server depend on.

## Main endpoints

Paths are relative to the base URL. "Key" means an API key works; "Session" means it needs a signed-in session.

| Method and path | Auth | What it does |
|---|---|---|
| `GET /ubriot/apps` | Key | List apps. |
| `POST /ubriot/apps` | Key | Create an app: `name`, `slug`, optional `repoUrl`, `defaultBranch`, `iosBundleIdentifier`, `androidApplicationId`, `expoProjectRoot`. |
| `GET /ubriot/apps/:appId` | Key | Get one app. |
| `PATCH /ubriot/apps/:appId` | Key | Update app settings. |
| `GET /ubriot/apps/:appId/readiness` | Key | Credential and configuration checklist. |
| `GET /ubriot/apps/:appId/activity` | Key | Who changed what on the app. |
| `POST /ubriot/apps/:appId/builds` | Key | Queue a build: `platform` (`ios` or `android`), optional `profile`, `branch`, `repoUrl`. |
| `GET /ubriot/apps/:appId/builds` | Key | List an app's builds. |
| `GET /ubriot/builds` | Key | List recent builds across apps. |
| `GET /ubriot/builds/queue` | Key | Why queued builds have not started. |
| `GET /ubriot/builds/last-good` | Key | Last successful build per app, platform and profile. |
| `GET /ubriot/builds/:id` | Key | Build status, error and submission state. |
| `GET /ubriot/builds/:id/logs` | Key | Build log. |
| `GET /ubriot/builds/:id/artifacts` | Key | Build artifacts. |
| `GET /ubriot/artifacts/:id/link` | Key | A download link for an artifact. |
| `POST /ubriot/builds/:id/cancel` | Key | Cancel a queued or running build. |
| `POST /ubriot/builds/:id/submit-testflight` | Key | Upload an iOS build to TestFlight. |
| `POST /ubriot/builds/:id/submit-google-play` | Key | Upload an Android build to Google Play: optional `track`, `releaseStatus`, `rolloutPercentage`, `releaseNotes`. |
| `GET /ubriot/apps/:appId/updates` | Key | List OTA updates. |
| `POST /ubriot/apps/:appId/channels/:channel/rollback` | Key | Roll an OTA channel back. |
| `GET /ubriot/apps/:appId/health` | Key | Release health status. |
| `GET /ubriot/analytics/builds` | Key | Build analytics. |
| `/ubriot/apps/:appId/credentials`, `/ubriot/account/credentials` | Session | Signing credentials. |
| `/ubriot/apps/:appId/channels` | Session | List, create and repoint OTA channels. |
| `/ubriot/apps/:appId/push/server-keys` | Session | Push server keys. |
| `/ubriot/api-keys` | Session | Create, list and revoke API keys. |

Publishing an OTA update means uploading an exported JavaScript bundle and its assets. Use `ubriot update` rather than calling the update endpoints directly.

Sending push from your backend uses a push server key in the `x-ubriot-push-key` header, not an API key. See [Notify](https://docs.ubriot.dev/notify.md).

## Errors

Errors return an HTTP status and a JSON body:

```json
{ "statusCode": 401, "message": "Missing token", "error": "Unauthorized" }
```

`message` is a plain sentence, and for billing and setup problems it says what to do next, for example `Verify a payment card at ubriot.dev/dashboard/billing to start your 14-day trial.` Some validation errors return `message` as an array of strings.

Newer errors also carry a stable `code` and a `doc_url` to the guide that fixes them:

```json
{ "statusCode": 403, "code": "email_not_verified", "message": "Verify this account's email address before starting builds or store submissions. ...", "doc_url": "https://docs.ubriot.dev/quickstart#verify-email" }
```

| `code` | Status | Meaning |
|---|---|---|
| `email_not_verified` | `403` | Starting a build or a TestFlight or Google Play submission before the account's email is verified. A person verifies it from the dashboard banner; see [Verify your email](https://docs.ubriot.dev/quickstart.md#verify-email). |
| `account_paused` | `403` | Signing in with the correct password to an account that was paused. See [Create and verify your account](https://docs.ubriot.dev/quickstart.md#account). |
| `signup_network_blocked`, `signup_rate_limited`, `captcha_required`, `captcha_failed`, `captcha_unavailable` | `403`, `429`, `400`, `403`, `503` | Account creation only. See [Create and verify your account](https://docs.ubriot.dev/quickstart.md#account). |

| Status | Usual cause | What to do |
|---|---|---|
| `400` | A missing or invalid field, or a submission already running for the build. | Read `message` and fix the request. |
| `401` | Missing, revoked or wrong token, or an API key used on a session-only route. | Check the token, or sign in for session-only routes. |
| `403` | No trial or plan, an unverified email (`email_not_verified`), or no access to that app. | A person fixes billing at [ubriot.dev/dashboard/billing](https://ubriot.dev/dashboard/billing) or verifies the email from the dashboard. |
| `404` | The app or build does not exist or belongs to another account. | Check the id with `GET /ubriot/apps`. |
| `429` | Rate limited. | Wait and retry with backoff. |

Older errors do not carry a `code` or a `doc_url` yet, and writes do not accept an idempotency key. Before retrying a write that may have succeeded, check its effect first, for example list builds before queueing another one.
