Skip to main content

Subscription Lifecycle

How subscriptions flow from request to active API key β€” with approval workflows, state transitions, and gateway provisioning.

Overview​

Every API or MCP tool access in STOA goes through a subscription. Subscriptions connect a consumer (who wants access) to an API (what they want to access) via a plan (how much access they get).

Subscription States​

StateAccessTransition FromTransition To
pendingNone β€” awaiting approval[*]active, revoked
activeFull API accesspending, suspendedsuspended, revoked, expired
suspendedBlocked temporarilyactiveactive, revoked
revokedPermanently cancelledpending, active, suspendedTerminal
expiredAuto-expiredactiveTerminal

API Key Format​

When a subscription is approved, STOA generates a unique API key:

stoa_sk_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4
β””β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
prefix 32 hex characters (128 bits entropy)
VariantPrefixUsage
REST API subscriptionstoa_sk_Standard API access via X-API-Key header
MCP server subscriptionstoa_mcp_MCP tool access via gateway

Security:

  • The full API key is returned once at creation β€” store it securely
  • STOA stores only a SHA-256 hash β€” the key cannot be recovered
  • The prefix (stoa_sk_a1b2) is stored for identification in dashboards
Configure your environment

The examples below use environment variables. Set them for your STOA instance:

export STOA_API_URL="https://api.gostoa.dev"       # Replace with your domain
export STOA_AUTH_URL="https://auth.gostoa.dev" # Keycloak OIDC provider
export STOA_GATEWAY_URL="https://mcp.gostoa.dev" # MCP Gateway endpoint

Self-hosted? Replace gostoa.dev with your domain.

Create a Subscription​

Via REST API​

curl -X POST "${STOA_API_URL}/v1/subscriptions" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{
"api_id": "billing-api",
"plan_name": "gold",
"application_name": "my-payment-app"
}'

Response:

{
"id": "sub-uuid-123",
"status": "pending",
"api_key": "stoa_sk_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
"api_key_prefix": "stoa_sk_a1b2",
"api_name": "billing-api",
"plan_name": "gold",
"created_at": "2026-02-13T10:00:00Z"
}
Save Your API Key

The api_key field is only returned once. Copy it to a secure location (e.g., Infisical, environment variable). It cannot be retrieved later β€” only rotated.

Via Developer Portal​

  1. Browse the API Catalog at portal.<YOUR_DOMAIN>
  2. Click Subscribe on any API
  3. Select a plan (e.g., Gold, Silver, Community)
  4. Name your application
  5. Click Request Access
  6. Copy your API key from the confirmation screen

Approval Workflows​

Manual Approval (Default)​

When a plan has requires_approval: true, subscriptions start in pending state:

# Admin: List pending subscriptions for your tenant
curl "${STOA_API_URL}/v1/subscriptions/tenant/${TENANT_ID}/pending" \
-H "Authorization: Bearer ${TOKEN}"

# Admin: Approve a subscription
curl -X POST "${STOA_API_URL}/v1/subscriptions/${SUB_ID}/approve" \
-H "Authorization: Bearer ${TOKEN}"

Auto-Approval​

Plans can define roles that bypass manual approval:

{
"slug": "community",
"name": "Community Plan",
"requires_approval": false,
"auto_approve_roles": ["tenant-admin", "devops"]
}

When requires_approval is false, subscriptions go directly to active and the API key is usable immediately.

State Transitions​

Suspend a Subscription​

Temporarily blocks access (e.g., billing issues, abuse detection):

curl -X POST "${STOA_API_URL}/v1/subscriptions/${SUB_ID}/suspend" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"reason": "Payment overdue"}'

The consumer receives a 401 Unauthorized error on API calls. The API key is not deleted β€” it can be reactivated.

Reactivate a Subscription​

curl -X POST "${STOA_API_URL}/v1/subscriptions/${SUB_ID}/reactivate" \
-H "Authorization: Bearer ${TOKEN}"

Revoke a Subscription​

Permanently cancels access β€” cannot be undone:

curl -X POST "${STOA_API_URL}/v1/subscriptions/${SUB_ID}/revoke" \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"reason": "Terms of service violation"}'

Gateway Provisioning​

When a subscription is approved, STOA provisions the API route on the gateway. This process is tracked via a separate provisioning status:

Provisioning StatusMeaning
noneNo gateway provisioning needed
pendingQueued for provisioning
provisioningRoute being created on gateway
readyRoute active β€” traffic flowing
failedProvisioning error (check provisioning_error)
deprovisioningRoute being removed
deprovisionedRoute removed from gateway

Using Your API Key​

Once your subscription is active and provisioning is ready, use the API key:

curl "${STOA_GATEWAY_URL}/apis/${TENANT_ID}/${API_NAME}/v1/endpoint" \
-H "X-API-Key: stoa_sk_a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4"

The gateway validates the key, checks the subscription status, and applies the plan's rate limits before forwarding to the backend.

Subscription Plans​

Plans define the quotas and approval rules for subscriptions:

FieldTypeDescription
slugstringUnique identifier per tenant (e.g., gold)
rate_limit_per_secondintMax requests per second
rate_limit_per_minuteintMax requests per minute
daily_request_limitintMax requests per day
monthly_request_limitintMax requests per month
burst_limitintMax concurrent requests
requires_approvalboolWhether admin must approve
auto_approve_roleslistRoles that skip approval

Example Plans​

PlanRate/minDailyMonthlyApproval
Community6010,000100,000Auto
Silver30050,0001,000,000Auto
Gold1,000500,00010,000,000Manual
EnterpriseCustomCustomCustomManual