Skip to main content

OpenAPI Reference

The Control Plane API is documented using OpenAPI 3.1.0. The specification is auto-generated from FastAPI route definitions and kept in sync via CI.

Live Documentation​

The API serves interactive documentation at:

FormatURLDescription
Swagger UIhttps://api.<YOUR_DOMAIN>/docsInteractive API explorer
ReDochttps://api.<YOUR_DOMAIN>/redocRead-optimized documentation
OpenAPI JSONhttps://api.<YOUR_DOMAIN>/openapi.jsonRaw specification

Endpoint Categories​

The API organizes endpoints into the following groups:

CategoryPrefixEndpointsDescription
APIs/v1/apisCRUD + syncAPI lifecycle management
Tenants/v1/tenantsCRUD + membersTenant management
Subscriptions/v1/subscriptionsCRUD + approve/revokeSubscription lifecycle
Consumers/v1/consumersCRUD + keysConsumer management
Gateways/v1/gatewaysCRUD + healthGateway instance management
Deployments/v1/deploymentsList + promoteDeployment tracking
Environments/v1/environmentsListEnvironment management
Tools/v1/toolsCRUDMCP tool catalog
Webhooks/v1/tenants/{id}/webhooksCRUD + testEvent notifications
Service Accounts/v1/service-accountsCRUD + rotateM2M authentication
Health/healthGETPlatform health check
Metrics/metricsGETPrometheus metrics

Authentication​

All endpoints (except /health and /openapi.json) require a Bearer token:

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.

# Get a token
TOKEN=$(curl -s -X POST "${STOA_AUTH_URL}/realms/stoa/protocol/openid-connect/token" \
-d "grant_type=password" \
-d "client_id=control-plane-api" \
-d "username=admin" \
-d "password=demo" \
| jq -r '.access_token')

# Use the token
curl -s "${STOA_API_URL}/v1/apis" \
-H "Authorization: Bearer $TOKEN"

Common Response Codes​

CodeMeaningWhen
200SuccessGET, PUT, PATCH
201CreatedPOST (new resource)
204No ContentDELETE
400Bad RequestInvalid payload
401UnauthorizedMissing or invalid token
403ForbiddenInsufficient permissions
404Not FoundResource does not exist
409ConflictDuplicate resource
422UnprocessableValidation error (with details)
429Too Many RequestsRate limit exceeded

Error Format​

All errors follow a consistent format:

{
"detail": "API not found",
"status_code": 404,
"error_code": "API_NOT_FOUND"
}

Validation errors (422) include field-level details:

{
"detail": [
{
"loc": ["body", "name"],
"msg": "field required",
"type": "value_error.missing"
}
]
}

Pagination​

List endpoints support pagination:

curl "${STOA_API_URL}/v1/apis?skip=0&limit=20" \
-H "Authorization: Bearer $TOKEN"
ParameterDefaultMaxDescription
skip0--Number of items to skip
limit20100Number of items to return

Downloading the Specification​

# Download the full OpenAPI spec
curl -s "${STOA_API_URL}/openapi.json" | jq '.' > openapi.json

# Count endpoints
cat openapi.json | jq '.paths | length'

The specification can be imported into tools like Postman, Insomnia, or any OpenAPI-compatible client.

Contract Testing​

The OpenAPI spec is validated in CI using snapshot tests:

# Generate and compare (in control-plane-api/)
pytest tests/test_openapi_contract.py -v

Any endpoint change that modifies the spec requires updating the snapshot.