Prompts API
The prompt library is a data plane for your apps: fetch a versioned prompt by name, or compile it with variable values. Prompts are visible to a key when they are enabled and either global (no workspace) or owned by the key's workspace. No scope is needed beyond a valid key.
See Prompt library for authoring concepts.
#List prompts
GET /v1/prompts
{ "object": "list", "data": [
{ "name": "support-greeting", "description": "…", "tags": ["support"], "latest_version": 3, "labels": ["production"] }
] }
#Filtering
| Query | Filters by | Example |
|---|---|---|
?tag= | Prompt tags — free-form metadata on the prompt itself | ?tag=support |
?label= | Version labels — which revision is which | ?label=production |
Tags and labels are different things, and the distinction is worth holding on to: a tag describes what a prompt is for and lives on the prompt (support, billing, internal); a label marks which revision to use and lives on a version (production, staging). production and latest are labels, not tags — so ?label=latest, not ?tag=latest.
Both accept a comma-separated list, and both mean all of these, not any of these — a filter narrows, so naming two values returns fewer results:
# Prompts tagged BOTH support and billing
curl "http://localhost:5300/v1/prompts?tag=support,billing" -H "Authorization: Bearer $RELAY_API_KEY"
# Prompts that have a production version
curl "http://localhost:5300/v1/prompts?label=production" -H "Authorization: Bearer $RELAY_API_KEY"
# Combine: support prompts that are live
curl "http://localhost:5300/v1/prompts?tag=support&label=production" -H "Authorization: Bearer $RELAY_API_KEY"
Multiple labels must sit on the same version — ?label=production,canary finds prompts with one version carrying both, not prompts that happen to have each label somewhere.
?label=latest means "has at least one version". That mirrors the fetch endpoint, where latest resolves to the highest version number rather than to a stored label — so a prompt listed under ?label=latest is always fetchable with ?label=latest, and one with no versions appears under neither.
Omit both parameters to list everything, as before.
#Fetch a version
GET /v1/prompts/{name} — with ?version=N or ?label=<label> that exact version is returned, and 404 prompt_version_not_found if it does not exist; there is no fall-through from a miss. With neither, Relay uses the version labelled production, falling back to the latest (highest-numbered) version. A prompt with no versions at all is a 404 too.
A prompt in a folder is fetched by its full name with the / URL-encoded: support/greeting is /v1/prompts/support%2Fgreeting. The same applies to /compile.
curl "http://localhost:5300/v1/prompts/support-greeting?label=production" \
-H "Authorization: Bearer $RELAY_API_KEY"
{
"name": "support-greeting",
"version": 3,
"type": "text",
"labels": ["production"],
"tags": ["support"],
"variables": ["company", "customer"],
"prompt": "You are a support agent for {{company}}. Greet {{customer}}.",
"config": { },
"commit_message": "Shorter greeting",
"updated_at": "2026-09-27T10:00:00Z"
}
For a chat-type prompt the payload has messages (an array of { role, content }) instead of prompt.
#Compile with variables
POST /v1/prompts/{name}/compile — fetch a version and substitute {{variables}}. The same resolution rules apply, but label and version travel in the JSON body alongside variables, not in the query string.
curl -X POST "http://localhost:5300/v1/prompts/support-greeting/compile" \
-H "Authorization: Bearer $RELAY_API_KEY" -H "Content-Type: application/json" \
-d '{ "label": "production", "variables": { "company": "Spinneys", "customer": "Sara" } }'
{
"name": "support-greeting",
"version": 3,
"type": "text",
"prompt": "You are a support agent for Spinneys. Greet Sara.",
"missing_variables": [],
"config": { }
}
missing_variables lists any placeholder that wasn't supplied — unprovided placeholders are left intact so you can see what's missing.
#Typical flow
- Author and label a prompt
productionin the panel. - Your app fetches (or compiles) it at runtime by name.
- You send the compiled text/messages to
/v1/chat/completions, withX-Relay-Prompt: support-greeting@3so the generation is counted on that version's Metrics tab (see Observability).
Or skip the round trip entirely and attach the prompt to an agent — the agent resolves and compiles it server-side, and the attribution is automatic.