Skip to main content

Authentication

Stateway uses API keys for authentication. Every API request must include a valid API key in the X-API-Key header.

API Key Format

Stateway API keys follow a prefixed format:

sw_live_abc123...

The sw_live_ prefix identifies the key as a Stateway live key. All API keys are hashed at rest.

Registering a Tenant

Registration is a two-step process: submit your details, then verify your email address.

Step 1 — Submit registration

Request:

curl -X POST https://api.stateway.io/v1/register \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Corp",
"email": "admin@acmecorp.com"
}'

Response:

{
"data": {
"tenantId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"status": "pending_verification",
"message": "A 6-digit verification code has been sent to your email. It is valid for 10 minutes."
}
}

An optional slug field can be provided. If omitted, it is derived from name.

Step 2 — Verify email and get your API key

Request:

curl -X POST https://api.stateway.io/v1/register/verify \
-H "Content-Type: application/json" \
-d '{
"tenantId": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"verificationCode": "482910"
}'

Response:

{
"data": {
"tenant": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "Acme Corp",
"slug": "acme-corp",
"email": "admin@acmecorp.com",
"plan": "free"
},
"apiKey": {
"id": "9a8b7c6d-...",
"key": "sw_live_Kx9mN2pQ4rT7vY1w...",
"prefix": "sw_live_Kx9m",
"name": "Default API Key",
"scopes": ["admin"],
"createdAt": "2026-04-26T12:00:00.000Z"
}
}
}
warning

The key value is only shown once at this step. Store it securely — you cannot retrieve it later.

Making Authenticated Requests

Include the API key in every request:

Request:

curl https://api.stateway.io/v1/definitions \
-H "X-API-Key: sw_live_Kx9mN2pQ4rT7vY1w..."

Response:

{
"data": [
{
"id": "def_01j...",
"key": "expense-approval",
"version": 1,
"name": "Expense Approval",
"source_type": "json",
"is_active": true,
"created_at": "2026-04-26T12:00:00.000Z"
}
]
}

How Tenant Resolution Works

Stateway implements multitenancy by API key. When a request arrives with a valid X-API-Key header:

  1. The key is validated and looked up
  2. The associated tenant is resolved automatically
  3. All subsequent operations are scoped to that tenant

You never need to pass tenant_id in request bodies, query parameters, or URLs. The API key handles tenant resolution transparently.

API Key Scopes

Each API key has a list of scopes that controls what it can do. The admin scope grants full access. Scoped keys allow least-privilege access per integration.

ScopeAccess
definitions:readRead process and decision definitions
definitions:writeCreate, update, delete definitions
instances:readRead instances, tokens, variables, history
instances:writeStart, suspend, resume, terminate instances; update variables; send events
tasks:readRead human tasks
tasks:writeClaim, unclaim, complete, delegate tasks
webhooks:manageCreate, update, delete webhook subscriptions
credentials:readList and inspect credential metadata
credentials:writeCreate, rotate, delete credentials
adminFull access to all operations

The first key created on registration has the admin scope. When creating additional keys, pass only the scopes needed.

Managing API Keys

List API Keys

Request:

curl https://api.stateway.io/v1/auth/keys \
-H "X-API-Key: sw_live_Kx9mN2pQ4rT7vY1w..."

Response:

{
"data": [
{
"id": "9a8b7c6d-...",
"prefix": "sw_live_Kx9m",
"name": "Default API Key",
"scopes": ["admin"],
"created_at": "2026-04-26T12:00:00.000Z",
"last_used_at": "2026-04-27T08:30:00.000Z"
}
]
}

Create Additional API Keys

Request:

curl -X POST https://api.stateway.io/v1/auth/keys \
-H "X-API-Key: sw_live_Kx9mN2pQ4rT7vY1w..." \
-H "Content-Type: application/json" \
-d '{
"name": "CI/CD Pipeline",
"scopes": ["definitions:write", "instances:write"]
}'

Response:

{
"data": {
"id": "a1b2c3d4-...",
"key": "sw_live_newkey...",
"prefix": "sw_live_newk",
"name": "CI/CD Pipeline",
"scopes": ["definitions:write", "instances:write"],
"createdAt": "2026-04-27T09:00:00.000Z"
}
}

Revoke an API Key

Request:

curl -X DELETE https://api.stateway.io/v1/auth/keys/{key_id} \
-H "X-API-Key: sw_live_Kx9mN2pQ4rT7vY1w..."

Returns 204 No Content. Revoked keys are immediately invalid. Any in-flight requests using a revoked key will receive a 401 UNAUTHORIZED response.

API key cache

Stateway caches API key lookups for up to 60 seconds. A revoked key may continue to work for up to 60 seconds after revocation due to this cache.

Tenant Management

Get Current Tenant

Request:

curl https://api.stateway.io/v1/tenant \
-H "X-API-Key: sw_live_Kx9mN2pQ4rT7vY1w..."

Response:

{
"data": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "Acme Corp",
"slug": "acme-corp",
"email": "admin@acmecorp.com",
"plan": "free"
}
}

Update Tenant Settings

Request:

curl -X PUT https://api.stateway.io/v1/tenant \
-H "X-API-Key: sw_live_Kx9mN2pQ4rT7vY1w..." \
-H "Content-Type: application/json" \
-d '{ "name": "Acme Corp (Updated)" }'

Response:

{
"data": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "Acme Corp (Updated)",
"slug": "acme-corp",
"email": "admin@acmecorp.com",
"plan": "free"
}
}

Error Responses

StatusError CodeDescription
401UNAUTHORIZEDMissing or invalid API key
403FORBIDDENValid key but insufficient permissions

Example 401 response:

{
"error": {
"code": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
}

Best Practices

  • Rotate keys regularly — revoke old keys and create new ones
  • Use separate keys per environment (development, staging, production)
  • Use separate keys per integration (web app, CI/CD, monitoring)
  • Never commit keys to source control — use environment variables
  • Never log API keys — they are the equivalent of tenant credentials