Relay docs

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 global (no team) or owned by the key's team.

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

QueryFilters byExample
?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} — resolves, in order: ?version=N → ?label=<label> → the production label → the latest version.

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"],
  "variables": ["company", "customer"],
  "prompt": "You are a support agent for {{company}}. Greet {{customer}}.",
  "config": { }
}

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 (same resolution rules via label/version) and substitute {{variables}}.

curl -X POST "http://localhost:5300/v1/prompts/support-greeting/compile" \
  -H "Authorization: Bearer $RELAY_API_KEY" -H "Content-Type: application/json" \
  -d '{ "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

  1. Author and label a prompt production in the panel.
  2. Your app fetches (or compiles) it at runtime by name.
  3. You send the compiled text/messages to /v1/chat/completions.

Or skip the round trip entirely and attach the prompt to an agent — the agent resolves and compiles it server-side.