> ## Documentation Index
> Fetch the complete documentation index at: https://docs.satyakod.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API introduction

> Authenticate with an API key and verify codes from your apps, scanners and systems.

The API is at `https://api.satyakod.com/v1`. Apps, scanners and server-to-server integrations call
it with an API key.

## API keys

Admins create keys in **Settings → API**. There are two types:

* **Secret keys** (`vrq_live_…`, `vrq_test_…`) are for your servers. You choose the scopes the key
  may use, and the key is shown once: store it in your secrets manager.
* **Publishable keys** (`pk_live_…`, `pk_test_…`) go in your web page or app. They can only
  verify scans, and only from the websites and apps you list on the key. See
  [Publishable keys](#publishable-keys).

```http theme={null}
Authorization: Bearer vrq_live_…
```

| Scope | Allows |
| - | - |
| `scans:verify` | [Verify a serial](https://docs.satyakod.com/api-reference/verify.md), [read a camera frame](https://docs.satyakod.com/api-reference/scan-frame.md), [upload offline scans](https://docs.satyakod.com/api-reference/verify-offline.md) |
| `scans:read` | Read scans |
| `batches:read` / `batches:write` | Read batches and products / create them |
| `alerts:read` / `alerts:write` | Read alerts / update them |
| `webhooks:write` | Manage webhook endpoints |

Live and test keys call the same API on your workspace's data; label keys used in development as
test so they're easy to find and revoke. Pilot workspaces get test keys only.

> [!WARNING]
>
> Keep secret keys on servers and devices you control. In a web page or an app on consumers' phones,
> use a publishable key, or call your own backend, which holds the secret key.

## Publishable keys

A publishable key is safe to put in a web page or app because it can only do what a consumer's scan
does: [verify a serial](https://docs.satyakod.com/api-reference/verify.md), [read a camera frame](https://docs.satyakod.com/api-reference/scan-frame.md)
and [upload offline scans](https://docs.satyakod.com/api-reference/verify-offline.md) (at most 50 at a time). Every other
endpoint answers `403`.

When you create one, list where it will be used:

* **Websites**: full addresses like `https://www.example.com` (https only; `http://localhost`
  works on test keys). A browser sends its page's address in the `Origin` header; calls from other
  sites get `401`, and browsers on other sites are refused by CORS.
* **Apps**: the Android package or iOS bundle id, like `com.example.app`. The app sends it on every
  call:

```http theme={null}
Authorization: Bearer pk_live_…
X-Satyakod-App: com.example.app
```

The key stays visible in **Settings → API**, where admins can copy it and change its websites and
apps (changes apply within a minute). Lookups with a publishable key are always recorded as scans
(`dryRun` is ignored), so scripted lookups show up in **Scans** and raise the serial enumeration
alert, and each key is rate limited per phone or browser. Revoke a key and its calls stop at once.

## Requests and responses

* JSON with camelCase field names. Dates are ISO 8601; money is `{"amountMinor": 41500, "currency": "INR"}` in minor units.
* Lists are `{"items": [...], "total": 120, "page": 1, "pageSize": 20}`.
* Errors are `400` with the field and what's wrong (`{"serial": ["Required."]}`), `401` for a
  missing or revoked key, `403` for a key without the scope, and `429` when you are over the rate
  limit (a `Retry-After` header says when to try again).
* A request for a feature your [plan](https://docs.satyakod.com/guides/plans.md) doesn't include, such as a Private Code batch
  on Launch, answers `403` with `"error": "not_in_plan"`, the feature, a message you can show and
  your plan's name. Private Code design limits also carry `limit`, the number of designs your plan
  allows:

  ```json theme={null}
  {
    "error": "not_in_plan",
    "feature": "private_code",
    "detail": "Private Code is available on Scale and Enterprise. Contact us to upgrade.",
    "plan": "Launch"
  }
  ```

  Features: `private_code` (Private Code batches), `private_code_designs`, `code_studio` (Code
  Studio and scan tests), `erp_print_integrations` (Zebra printers and SAP S/4HANA),
  `whatsapp_bot` (the WhatsApp verify bot) and `sso_scim` (requiring SSO, SCIM provisioning and the
  audit log CSV export).
* Every response has an `X-Correlation-Id`; quote it when you contact support.

## Reading Private Codes

Private Codes are read only on Satyakod's servers: your app sends camera frames to
[`POST /v1/scan-frame`](https://docs.satyakod.com/api-reference/scan-frame) and gets the verdict. The reader and its keys
never ship in an app.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.