---
title: "Account & provisioning"
description: "Sign up, get an API key, set your webhook URL, and go live. These calls use your dashboard session, not your API key, and your application never makes them."
---

# Account & provisioning

Sign up, get an API key, set your [webhook](/docs/concepts/webhooks) URL, go live. Dashboard session, not your API key.

These calls use your dashboard session, not your API key. Your application does not call them. You call them once, while setting QuotaStack up.

You will normally do all of this in the
[dashboard](https://platform.quotastack.io). The calls are written down here
so you can automate the setup instead, if you would rather.

Nine of them are yours. Sign up, confirm your email, make and revoke API keys,
read and change your tenant settings, and rotate your
[webhook](/docs/concepts/webhooks) signing secret.

Five of them belong to QuotaStack. Those approve, refuse, or pause your access
to the live [environment](/docs/concepts/environments). Your key cannot call
them, whatever it holds.

Every other page in this reference is the product API, which your application
does call, with your API key.

14 setup calls. This page summarises them; your application does not call them.

## Start public self-serve signup.

`POST /v1/admin/auth/signup`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Body parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `name` | string | required |  |
| `email` | string (email) | required |  |
| `password` | string | required |  |
| `company_name` | string | required |  |
| `captcha_token` | string | optional |  |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `message` | string | required |  |

### Errors

- `400` — Malformed request.
- `409` — State conflict (e.g., duplicate resource, stale version).
- `422` — Request shape was valid but field validation failed.

## Verify signup email and create an admin session.

`POST /v1/admin/auth/verify-email`

- **Idempotency-Key:** Not required for this operation.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Body parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `token` | string | required |  |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `user` | object | required |  |
| `tenant` | object | required |  |
| `token` | string | required |  |

### Errors

- `400` — Malformed request.

## Resend signup email verification when available.

`POST /v1/admin/auth/resend-verification`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Body parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `email` | string (email) | required |  |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `message` | string | required |  |

### Errors

- `409` — State conflict (e.g., duplicate resource, stale version).
- `422` — Request shape was valid but field validation failed.

## List the tenant's API keys.

`GET /v1/admin/api-keys`

- **Idempotency-Key:** Not used. This is a read.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `data` | array | optional |  |

### Errors

- `401` — Missing or invalid authentication.

## Create a tenant API key from the admin dashboard.

`POST /v1/admin/api-keys`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Body parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `environment` | string | required | Which environment this resource lives in. Determined by the API key prefix used (`qs_live_…` → live, `qs_test_…` → sandbox). `live` `sandbox` |
| `name` | string | optional |  |
| `scopes` | array | optional |  |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `id` | string (uuid) | optional |  |
| `tenant_id` | string (uuid) | optional |  |
| `environment` | string | optional | Which environment this resource lives in. Determined by the API key prefix used (`qs_live_…` → live, `qs_test_…` → sandbox). `live` `sandbox` |
| `key_prefix` | string | optional |  |
| `name` | string | optional |  |
| `scopes` | array | optional |  |
| `created_at` | string (date-time) | optional |  |
| `key` | string | optional |  |

### Errors

- `403` — Authenticated but not permitted (insufficient scope).
- `409` — State conflict (e.g., duplicate resource, stale version).
- `422` — Request shape was valid but field validation failed.

## Revoke a tenant API key from the admin dashboard.

`POST /v1/admin/api-keys/{id}/revoke`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Path parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `id` | string (uuid) | required |  |

### Errors

- `403` — Authenticated but not permitted (insufficient scope).
- `404` — Resource not found.
- `409` — State conflict (e.g., duplicate resource, stale version).
- `422` — Request shape was valid but field validation failed.

## Read the tenant's configuration.

`GET /v1/admin/tenants/{tenant_id}/config`

- **Idempotency-Key:** Not used. This is a read.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Path parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | required |  |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | optional |  |
| `webhook_url` | string | optional |  |
| `webhook_secret_set` | boolean | optional | True when a webhook signing secret exists for this tenant. The secret itself is never returned here. To get a secret, call POST /v1/admin/tenants/{tenant_id}/webhook-secret/rotate. That endpoint returns the new secret one time. |
| `overage_policy` | string | optional | `block` `allow` `notify` |
| `default_currency` | string | optional |  |
| `timezone` | string | optional |  |
| `data_region` | string | optional |  |
| `low_balance_threshold_mc` | integer (int64) | optional | Default threshold (millicredits) for `credit.low_balance` webhooks. `0` (default) disables low_balance for customers that inherit this value. Per-customer override via `Customer.low_balance_threshold_mc`. `credit.exhausted` is always on and ignores this field. Range: 0–∞. |
| `credit_expiring_soon_hours` | integer | optional | Lead time in hours for `credit.expiring_soon` webhooks (per credit block). `0` (default) disables the alert. Recommended: `72` for packs / annual grants. Maximum: `8760` (1 year). No per-customer override in Phase 1. Range: 0–8760. |
| `updated_at` | string (date-time) | optional |  |

### Errors

- `401` — Missing or invalid authentication.
- `403` — Authenticated but not permitted (insufficient scope).
- `404` — Resource not found.

## Update the tenant's configuration (partial).

`PATCH /v1/admin/tenants/{tenant_id}/config`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Path parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | required |  |

### Body parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `webhook_url` | string | optional |  |
| `overage_policy` | string | optional | `block` `allow` `notify` |
| `default_currency` | string | optional |  |
| `timezone` | string | optional | IANA timezone name. |
| `low_balance_threshold_mc` | integer (int64) | optional | Millicredits. 0 = low_balance alerts off (default). Range: 0–∞. |
| `credit_expiring_soon_hours` | integer | optional | Hours before `expires_at` to emit `credit.expiring_soon` (0 = off). Recommended: 72. Maximum: 8760 (1 year). Range: 0–8760. |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | optional |  |
| `webhook_url` | string | optional |  |
| `webhook_secret_set` | boolean | optional | True when a webhook signing secret exists for this tenant. The secret itself is never returned here. To get a secret, call POST /v1/admin/tenants/{tenant_id}/webhook-secret/rotate. That endpoint returns the new secret one time. |
| `overage_policy` | string | optional | `block` `allow` `notify` |
| `default_currency` | string | optional |  |
| `timezone` | string | optional |  |
| `data_region` | string | optional |  |
| `low_balance_threshold_mc` | integer (int64) | optional | Default threshold (millicredits) for `credit.low_balance` webhooks. `0` (default) disables low_balance for customers that inherit this value. Per-customer override via `Customer.low_balance_threshold_mc`. `credit.exhausted` is always on and ignores this field. Range: 0–∞. |
| `credit_expiring_soon_hours` | integer | optional | Lead time in hours for `credit.expiring_soon` webhooks (per credit block). `0` (default) disables the alert. Recommended: `72` for packs / annual grants. Maximum: `8760` (1 year). No per-customer override in Phase 1. Range: 0–8760. |
| `updated_at` | string (date-time) | optional |  |

### Errors

- `401` — Missing or invalid authentication.
- `403` — Authenticated but not permitted (insufficient scope).
- `404` — Resource not found.
- `409` — State conflict (e.g., duplicate resource, stale version).
- `422` — Request shape was valid but field validation failed.

## Rotate the tenant's webhook signing secret.

`POST /v1/admin/tenants/{tenant_id}/webhook-secret/rotate`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Path parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | required |  |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `webhook_secret` | string | required | New base64 signing secret. Store it now — it is not shown again. |

### Errors

- `401` — Missing or invalid authentication.
- `403` — Authenticated but not permitted (insufficient scope).
- `404` — Resource not found.
- `409` — State conflict (e.g., duplicate resource, stale version).
- `422` — Request shape was valid but field validation failed.

## Approve live access for a tenant.

`POST /v1/tenants/{id}/live-access/approve`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Path parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `id` | string (uuid) | required | QuotaStack tenant UUID. |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | required |  |
| `live_access_status` | string | required |  |
| `reviewed_at` | string (date-time) | optional |  |

### Errors

- `403` — Authenticated but not permitted (insufficient scope).
- `404` — Resource not found.
- `409` — State conflict (e.g., duplicate resource, stale version).

## Reject live access for a tenant.

`POST /v1/tenants/{id}/live-access/reject`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Path parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `id` | string (uuid) | required | QuotaStack tenant UUID. |

### Body parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `reason` | string | required |  |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | required |  |
| `live_access_status` | string | required |  |

### Errors

- `403` — Authenticated but not permitted (insufficient scope).
- `404` — Resource not found.
- `409` — State conflict (e.g., duplicate resource, stale version).

## Suspend live access for a tenant.

`POST /v1/tenants/{id}/live-access/suspend`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Path parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `id` | string (uuid) | required | QuotaStack tenant UUID. |

### Body parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `reason` | string | required |  |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | required |  |
| `live_access_status` | string | required |  |

### Errors

- `403` — Authenticated but not permitted (insufficient scope).
- `404` — Resource not found.
- `409` — State conflict (e.g., duplicate resource, stale version).

## Suspend sandbox access for a tenant.

`POST /v1/tenants/{id}/sandbox-access/suspend`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Path parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `id` | string (uuid) | required | QuotaStack tenant UUID. |

### Body parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `reason` | string | required |  |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | required |  |
| `sandbox_access_status` | string | required |  |

### Errors

- `403` — Authenticated but not permitted (insufficient scope).
- `404` — Resource not found.
- `409` — State conflict (e.g., duplicate resource, stale version).

## Enable sandbox access for a tenant.

`POST /v1/tenants/{id}/sandbox-access/enable`

- **Idempotency-Key:** Required. Returns 422 without it.
- **Environment:** Sandbox and Live
- **Auth:** Dashboard session
- **Fires:** No webhooks.

> Not yet documented in full. The fields below come from the API spec.

### Header parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `Idempotency-Key` | string | required | Required idempotency key for this mutating admin/public operation. Reusing the same key with a different body returns `409 Conflict`; successful 2xx and client 4xx responses are cached for 24 hours. |

### Path parameters

| Field | Type | Required | Meaning |
|---|---|---|---|
| `id` | string (uuid) | required | QuotaStack tenant UUID. |

### Response fields

| Field | Type | Required | Meaning |
|---|---|---|---|
| `tenant_id` | string (uuid) | required |  |
| `sandbox_access_status` | string | required |  |

### Errors

- `403` — Authenticated but not permitted (insufficient scope).
- `404` — Resource not found.
- `409` — State conflict (e.g., duplicate resource, stale version).
