SMAO API Documentation

Authentication

OAuth and organization API keys for MCP, Public API keys, and SMAO-issued Distributor API keys.

The two REST APIs use independent key types — a Public API key never works against Distributor API v1 and vice versa. Both are sent the same way: Authorization: Bearer <key>. Newly issued Public API keys are ~43-character base64url strings with no prefix; legacy smao_-prefixed Public API keys remain valid.

MCP Connector — OAuth or organization API key

For an interactive AI client, add https://api2.smao.ai/mcp as a remote MCP connector and use OAuth. The client discovers SMAO's authorization server, opens the browser login and consent flow, and binds the connection to the organization you select. Disconnect and reconnect to switch organizations.

Clients that support custom HTTP headers can instead send a Public API organization key as Authorization: Bearer <key>. Both methods apply the current organization role and plan entitlements on every request. See the MCP setup and access rules for client examples, scopes, and revocation.

Public API — organization API keys

Create keys yourself in the dashboard under Settings → API Keys → New key. Each key gets a Role that scopes what it can do — pick the narrowest role that covers your use case. Keys belong to one organization; every request is scoped to that organization's data.

curl https://api2.smao.ai/api/v1/ping \
  -H "Authorization: Bearer YOUR_API_KEY"

A missing or invalid key returns 401:

{ "error": { "code": "unauthorized", "message": "Missing API key" } }

A valid key whose role lacks permission for the endpoint returns 403 with error.code: "forbidden". See Errors for the full envelope.

The raw key is shown once, at creation. Store it in a secret manager — it cannot be retrieved later.

Key handling:

  • One key per integration. Separate keys let you revoke one consumer without breaking the others.
  • Rotate by overlap. Create a new key, deploy it, then delete the old one. Both work in parallel in between, so rotation needs no downtime.
  • Revoke immediately on leak. Deleting a key invalidates it at once.

Distributor API v1 — distributor keys

Distributor keys are issued by SMAO during onboarding — there is no self-service issuance. The raw key is shown exactly once at creation; the server stores a SHA-256 hash plus the first 12 characters as an identification prefix — never the full key.

Every v1 key carries these fixed permissions:

  • organizations:read
  • organizations:write
  • usage:read
  • partners:read
  • partners:write

Permission sets are immutable after issuance. Keys expire, by default after 365 days. Request a replacement key from SMAO before expiry and switch over — old and new keys work in parallel until the old one expires or is revoked, so rotation needs no downtime.

curl https://api2.smao.ai/api/distributor/v1/partners \
  -H "Authorization: Bearer YOUR_DISTRIBUTOR_KEY"

Auth failures return 401 in the Distributor error envelope, with an errorCode telling you why:

{ "status": "error", "errorCode": "INVALID_API_KEY", "message": "Invalid or revoked API key." }
errorCodeMeaning
MISSING_API_KEYNo Authorization: Bearer header, or an empty key.
INVALID_API_KEYKey unknown or revoked.
API_KEY_EXPIREDKey past its expiry date — request a replacement from SMAO.
API_VERSION_NOT_ALLOWEDKey metadata does not authorize Distributor API v1.

Only GET /health is public. Every other Distributor endpoint requires a valid v1 key and its documented permission. Continue with the Distributor v1 quickstart.

REST API comparison

Public APIDistributor API v1
IssuanceSelf-service: dashboard Settings → API KeysBy SMAO during onboarding
ScopingOne organizationAll organizations managed by the distributor
PermissionsRole-based, chosen per keyFive fixed v1 scopes
ExpiryNone365 days by default
RotationCreate new key, deploy, delete oldRequest replacement from SMAO; parallel until old key expires or is revoked
Rate limitsPer key defaults: read 1000/min, write 200/min, POST /calls 60/hourPer key: 60 req/min default (configurable per key)
401 shape{ "error": { "code": "unauthorized", ... } }{ "status": "error", "errorCode": "...", "message": "..." }

For the Public API, matched operations that pass authentication and the feature gate return X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset after the limiter succeeds. Auth failures, feature-gate failures, unmatched routes, and limiter-storage failures do not carry the full header set. Details in Errors.

On this page