API reference

Agent auth (auth.md)

Let AI agents register and call the API on behalf of a human user with short-lived, scoped, revocable tokens — no API key sharing. MyTabulon implements auth.md, the open Agent Registration Protocol, on top of standard OAuth. Turn it on per workspace under Agent auth in the dashboard.

https://api.mytabulon.com/v1

How it fits together

The /v1 API is the resource server. An agent discovers how to register, picks a method, obtains a service-signed identity_assertion, exchanges it for a short-lived access_token (mtb_agt_), and calls /v1 with that token. Tokens carry the same scopes as API keys and can be revoked instantly.

1. Discover

Discovery is two hops. A 401 from /v1 returns a WWW-Authenticate header pointing at the Protected Resource Metadata, which points at the Authorization Server metadata and its agent_auth block. The published auth.md file is the human + agent readable guide.

discovery
# Human + agent readable guide
GET https://api.mytabulon.com/auth.md

# Protected resource metadata (resource, scopes, auth servers)
GET https://api.mytabulon.com/v1/.well-known/oauth-protected-resource

# Authorization server metadata (endpoints + agent_auth block)
GET https://api.mytabulon.com/.well-known/oauth-authorization-server

2. Register

Three methods. service_auth (you have the user's email) and anonymous (claim later) both run a claim ceremony; identity_assertion verifies an ID-JAG from a trusted provider. Each returns a claim_token and/or a service-signed identity_assertion.

register (email claim)
curl -X POST https://api.mytabulon.com/agent/identity \
  -H "Content-Type: application/json" \
  -d '{ "type": "service_auth", "login_hint": "user@example.com" }'

# -> { "registration_id", "claim_token", "post_claim_scopes",
#      "claim": { "user_code": "123456", "verification_uri": "...", "interval": 5 } }

3. Claim ceremony

Surface the verification_uri and 6-digit user_code to the user. They open the link, sign in to MyTabulon, and confirm the code on a secure page. Poll the token endpoint with the claim grant until they finish.

poll for completion
curl -X POST https://api.mytabulon.com/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=urn:workos:agent-auth:grant-type:claim&claim_token=clm_..."

# authorization_pending -> keep polling (honor interval)
# success -> { "access_token", "token_type": "Bearer", "expires_in", "scope",
#              "identity_assertion" }

4. Exchange the assertion

Once you hold an identity_assertion (returned directly for anonymous, or after a claim), exchange it for an access_token with the RFC 7523 JWT-bearer grant. Re-run this whenever the access_token expires — there is no refresh token.

jwt-bearer exchange
curl -X POST https://api.mytabulon.com/oauth2/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=<identity_assertion>"

# -> { "access_token": "mtb_agt_...", "token_type": "Bearer", "expires_in": 3600, "scope": "..." }

5. Call the API

Send the agent access_token exactly like an API key. It is scoped to the same catalog (clients.read, invoices.write, ai.responses, …) and bound to the user's workspace. A missing scope returns 403 insufficient_scope.

GET/workspacegranted agent scopes

Call any /v1 endpoint with the agent token in the Authorization header.

request
Authorization: Bearer mtb_agt_...

Revocation

Revoke a single token with the standard RFC 7009 endpoint. Workspace owners can also revoke any registration or token instantly from the Agent auth dashboard, which kills all of that agent's tokens at once.

revoke a token
curl -X POST https://api.mytabulon.com/oauth2/revoke \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "token=mtb_agt_..."

Plan limits

Free is opt-in; Plus, Pro, and Max are on by default. Plans cap active registrations, concurrent tokens, token lifetime, and trusted ID-JAG providers. Agent tokens reuse the same rate limits and metering as API keys — no separate billing.