Prompts
Create, manage, version, and render prompts. Prompts have three types: system-prompt, user-prompt, and template. For skills, see the Skills API. Every change to a prompt's content creates a new version.
All endpoints require authentication via X-API-Key header and the appropriate scope.
Prompt Object
{
"_id": "prompt_abc123",
"name": "Customer Support Agent",
"description": "System prompt for customer support interactions",
"type": "system-prompt",
"content": "You are a helpful customer support agent for {{company}}. Help customers with {{topic}} questions.",
"variables": [
{
"name": "company",
"description": "Company name",
"required": true
},
{
"name": "topic",
"description": "Support topic area",
"defaultValue": "general",
"required": false
}
],
"tags": ["support", "customer-facing"],
"linkedIds": [],
"currentVersion": 3,
"ownerId": "user_456",
"ownerName": "Jane Smith",
"organizationId": "org_789",
"isPublic": false,
"sharedWith": ["user_012"],
"source": "user",
"usageCount": 12,
"createdAt": "2026-01-15T10:00:00Z",
"updatedAt": "2026-02-19T14:30:00Z"
}
Version Object
{
"_id": "ver_xyz789",
"promptId": "prompt_abc123",
"versionNumber": 3,
"parentVersionNumber": 2,
"contentPatch": "@@ -1 +1 @@\n-You are a customer support agent...\n+You are a helpful customer support agent...\n",
"sideFields": {
"variables": [
{
"name": "company",
"description": "Company name",
"defaultValue": "Acme Corp",
"required": true
}
]
},
"changeNote": "Updated tone to be more friendly",
"createdAt": "2026-02-19T14:30:00Z",
"createdBy": "user_456",
"createdByName": "Jane Smith"
}
A version stores its content as contentPatch, a unified diff against the previous version's content (version 1 is a diff from empty text). sideFields.variables holds the variable definitions at that version.
Variables
Variables are the {{name}} placeholders in a prompt's content, detected whenever the content is saved. A variable you send in variables keeps its description and defaultValue; required is set for you: a variable with no default value is required, and rendering refuses without a value for it.
GET /api/v1/library/prompts/search
Search the prompts you may use, by meaning and by words, best match first. Two rankings are fused (Reciprocal Rank Fusion): how close each prompt's meaning is to the query (an embedding of its name, description, tags and content), and how well its words match (full-text search over the same fields). A prompt whose name is the query ranks first; a description of what a prompt does finds it too.
Scope: prompts:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search query text |
type | string | No | Filter by type: system-prompt, user-prompt, template |
tags | string | No | Comma-separated tags; only prompts with every one |
limit | integer | No | Max results, 1-100 (default: 20) |
popularity | number | No | Weight of each prompt's usageCount in the meaning ranking, 0-1 (default: 0 = off) |
mmr | string | No | Set to "true" to re-rank the meaning ranking for diversity (maximal marginal relevance) |
mmr_lambda | number | No | MMR lambda, 0-1 (default: 0.7) |
Response 200 OK
Each result is the prompt plus score, its fused rank score (higher is a better match; it orders the results and is not a percentage).
{
"data": [
{
"_id": "prompt_abc123",
"name": "Customer Support Agent",
"type": "system-prompt",
"description": "System prompt for customer support",
"content": "You are a helpful customer support agent for {{company}}.",
"tags": ["support"],
"currentVersion": 3,
"ownerName": "Jane Smith",
"isPublic": false,
"updatedAt": "2026-02-19T14:30:00Z",
"score": 0.0328
}
],
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/library/prompts
List all prompts accessible to the authenticated user. Includes owned and shared prompts, and prompts open to all users.
Scope: prompts:read
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | No | Items per page (default: 20, max: 100) |
cursor | string | No | meta.nextCursor of the previous page; omit for the first page |
type | string | No | Filter by type: system-prompt, user-prompt, template |
q | string | No | Search by name (case-insensitive) |
tags | string | No | Comma-separated tag filter |
Response 200 OK
{
"data": [
{
"_id": "prompt_abc123",
"name": "Customer Support Agent",
"type": "system-prompt",
"description": "System prompt for customer support",
"tags": ["support"],
"currentVersion": 3,
"ownerName": "Jane Smith",
"isPublic": false,
"updatedAt": "2026-02-19T14:30:00Z"
}
],
"meta": {
"total": 42,
"limit": 20,
"nextCursor": "eyJvIjo1MH0",
"requestId": "req_abc123"
}
}
Prompts are returned most recently updated first.
POST /api/v1/library/prompts
Create a new prompt. Automatically creates version 1. Variables are auto-detected from {{variableName}} patterns in content.
Scope: prompts:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Prompt name (max 200 characters) |
type | string | No | One of: system-prompt, user-prompt, template (default and any other value: user-prompt) |
content | string | Yes | Prompt content (supports {{variable}} syntax) |
description | string | No | Optional description |
tags | string[] | No | Array of tags |
variables | object[] | No | Variable definitions with name, description, defaultValue (see Variables) |
Request
{
"name": "Data Extraction Template",
"type": "template",
"content": "Extract the following entities from the text:\n- {{entity_types}}\n\nText: {{input_text}}\n\nReturn as JSON.",
"description": "General-purpose entity extraction prompt",
"tags": ["extraction", "nlp"],
"variables": [
{
"name": "entity_types",
"description": "Comma-separated list of entity types to extract",
"defaultValue": "person, organization, location"
},
{
"name": "input_text",
"description": "The text to extract entities from"
}
]
}
Response 201 Created
{
"data": { "promptId": "prompt_def456" },
"meta": { "requestId": "req_abc123" }
}
GET /api/v1/library/prompts/:id
Get a specific prompt by ID. Requires read access (owner, shared, or open to all users).
Scope: prompts:read
Response 200 OK
Returns the full Prompt Object.
PATCH /api/v1/library/prompts/:id
Update a prompt. When content changes, a new version is created and currentVersion is incremented; the other fields are saved on the current version.
Scope: prompts:write
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Updated name |
description | string | No | Updated description |
content | string | No | Updated content (triggers new version) |
tags | string[] | No | Updated tags |
variables | object[] | No | Updated variable descriptions and defaults (see Variables) |
changeNote | string | No | Description of changes for the version history |
Request
{
"content": "You are a friendly customer support agent for {{company}}. Always greet the customer warmly.",
"changeNote": "Made tone more friendly, added greeting instruction"
}
Response 200 OK
The updated prompt; currentVersion is new when the content changed.
version is the new version number; it is left out when the update created no new version.
DELETE /api/v1/library/prompts/:id
Delete a prompt with all its versions and saved comparisons. This action cannot be undone.
Scope: prompts:write
Response 204 No Content
GET /api/v1/library/prompts/:id/versions
List all versions of a prompt, newest first. Each entry is a Version Object plus content, the prompt's full content at that version (rebuilt from the diff chain); the example shows a subset of its fields.
Scope: prompts:read
Response 200 OK
{
"data": [
{
"_id": "ver_2",
"versionNumber": 2,
"content": "You are a friendly customer support agent for {{company}}. Always greet the customer warmly.",
"changeNote": "Made tone more friendly",
"createdBy": "user_456",
"createdByName": "Jane Smith",
"createdAt": "2026-02-19T14:30:00Z"
},
{
"_id": "ver_1",
"versionNumber": 1,
"content": "You are a customer support agent for {{company}}.",
"changeNote": "Initial version",
"createdBy": "user_456",
"createdByName": "Jane Smith",
"createdAt": "2026-01-15T10:00:00Z"
}
],
"meta": { "requestId": "req_abc123" }
}
POST /api/v1/library/prompts/:promptId/versions/:version/restore
Restore a previous version (:version is its version number). This creates a new version with the content (and the variable defaults) of that version, preserving the full history.
Scope: prompts:write
Response 200 OK
The prompt, as GET /library/prompts/:id shows it: its content is the restored version's, saved as a new version.
POST /api/v1/library/prompts/:id/duplicate
Create a copy of an existing prompt. The new prompt has:
- The authenticated user as owner
- Name suffixed with "(Copy)"
- Version reset to 1
- All content and variables preserved, and its tags (except
platform) - It is your own prompt (
sourceuser), also when it copies a platform prompt
Scope: prompts:write
Response 201 Created
{
"data": { "promptId": "prompt_new789" },
"meta": { "requestId": "req_abc123" }
}
POST /api/v1/library/prompts/:id/usage-events
Record a usage event for a prompt. Increments the prompt's usageCount, which feeds the popularity weighting in GET /api/v1/library/prompts/search.
Scope: prompts:read
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Prompt ID |
Response 201 Created: { "usageCount": 12 }, how many times the prompt has been used.
POST /api/v1/library/prompts/:id/render
Render a prompt by substituting variable values into the content. A variable you leave out takes its default value; one with no default is required, and leaving it out is refused with 400 validation-error naming it (for example Missing a value for: ticket). Returns the rendered text without modifying the prompt.
Scope: prompts:read
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
variables | object | Yes | Key-value pairs for variable substitution |
Request
{
"variables": {
"company": "Acme Corp",
"topic": "billing"
}
}
Response 200 OK
{
"data": {
"content": "You are a helpful customer support agent for Acme Corp. Help customers with billing questions.",
"promptId": "prompt_abc123",
"name": "Customer Support Agent"
},
"meta": { "requestId": "req_abc123" }
}
Access Control
Prompts follow the platform's multi-tenant access model:
| Scenario | Access |
|---|---|
| Owner | Full read/write/delete |
| User it is shared with | Read and edit (Full Access) |
| Prompt open to all users (same org) | Read only |
Platform prompt (source platform) | Read only; duplicate it to make your own |
| Different organization | No access |
API key with prompts:read | Read access to owned and shared prompts and those open to all users |
API key with prompts:write | Create, and change the prompts you may edit |
Error Codes
| Code | Status | Description |
|---|---|---|
unauthorized | 401 | Missing or invalid authentication |
not-found | 404 | Prompt not found or no access, or (restore) no such version |
forbidden | 403 | Insufficient permissions (e.g., trying to edit someone else's prompt) |
validation-error | 400 | Invalid request (missing name or content, source platform, a render missing a required variable, etc.) |