# Authentication

URL: https://submitator.com/docs/authentication

> Send your secret key in the Authorization header, from your server only.

Every request carries your secret key as a bearer token. A request without a valid key gets 401 and changes nothing.

```bash
curl https://api.submitator.com/v1/ping \
  -H "Authorization: Bearer $SUBMITATOR_API_KEY"
```

The key goes in the `Authorization` header only: the API reads it from nowhere else, such as the query string.

## Keys

A key is a prefix, 8 letters or digits, an underscore and 43 more letters or digits:

```text
sbm_live_8fK2qL7x_Vb3Nc8Tk3HwPm2Lr9Xz5Qa1Ws4Ed7Rf0Tg6Yh8Uj3Ik
```

| Prefix | Mode | What it does |
| --- | --- | --- |
| `sbm_live_` | Live | Works on real listings and spends real launches. Live keys come with your first purchase. |
| `sbm_test_` | Test | Runs every call on test data: nothing is submitted and nothing is spent. Test keys are free from the day you create your agency. |

The key decides the mode: there is no `livemode` parameter, and sending one returns 400 `unknown_parameter`. Each mode has its own projects, listings, events and webhook endpoints. An id from one mode returns 404 `not_found` with a key of the other.

`GET /ping` shows which key you sent: its `key.id` (such as `key_3Rw8Kx2Lq9Vt5Nb1Zm7HcW`) is safe to log and to quote to support, the key itself is not.

## Permissions

You choose a key's permissions when you create it, and `GET /ping` returns them in `key.permissions`.

| Permissions | What the key can do |
| --- | --- |
| `full` | Read and write: create projects, launch them and spend launches. |
| `read_only` | Read only. A call that changes data returns 403 `permission_denied` and changes nothing. |

A read-only key reads everything but logins: the [Logins](https://submitator.com/docs/api/logins) operations, and the file of a report with logins, answer it with 403 `permission_denied`.

Give a read-only key to anything that only reads, such as a dashboard or the job that copies statuses into your CRM. If that key leaks, it cannot spend a launch.

## Create, roll and revoke

Keys live in the console, under Developers: live keys on the LIVE tab, test keys on the TEST tab. A new key is shown once: store it in your secret manager right away.

- **Roll** replaces a key. You choose when the old key stops working: now, in 1 hour or in 24 hours, so your servers can switch without downtime.
- **Revoke** stops a key at once. The console asks you to type the key's label first.

If a key leaks, roll it with "now" and deploy the new one.

## Keep keys on your server

A key acts for your whole agency: it can create projects and spend launches. Keep it out of anything a person outside your team can open.

- Never put a key in a browser, a mobile app or a desktop app. The API sends no CORS headers, so browser calls fail anyway; call it from your server.
- Never commit a key to a repository. Read it from an environment variable, such as `SUBMITATOR_API_KEY` in these docs.
- Give each server or integration its own key, so you can roll one without touching the others.

## Errors

| Code | Status | When |
| --- | --- | --- |
| [`api_key_missing`](https://submitator.com/docs/errors#api_key_missing) | 401 | The request has no `Authorization` header. |
| [`api_key_invalid`](https://submitator.com/docs/errors#api_key_invalid) | 401 | The key is unknown, revoked or expired. |
| [`account_suspended`](https://submitator.com/docs/errors#account_suspended) | 403 | Your account is suspended: reads work, writes do not. |
| [`permission_denied`](https://submitator.com/docs/errors#permission_denied) | 403 | A read-only key called an operation that changes data. |
| [`not_found`](https://submitator.com/docs/errors#not_found) | 404 | The id belongs to the other mode: a live id sent with a test key, or the other way round. |

A read-only key also gets `permission_denied` from the [Logins](https://submitator.com/docs/api/logins) operations and from the file of a report with logins.
