Models
List the models a key may use, with their prices, and read the public catalogue without a key.
Use this page to see which models your key can route to and what they cost. You can also read the public catalogue without a key.
List the models your key can use
GET /v1/models lists what this key may route to, in the OpenAI list shape.
curl https://api.massrelay.ai/v1/models -H "Authorization: Bearer $RELAY_KEY"Each entry carries a massrelay object with these fields:
- provider — the provider that serves the model.
- custody — whose key pays the provider for this route (see Bring your own key).
- family — the model family.
- prices — per million tokens, where a rate is known.
- reasoning options — where the catalogue states them.
A model the workspace brought itself says ownedBy: workspace. Aliases are listed after the models and are marked alias; an alias is a name that routes, never a real model.
not_ported answer rather than a guess.Read the public catalogue
GET /public/models and GET /public/models/{provider}/{model} need no credential. They show the catalogue with the price per million input and output tokens and, on the detail page, latency and uptime. A figure backed by too few calls is null, never a small number. Partner models appear with partner: true.
curl https://api.massrelay.ai/public/modelsA catalogue generated from the provider feeds is not available yet; today the catalogue is the one the router ships.
API reference
GET /v1/models
Authentication relay key (bearer)
Example request
curl https://api.massrelay.ai/v1/models \
-H "Authorization: Bearer $RELAY_KEY"import os, requests
r = requests.get(
"https://api.massrelay.ai/v1/models",
headers={"Authorization": f"Bearer {os.environ['RELAY_KEY']}"},
)
r.raise_for_status()
print(r.json())const r = await fetch("https://api.massrelay.ai/v1/models", {
method: "GET",
headers: { Authorization: `Bearer ${process.env.RELAY_KEY}` },
});
if (!r.ok) throw new Error(`${r.status} ${await r.text()}`);
console.log(await r.json());Response
| Field | Type | Description |
|---|---|---|
object required | string | The kind of object returned, for example chat.completion. Always "list". |
data required | array of object | The list of items returned. |
data[].id required | string | A model id, or an alias name (after the models). |
data[].object required | string | The kind of object returned, for example chat.completion. Always "model". |
data[].massrelay | object | |
data[].massrelay.provider | string | |
data[].massrelay.custody | string | |
data[].massrelay.family | string | |
data[].massrelay.reasoning_options | object | |
data[].massrelay.price_bands | array | |
data[].massrelay.ownedBy | string | Present only for the workspace's own model. Always "workspace". |
data[].massrelay.inputUsdPerM | number | |
data[].massrelay.outputUsdPerM | number | |
data[].massrelay.alias | boolean | Present on an alias entry. Always true. |
data[].massrelay.startTier | object | |
data[].massrelay.preferOwnModels | boolean |
{
"object": "list",
"data": [
{
"id": "<id>",
"object": "model",
"massrelay": {
"provider": "<provider>",
"custody": "<custody>",
"family": "<family>",
"reasoning_options": "<reasoning_options>",
"price_bands": [],
"ownedBy": "workspace",
"inputUsdPerM": 0,
"outputUsdPerM": 0,
"alias": true,
"startTier": "<startTier>",
"preferOwnModels": false
}
}
]
}Common errors
401invalid_api_key403insufficient_scope429over the request rate; read Retry-After
Every error has the same JSON shape; see Errors and Limits.
Full schema (JSON)
Response schema
{
"description": "Served for an L1 key; any other key layer answers 501 not_ported. The massrelay keys listed are those the handler inserts; a key appears only when its source row exists.",
"type": "object",
"required": [
"object",
"data"
],
"properties": {
"object": {
"const": "list"
},
"data": {
"type": "array",
"items": {
"type": "object",
"required": [
"id",
"object"
],
"properties": {
"id": {
"type": "string",
"description": "A model id, or an alias name (after the models)."
},
"object": {
"const": "model"
},
"massrelay": {
"type": "object",
"additionalProperties": true,
"properties": {
"provider": {
"type": "string"
},
"custody": {
"type": "string"
},
"family": {
"type": "string"
},
"reasoning_options": {},
"price_bands": {
"type": "array"
},
"ownedBy": {
"const": "workspace",
"description": "Present only for the workspace's own model."
},
"inputUsdPerM": {
"type": "number"
},
"outputUsdPerM": {
"type": "number"
},
"alias": {
"const": true,
"description": "Present on an alias entry."
},
"startTier": {},
"preferOwnModels": {
"type": "boolean"
}
}
}
}
}
}
}
}GET /public/models
Authentication public, no credential
Response
| Field | Type | Description |
|---|---|---|
floor required | integer | |
models required | array of object | |
models[].provider required | string | |
models[].model required | string | The model id. In a request it is optional: without it the key's routing chooses. |
models[].family | string or null | |
models[].contextWindow | integer or null | |
models[].priceInputPerMillionUsd | number or null | |
models[].priceOutputPerMillionUsd | number or null | |
models[].partner required | boolean |
{
"floor": 0,
"models": [
{
"provider": "<provider>",
"model": "provider/model-id",
"family": "<family>",
"contextWindow": "<contextWindow>",
"priceInputPerMillionUsd": "<priceInputPerMillionUsd>",
"priceOutputPerMillionUsd": "<priceOutputPerMillionUsd>",
"partner": false
}
]
}Full schema (JSON)
Response schema
{
"description": "No credential. 404 when the public pages are switched off. `floor` is the k-floor: a figure backed by fewer calls is null, never a small number.",
"type": "object",
"required": [
"floor",
"models"
],
"properties": {
"floor": {
"type": "integer"
},
"models": {
"type": "array",
"items": {
"type": "object",
"required": [
"provider",
"model",
"partner"
],
"properties": {
"provider": {
"type": "string"
},
"model": {
"type": "string"
},
"family": {
"type": [
"string",
"null"
]
},
"contextWindow": {
"type": [
"integer",
"null"
]
},
"priceInputPerMillionUsd": {
"type": [
"number",
"null"
]
},
"priceOutputPerMillionUsd": {
"type": [
"number",
"null"
]
},
"partner": {
"type": "boolean"
}
}
}
}
}
}GET /public/models/{provider}/{model}
Authentication public, no credential
Path parameters
provider required | string | |
model required | string |
Response
| Field | Type | Description |
|---|---|---|
provider required | string | |
model required | string | The model id. In a request it is optional: without it the key's routing chooses. |
family | string or null | |
contextWindow | integer or null | |
priceInputPerMillionUsd | number or null | |
priceOutputPerMillionUsd | number or null | |
partner required | boolean | |
latency | object | |
latency.p50Ms | number or null | |
latency.p95Ms | number or null | |
latency.window | string | Always "24h". |
uptime | object | |
uptime.5m | null | |
uptime.30m | null | |
uptime.1d | number or null | |
floor | integer |
{
"provider": "<provider>",
"model": "provider/model-id",
"family": "<family>",
"contextWindow": "<contextWindow>",
"priceInputPerMillionUsd": "<priceInputPerMillionUsd>",
"priceOutputPerMillionUsd": "<priceOutputPerMillionUsd>",
"partner": false,
"latency": {
"p50Ms": "<p50Ms>",
"p95Ms": "<p95Ms>",
"window": "24h"
},
"uptime": {
"5m": null,
"30m": null,
"1d": "<1d>"
},
"floor": 0
}Full schema (JSON)
Response schema
{
"description": "404 {error:not_found} for a name the catalogue and the partner listing do not know. Latency and uptime are null below the k-floor.",
"type": "object",
"required": [
"provider",
"model",
"partner"
],
"properties": {
"provider": {
"type": "string"
},
"model": {
"type": "string"
},
"family": {
"type": [
"string",
"null"
]
},
"contextWindow": {
"type": [
"integer",
"null"
]
},
"priceInputPerMillionUsd": {
"type": [
"number",
"null"
]
},
"priceOutputPerMillionUsd": {
"type": [
"number",
"null"
]
},
"partner": {
"type": "boolean"
},
"latency": {
"type": "object",
"properties": {
"p50Ms": {
"type": [
"number",
"null"
]
},
"p95Ms": {
"type": [
"number",
"null"
]
},
"window": {
"const": "24h"
}
}
},
"uptime": {
"type": "object",
"properties": {
"5m": {
"type": "null"
},
"30m": {
"type": "null"
},
"1d": {
"type": [
"number",
"null"
]
}
}
},
"floor": {
"type": "integer"
}
}
}