Customers
A customer is the account that owns your VerifyAI data. Every API key
acts on behalf of exactly one customer, and that customer_id is what
scopes everything else: the verifications you can read, the policies your
keys can run, and the webhook endpoints you register all belong to a
single customer.
If you run VerifyAI for one organization, you have one customer and rarely touch these endpoints — your key already resolves to it. If you're a platform reselling VerifyAI to your own users, customers are how you keep each tenant's data isolated.
How customer_id flows through the API
customer_id is the spine of account isolation:
- API keys resolve to a
customer_idat authentication time. A key can only read and write data for its own customer. - Policies are either system policies (
customer_id = null, like the built-inscooter_parking) or custom policies owned by one customer. - Verifications are written under the authenticating key's
customer_id, and list/retrieve only ever return that customer's rows. - Inspection sessions and webhook deliveries carry the
customer_idso you can route them per tenant — theinspection.submittedwebhook payload includes it directly.
Because the key already resolves to a customer, the verify and
verifications endpoints never ask you for a customer_id — they infer
it from the key. These customer endpoints exist for reading your own
account record and, for platform integrations, provisioning sub-accounts.
The customer object
{
"id": "cus_forest1",
"name": "Forest (HumanForest)",
"status": "active",
"created_at": "2026-01-08T09:00:00Z",
"metadata": {
"region": "london",
"external_account_id": "acct_8821"
}
}Fields
| Field | Type | Description |
| ------------ | -------- | --------------------------------------------------------------------------------- |
| id | string | Stable customer identifier, prefix cus_. This is the customer_id on keys/policies. |
| name | string | Display name for the account. |
| status | string | active, paused, or cancelled. A non-active customer's keys return 403. |
| created_at | ISO 8601 | When the customer was created. |
| metadata | object? | Free-form key/value data you attach (e.g. your own account ID, region). |
Authentication
| Header | Required | Value |
| ----------- | -------- | ------------------------------------------------------ |
| X-API-Key | Yes | Your vai_… key. See Authentication. |
Most accounts manage their customer record from Dashboard →
Settings, and platform sub-account provisioning is enabled per
integration. If a call below returns 404, the programmatic surface
isn't enabled for your account yet — the request and response shapes
match what ships. Contact support to turn on multi-customer
provisioning.
Retrieve the current customer
GET /api/v1/customers/meReturns the customer the authenticating key belongs to. This is the call
to make when you want to confirm which account a key resolves to, or read
your own status.
curl https://verify.switchlabs.dev/api/v1/customers/me \
-H "X-API-Key: vai_your_api_key"{
"id": "cus_forest1",
"name": "Forest (HumanForest)",
"status": "active",
"created_at": "2026-01-08T09:00:00Z",
"metadata": { "region": "london" }
}List customers
GET /api/v1/customersFor platform integrations only. Returns the sub-accounts you've provisioned, newest first. A single-tenant account sees just its own record.
Query parameters
| Parameter | Type | Default | Description |
| --------- | ------ | ------- | ---------------------------------------------------- |
| limit | number | 20 | Page size. Clamped to a maximum of 100. |
| cursor | string | — | Pagination cursor. Pass next_cursor from the prior page. |
| status | string | — | Filter by active, paused, or cancelled. |
curl "https://verify.switchlabs.dev/api/v1/customers?limit=20&status=active" \
-H "X-API-Key: vai_your_api_key"{
"data": [
{
"id": "cus_forest1",
"name": "Forest (HumanForest)",
"status": "active",
"created_at": "2026-01-08T09:00:00Z"
}
],
"has_more": false,
"next_cursor": null
}Pagination follows the same cursor contract as
Verifications: pass next_cursor
back as cursor until has_more is false.
Create a customer
POST /api/v1/customersFor platform integrations. Provisions a new sub-account under your organization. Issue that customer a key via the API keys endpoint to let it submit verifications independently.
Body parameters
| Parameter | Type | Required | Description |
| ---------- | ------ | -------- | ------------------------------------------------------------------------ |
| name | string | Yes | Display name for the new customer. |
| metadata | object | No | Free-form data to attach (your own account ID, region, plan, etc.). |
curl -X POST https://verify.switchlabs.dev/api/v1/customers \
-H "X-API-Key: vai_your_api_key" \
-H "Content-Type: application/json" \
-d '{ "name": "Acme Mobility", "metadata": { "external_account_id": "acct_991" } }'{
"id": "cus_9q2v8m",
"name": "Acme Mobility",
"status": "active",
"created_at": "2026-06-01T12:00:00Z",
"metadata": { "external_account_id": "acct_991" }
}Errors
| Status | Reason |
| ------ | ------------------------------------------------------------------- |
| 400 | Missing name, or invalid metadata. |
| 401 | Missing or invalid API key. |
| 403 | Key not valid for VerifyAI, not linked to a customer, or lacks platform provisioning. |
| 404 | No customer with that id, or it belongs to a different organization. |
| 429 | Rate limit — check the Retry-After header. |
| 503 | Authentication service unavailable. Retry. |
What's next
- API keys — issue a key scoped to a customer.
- Concepts: Verifications — how
customer_idscopes the verification history you can read. - Policies API — system policies vs. custom policies owned by a customer.