API Reference

All endpoints are served by the broker at http://localhost:3001 by default. Request and response bodies are JSON.

Endpoints

Method Endpoint Description
POST /grant-requests Create a new grant request
POST /grants/:id/approve Approve a pending grant
POST /grants/:id/deny Deny a pending grant
GET /grants List all grants
GET /grants/:id Get a single grant
POST /grants/:id/revoke Revoke a grant and invalidate its tokens
POST /tokens Issue a delegated JWT for an approved grant
GET /tokens/:token/inspect Inspect a token’s validity
POST /proxy/chat Proxy a chat request to the upstream provider
GET /health Health check

Grant requests

POST /grant-requests

Create a new grant request. This is how a third-party app asks for delegated access.

Request body:

{
  "appName": "My AI App",
  "appUrl": "https://myapp.example.com",
  "scope": {
    "provider": "openai",
    "models": ["gpt-4o", "gpt-4o-mini"],
    "capabilities": ["chat"],
    "maxBudgetCents": 500,
    "maxRequests": 100,
    "rateLimit": 10
  },
  "reason": "Chat assistant feature"
}

Scope fields:

Field Type Required Description
provider string Yes "openai", "anthropic", or "google"
models string[] Yes Allowed model IDs
capabilities string[] Yes "chat", "embeddings", "images", "audio", "code"
maxBudgetCents number No Spending cap in cents
maxRequests number No Maximum number of proxied requests
rateLimit number No Requests per minute (defined but not yet enforced)

Response: 201 Created

{
  "grantRequest": { "id": "...", "appName": "...", ... },
  "grant": { "id": "...", "status": "pending", ... }
}

Grant management

POST /grants/:id/approve

Approve a pending grant. Optionally set a custom expiration.

Request body (optional):

{ "expiresInSeconds": 7200 }

Default expiration is 3600 seconds (1 hour).

Response: 200 OK with the updated grant object.

POST /grants/:id/deny

Deny a pending grant.

Response: 200 OK with the updated grant object.

POST /grants/:id/revoke

Revoke an approved grant. All tokens issued for this grant are immediately invalidated.

Response: 200 OK with the updated grant object.

GET /grants

List all grants, sorted by creation date (newest first).

Response: 200 OK with an array of grant objects.

GET /grants/:id

Get a single grant by ID.

Response: 200 OK with the grant object, or 404 if not found.


Tokens

POST /tokens

Issue a signed JWT delegated token for an approved grant.

Request body:

{ "grantId": "..." }

Response: 201 Created

{
  "token": "eyJhbGciOiJIUzI1NiJ9...",
  "grantId": "...",
  "issuedAt": "2026-03-15T12:00:00.000Z",
  "expiresAt": "2026-03-15T13:00:00.000Z"
}

The token field is a signed JWT. It never contains the raw provider API key.

GET /tokens/:token/inspect

Inspect a token’s validity and associated grant metadata. Useful for debugging.

Response: 200 OK

{
  "valid": true,
  "grant": {
    "id": "...",
    "appName": "...",
    "scope": { ... },
    "status": "approved",
    "usageCount": 5
  }
}

Proxy

POST /proxy/chat

Proxy a chat completion request to the upstream AI provider. The broker validates the token, checks scopes and usage caps, injects the real API key, and forwards the request.

Headers:

Authorization: Bearer <delegated-token>
Content-Type: application/json

Request body:

{
  "model": "gpt-4o-mini",
  "messages": [
    { "role": "user", "content": "Hello!" }
  ]
}

Response: The upstream provider’s response, proxied through.

Error responses:

Status Meaning
400 Invalid request body (missing model or messages)
401 Missing, malformed, expired, or revoked token
429 Usage cap exceeded
502 Upstream provider error

Example with curl:

curl -X POST http://localhost:3001/proxy/chat \
  -H "Authorization: Bearer <delegated-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Health

GET /health

Returns broker status.

Response: 200 OK

{ "status": "ok", "service": "aipassport-broker" }

Back to top

AIPassport is an exploratory reference implementation. Not a finalized standard. MIT License.

This site uses Just the Docs, a documentation theme for Jekyll.