API examples
Every public endpoint, with real requests and responses captured from Model Gateway’s own code. The full endpoint list is in the generated API reference. Authentication says what a caller needs.
Base URL: https://gqbzygqa4dd3t54xnb2fg5wcou0pitmm.lambda-url.us-east-1.on.aws.
Bodies are JSON (Content-Type: application/json); times are RFC 3339 in
UTC. $AUTH below stands for:
AUTH=(-H "Authorization: Bearer $CHIRPAUTH_MACHINE_TOKEN"
-H "x-user-id: u_8Q3K2M11XZ"
-H "x-granite-grant: b6ddef35-fe77-43be-a871-bb80d528906a")
The examples act for a person whose Granite id is gr_sub_alice.
Provider credentials
Add a credential
POST /v1/model-gateway/provider-credentials
curl https://gqbzygqa4dd3t54xnb2fg5wcou0pitmm.lambda-url.us-east-1.on.aws/v1/model-gateway/provider-credentials \
"${AUTH[@]}" -H "Content-Type: application/json" \
-d '{"provider": "anthropic", "label": "My Anthropic key", "api_key": "sk-ant-example-0000-wxyz"}'
| Field | Required | Rules |
|---|---|---|
provider | Yes | 1–128 characters, no control characters, not fake. A built-in provider or one of the person’s custom adapters; see Concepts. |
api_key | Yes | 8–4096 characters, no control characters. |
label | No | 1–128 characters. Defaults to provider. |
Model Gateway does not check the key with the provider. A credential for a
custom adapter also has destination (the adapter’s dialect, base_url
and auth_style, copied now); a built-in provider’s has none.
Response, 201 Created:
{
"credential": {
"created_at": "2026-11-05T20:41:21.618254305Z",
"id": "c521b434-5993-4eca-83c9-5b15d20523d6",
"key_hint": "...wxyz",
"label": "My Anthropic key",
"owner_uid": "gr_sub_alice",
"provider": "anthropic",
"updated_at": "2026-11-05T20:41:21.618254305Z"
}
}
List credentials
GET /v1/model-gateway/provider-credentials returns the person’s
credentials in the same shape, without the credential wrapper:
[
{
"created_at": "2026-11-05T20:41:21.618254305Z",
"id": "c521b434-5993-4eca-83c9-5b15d20523d6",
"key_hint": "...wxyz",
"label": "My Anthropic key",
"owner_uid": "gr_sub_alice",
"provider": "anthropic",
"updated_at": "2026-11-05T20:41:21.618254305Z"
}
]
Delete a credential
DELETE /v1/model-gateway/provider-credentials/{credential_id} deletes the
credential and its stored key; spend grants that name it can no longer be
used.
Returns 204 No Content, or 404 if there is no such credential.
Spend grants
Spend grants are Granite grants, created and revoked in Granite; Model Gateway has no endpoints for them. See Concepts.
Usage
GET /v1/model-gateway/spend-usage returns the person’s usage records, oldest
first. Each has:
| Field | Meaning |
|---|---|
id | The record’s id |
owner_uid | The person |
grant_id | The Granite spend grant the call was counted against |
authorization_id | Model Gateway’s id for the call’s approval against the grant |
resource | model:{provider}:{model} |
units | Units counted. A model call Model Gateway makes counts one. |
created_at | When it was recorded |
A person with no usage gets [].
Custom adapters
Create an adapter
POST /v1/model-gateway/custom-adapters
curl https://gqbzygqa4dd3t54xnb2fg5wcou0pitmm.lambda-url.us-east-1.on.aws/v1/model-gateway/custom-adapters \
"${AUTH[@]}" -H "Content-Type: application/json" \
-d '{
"name": "my-llm",
"dialect": "openai_chat",
"base_url": "https://8.8.8.8/v1",
"auth_style": "bearer",
"models": ["my-model-1"]
}'
| Field | Required | Rules |
|---|---|---|
name | Yes | 1–128 characters: ASCII letters, digits, -, _, .. Unique for the person; not a built-in provider name. |
dialect | Yes | openai_chat, anthropic or gemini |
base_url | Yes | https://, resolving only to public addresses. A trailing / is removed. |
auth_style | Yes | bearer, x_api_key or goog_key: the header that carries the key |
models | No | A list of model names. Stored and returned; not checked against calls. |
Response, 201 Created:
{
"auth_style": "bearer",
"base_url": "https://8.8.8.8/v1",
"created_at": "2026-11-05T20:41:21.880385766Z",
"dialect": "openai_chat",
"models": [
"my-model-1"
],
"name": "my-llm",
"owner_uid": "gr_sub_alice",
"updated_at": "2026-11-05T20:41:21.880385766Z"
}
Refusals look like this:
{"error": "adapter name cannot shadow a built-in preset"}
{"error": "base_url must use https"}
{"error": "base_url resolves to a disallowed (private, loopback, link-local, or metadata) address"}
A second adapter with the same name is 409.
List adapters
GET /v1/model-gateway/custom-adapters returns the person’s adapters without
auth_style:
[
{
"base_url": "https://8.8.8.8/v1",
"created_at": "2026-11-05T20:41:21.880385766Z",
"dialect": "openai_chat",
"models": [
"my-model-1"
],
"name": "my-llm",
"owner_uid": "gr_sub_alice",
"updated_at": "2026-11-05T20:41:21.880385766Z"
}
]
Delete an adapter
DELETE /v1/model-gateway/custom-adapters/{name} returns 204 No Content,
or 404 (custom adapter not found).
Public endpoints
curl -fsS https://gqbzygqa4dd3t54xnb2fg5wcou0pitmm.lambda-url.us-east-1.on.aws/health