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"
}
}
}
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:
- The key is validated and looked up
- The associated tenant is resolved automatically
- 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.
| Scope | Access |
|---|---|
definitions:read | Read process and decision definitions |
definitions:write | Create, update, delete definitions |
instances:read | Read instances, tokens, variables, history |
instances:write | Start, suspend, resume, terminate instances; update variables; send events |
tasks:read | Read human tasks |
tasks:write | Claim, unclaim, complete, delegate tasks |
webhooks:manage | Create, update, delete webhook subscriptions |
credentials:read | List and inspect credential metadata |
credentials:write | Create, rotate, delete credentials |
admin | Full 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.
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
| Status | Error Code | Description |
|---|---|---|
401 | UNAUTHORIZED | Missing or invalid API key |
403 | FORBIDDEN | Valid 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