Context RepoContext Repo Docs
API Reference

Endpoints

Complete REST endpoint reference for prompts, documents, collections, search, progressive disclosure, and reasoning.

Unless an endpoint is explicitly marked public, include an Authorization header with every request. See Authentication for details.

Prompts

List Prompts

GET /v1/prompts

Auth: prompts.read

ParameterTypeRequiredDescription
limitnumberNoMaximum results to return (default: 20, max: 100)
cursorstringNoPagination cursor from a previous response
workspacestringNoFilter by workspace ID
includePublicstringNoInclude public prompts (true or false)
qstringNoFilter by title or description substring
tagsstringNoComma-separated list of tags. Items must match all supplied tags (AND semantics). See Filtering by tags.
Example Request
curl -X GET "https://api.contextrepo.com/v1/prompts?limit=10" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": [
    {
      "id": "k57abc123def456",
      "title": "Code Review Prompt",
      "description": "Reviews code for bugs and style issues",
      "content": "Review the following code for potential bugs...",
      "isPublic": false,
      "currentVersion": 2,
      "tags": ["engineering"],
      "stats": { "views": 42, "copies": 7 }
    }
  ],
  "pagination": {
    "cursor": "eyIxIjoiMjAifQ==",
    "hasMore": true
  }
}

Get Prompt

GET /v1/prompts/{id}

Auth: prompts.read

Example Request
curl -X GET "https://api.contextrepo.com/v1/prompts/k57abc123def456" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": {
    "id": "k57abc123def456",
    "title": "Code Review Prompt",
    "description": "Reviews code for bugs and style issues",
    "content": "Review the following ${language} code:\n\n${code}",
    "variables": [
      { "name": "language", "type": "string" },
      { "name": "code", "type": "string" }
    ],
    "isPublic": false,
    "isArchived": false,
    "currentVersion": 2,
    "tags": ["engineering"],
    "stats": { "views": 42, "copies": 7 }
  }
}

Create Prompt

POST /v1/prompts

Auth: prompts.write

FieldTypeRequiredDescription
titlestringYesPrompt title
descriptionstringYesBrief description
contentstringYesFree-form prompt content. Placeholder notation such as ${variable} is stored verbatim.
parametersobjectNoOptional temperature and maxTokens values
variablesarrayNoStored variable metadata with name, type (string, number, or boolean), and optional description
workspaceIdstringNoWorkspace to create the prompt in
tagsstring[]NoTags for categorization
Example Request
curl -X POST "https://api.contextrepo.com/v1/prompts" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Bug Report Template",
    "description": "Generates structured bug reports",
    "content": "Create a bug report for: ${issue_description}"
  }'
Example Response (201 Created)
{
  "data": {
    "id": "k57xyz789ghi012",
    "title": "Bug Report Template",
    "description": "Generates structured bug reports",
    "content": "Create a bug report for: ${issue_description}",
    "isPublic": false,
    "isArchived": false,
    "currentVersion": 0,
    "tags": [],
    "stats": { "views": 0, "copies": 0 }
  }
}

The response includes a Location header with the new prompt's URL: /v1/prompts/{id}.

Context Repo does not infer variable metadata from the prompt body and does not substitute placeholder values. If variables is omitted, the prompt is created with an empty variable array.

Update Prompt

PATCH /v1/prompts/{id}

Auth: prompts.write

Send only the fields you want to change. An update with non-empty content, or one that includes parameters or variables, creates a new version. A title, description, or tags-only update patches the prompt without adding a version.

FieldTypeRequiredDescription
titlestringNoNew title
descriptionstringNoNew description
contentstringNoNew content
parametersobjectNoUpdated parameters
variablesarrayNoUpdated variable definitions
tagsstring[]NoReplaces the prompt's tag set. Pass [] to clear all tags.
changeLogstringNoDescription saved when the update creates a version
Example Request
curl -X PATCH "https://api.contextrepo.com/v1/prompts/k57abc123def456" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Review the following ${language} code for bugs, style, and performance:\n\n${code}",
    "changeLog": "Added performance review to scope"
  }'
Example Response
{
  "data": {
    "id": "k57abc123def456",
    "title": "Code Review Prompt",
    "description": "Reviews code for bugs and style issues",
    "content": "Review the following ${language} code for bugs, style, and performance:\n\n${code}",
    "isPublic": false,
    "isArchived": false,
    "currentVersion": 3,
    "tags": ["engineering"],
    "stats": { "views": 42, "copies": 7 }
  }
}

Delete Prompt

DELETE /v1/prompts/{id}

Auth: prompts.write

Returns 200 with body { "success": true, "id": "<promptId>" } on success.

Example Request
curl -X DELETE "https://api.contextrepo.com/v1/prompts/k57abc123def456" \
  -H "Authorization: API-Key gm_your_api_key"

Get Prompt Versions

GET /v1/prompts/{id}/versions

Auth: prompts.read

Returns the version history for a prompt in descending order. The content field is a preview: at most 200 characters, followed by ... when the stored content is longer. Use GET /v1/prompts/{id} to read the current full content.

Example Request
curl -X GET "https://api.contextrepo.com/v1/prompts/k57abc123def456/versions" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": [
    {
      "id": "v_version003",
      "version": 3,
      "content": "Review the following ${language} code for bugs, style, and performance:\n\n${code}",
      "changeLog": "Added performance review to scope",
      "userName": "Alex Chen"
    },
    {
      "id": "v_version000",
      "version": 0,
      "content": "Review the following ${language} code:\n\n${code}",
      "changeLog": "Original version",
      "userName": "Alex Chen"
    }
  ]
}

Restore Prompt Version

POST /v1/prompts/{id}/restore

Auth: prompts.write

Restores a prompt to a previous version. This creates a new version entry — it doesn't delete the current content.

FieldTypeRequiredDescription
versionIdstringYesThe version ID to restore (from the versions endpoint)
Example Request
curl -X POST "https://api.contextrepo.com/v1/prompts/k57abc123def456/restore" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "versionId": "v_version000" }'
Example Response
{
  "data": {
    "id": "k57abc123def456",
    "title": "Code Review Prompt",
    "description": "Reviews code for bugs and style issues",
    "content": "Review the following ${language} code:\n\n${code}",
    "isPublic": false,
    "isArchived": false,
    "currentVersion": 4,
    "stats": { "views": 42, "copies": 7 }
  }
}

The restore response includes currentVersion as the new version number created by the restore. Unlike the other prompt endpoints, this response does not include tags.


Documents

Every completed document has a canonical revision, contentHash, and lastChangedAt. Detail and write responses also return:

  • ETag: a strong validator for that exact document revision
  • X-ContextRepo-Revision: the current numeric revision
  • X-ContextRepo-Content-Hash: the current Markdown hash

Use the exact ETag from GET /v1/documents/{id} as If-Match on a conditional update, restore, refresh, or coordination-policy change. Don't construct an ETag from the revision number.

PATCH and restore accept either If-Match or body expectedRevision. When both are supplied, their revisions must agree and the header's content hash is also checked. Managed PATCH and restore additionally require Idempotency-Key, X-ContextRepo-Lease-Id, and X-ContextRepo-Lease-Fence. Refresh and coordination-policy operations retain their existing preconditions. expectedRevision must be a nonnegative safe integer (0 through 9007199254740991).

Retry the identical operation with its original revision, key, payload, and lease fields. Do not replace the revision or key to recover an uncertain result. Matching receipts are retained for 24 hours from creation. Reconcile uncertain operations by reading the document and history before taking further action. Preserve the original precondition representation on REST retries too.

Canonical create, update, and restore operations return a compact acknowledgement:

{
  "data": {
    "id": "d_doc123abc",
    "revision": 3,
    "currentVersion": 3,
    "contentHash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "lastChangedAt": 1787702400000,
    "noop": false
  }
}

currentVersion is a compatibility alias for revision. An exact unchanged write is a No-op: it returns noop: true, keeps the current revision, and doesn't add a version-history entry.

List Documents

GET /v1/documents

Auth: documents.read

ParameterTypeRequiredDescription
limitnumberNoMaximum results (default: 20, max: 100)
cursorstringNoPagination cursor
workspacestringNoFilter by workspace ID
collectionIdstringNoFilter by collection ID
statusstringNoFilter by status
searchstringNoFilter by title substring
includeArchivedstringNoInclude archived documents (true or false)
includeContentstringNoInclude document content in response (true or false, default: false)
tagsstringNoComma-separated list of tags. Items must match all supplied tags (AND semantics). See Filtering by tags.
Example Request
curl -X GET "https://api.contextrepo.com/v1/documents?limit=5&includeContent=true" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": [
    {
      "id": "d_doc123abc",
      "title": "API Design Guidelines",
      "status": "completed",
      "isArchived": false,
      "updatedAt": 1710518400000,
      "tags": ["engineering", "standards"],
      "content": "# API Design Guidelines\n\nThis document outlines..."
    }
  ],
  "pagination": {
    "cursor": "eyIxIjoiNSJ9",
    "hasMore": true
  }
}

When includeContent is true, content is truncated to 2,000 characters in list responses. Use the get-document endpoint for document content up to the REST response limit.

Get Document

GET /v1/documents/{id}

Auth: documents.read

ParameterTypeRequiredDescription
includeContentstringNoInclude document content fields, subject to the REST response limit (default: true)
Example Request
curl -X GET "https://api.contextrepo.com/v1/documents/d_doc123abc" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": {
    "id": "d_doc123abc",
    "title": "API Design Guidelines",
    "status": "completed",
    "isArchived": false,
    "createdAt": 1710432000000,
    "updatedAt": 1710518400000,
    "revision": 2,
    "currentVersion": 2,
    "contentHash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "lastChangedAt": 1710518400000,
    "content": "# API Design Guidelines\n\nThis document outlines best practices...",
    "tags": ["engineering", "standards"],
    "sourceType": "scrape",
    "sourceUrl": "https://example.com/api-guidelines",
    "source": {
      "contentHash": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
      "lastCheckedAt": 1787529600000,
      "lastChangedAt": 1787184000000
    }
  }
}

Optional fields with no value (sourceUrl, source, contentHtml, rawHtml, workspaceId) are omitted from the response rather than returned as null. Document content fields are returned up to the REST response limit; use Deep Search for targeted retrieval from large documents. Within source, contentHash, lastCheckedAt, lastChangedAt, and lastRefreshError are also optional. Timestamps are epoch milliseconds. A failed refresh adds lastRefreshError with code, message, and at; a later successful refresh clears it. Internal refresh-lock fields are never returned.

Refresh Document from Source

POST /v1/documents/{id}/refresh

Auth: documents.write (legacy documents.scrape is also accepted)

Re-fetches a completed or failed scraped document from its stored HTTP(S) source URL. Send an empty request body. The response reports whether the source content changed and includes a Location header for the document. For a revisioned document, the 202 response also includes the current ETag, X-ContextRepo-Revision, and X-ContextRepo-Content-Hash after the refresh result is applied.

Example Request
curl -X POST "https://api.contextrepo.com/v1/documents/d_doc123abc/refresh" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response (202 Accepted)
{
  "data": {
    "documentId": "d_doc123abc",
    "changed": true
  }
}

When changed is true, Context Repo creates a new document version and starts chunking and embedding the refreshed content in the background. When it's false, no version is created, but source.lastCheckedAt is updated.

StatusMeaning
400The document isn't a refreshable scraped source, or initial processing hasn't finished
404The document doesn't exist or isn't accessible to the caller
409Another refresh is in progress, or this attempt was superseded by a document edit or newer refresh
429The stricter scrape rate limit was exceeded
500Fetching or saving the refreshed source failed

Create Document

POST /v1/documents

Auth: documents.write

FieldTypeRequiredDescription
titlestringYesDocument title
contentstringYesDocument content (plain text or markdown)
tagsstring[]NoTags for categorization
collectionIdsstring[]NoCollections to add the document to
workspaceIdstringNoWorkspace to create the document in
Example Request
curl -X POST "https://api.contextrepo.com/v1/documents" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Meeting Notes — March 2026",
    "content": "# Key Decisions\n\n- Migrate to v2 API by end of quarter\n- Add webhook support for collections",
    "tags": ["meetings", "planning"]
  }'
Example Response (201 Created)
{
  "data": {
    "id": "d_newdoc456",
    "revision": 0,
    "currentVersion": 0,
    "contentHash": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
    "lastChangedAt": 1787702400000,
    "noop": false
  }
}

Update Document

PATCH /v1/documents/{id}

Auth: documents.write

Send only the fields you want to change. A changed canonical field creates a new version; an exact unchanged request returns a no-op acknowledgement.

FieldTypeRequiredDescription
titlestringNoNew title
contentstringNoNew content
contentHtmlstring | nullNoHTML version, or null to clear it
rawHtmlstring | nullNoRaw source HTML, or null to clear it
sourceUrlstring | nullNoSource URL, or null to clear it
metadataobjectNoReplaces metadata. Pass {} to clear it.
tagsstring[]NoReplaces the document's tag set. Pass [] to clear all tags.
changeLogstringNoDescription of changes (saved in version history)
Example Request
curl -X PATCH "https://api.contextrepo.com/v1/documents/d_doc123abc" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H 'If-Match: "doc:d_doc123abc:rev:2:sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"' \
  -H "Idempotency-Key: update-api-guidelines-3" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "# API Design Guidelines (Updated)\n\nRevised to include REST and GraphQL...",
    "changeLog": "Added GraphQL section"
  }'
Example Response
{
  "data": {
    "id": "d_doc123abc",
    "revision": 3,
    "currentVersion": 3,
    "contentHash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
    "lastChangedAt": 1787702400000,
    "noop": false
  }
}

Delete Document

DELETE /v1/documents/{id}

Auth: documents.write

Returns 200 with body { "success": true, "id": "<documentId>" } on success.

Example Request
curl -X DELETE "https://api.contextrepo.com/v1/documents/d_doc123abc" \
  -H "Authorization: API-Key gm_your_api_key"

Get Document Versions

GET /v1/documents/{id}/versions

Auth: documents.read

Returns the version history for a document.

Example Request
curl -X GET "https://api.contextrepo.com/v1/documents/d_doc123abc/versions" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": [
    {
      "id": "dv_version001",
      "documentId": "d_doc123abc",
      "version": 2,
      "title": "REST API Reference",
      "content": "# REST API Reference\n\n## GraphQL Section\n\n...",
      "contentHtml": "<h1>REST API Reference</h1><h2>GraphQL Section</h2>...",
      "contentHash": "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc",
      "snapshotCompleteness": "complete",
      "actor": { "kind": "api_key", "displayName": "Docs sync" },
      "origin": "rest",
      "changeLog": "Added GraphQL section",
      "userName": "Alex Chen",
      "createdAt": 1710691200000
    },
    {
      "id": "dv_version000",
      "documentId": "d_doc123abc",
      "version": 1,
      "title": "REST API Reference",
      "content": "# REST API Reference\n\nInitial content...",
      "contentHtml": "<h1>REST API Reference</h1><p>Initial content...</p>",
      "changeLog": "Initial version",
      "userName": "Alex Chen",
      "createdAt": 1710432000000
    }
  ]
}

Restore Document Version

POST /v1/documents/{id}/restore

Auth: documents.write

Restores the selected canonical snapshot as a new current revision when it differs. An exact unchanged restore is a no-op. Complete and synthetic snapshots restore every canonical field.

FieldTypeRequiredDescription
versionIdstringYesThe version ID to restore
Example Request
curl -X POST "https://api.contextrepo.com/v1/documents/d_doc123abc/restore" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -H 'If-Match: "doc:d_doc123abc:rev:2:sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"' \
  -H "Idempotency-Key: restore-api-guidelines-2" \
  -d '{ "versionId": "dv_version000" }'
Example Response
{
  "data": {
    "id": "d_doc123abc",
    "revision": 3,
    "currentVersion": 3,
    "contentHash": "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd",
    "lastChangedAt": 1787702400000,
    "noop": false
  }
}

An older legacy_partial snapshot preserves fields that weren't recorded historically. Its first response and any idempotent replay include warnings: ["LEGACY_PARTIAL_SNAPSHOT"].

Get Document Coordination

GET /v1/documents/{id}/coordination

Auth: documents.read

Returns the editing policy (standard or lease_required), current fence, visible lease state, and current revision headers. Lease IDs are returned only to the caller that holds the lease.

Enable Document Coordination

PUT /v1/documents/{id}/coordination

Auth: documents.write (document owner only)

Send an empty body and the current If-Match value to enable managed mode. Managed writers must hold the current lease. The header-based write form is:

If-Match: "<exact ETag from GET>"
Idempotency-Key: <unique retry key>
X-ContextRepo-Lease-Id: <lease ID>
X-ContextRepo-Lease-Fence: <fence number>

For PATCH and restore only, body expectedRevision can replace If-Match; the key, lease ID, and fence remain required. Refresh still requires If-Match.

Disable Document Coordination

DELETE /v1/documents/{id}/coordination

Auth: documents.write (document owner only)

Send the current If-Match value. Disabling fails with 409 while an active lease exists.

Operate Document Lease

POST /v1/documents/{id}/coordination/lease

Auth: documents.write

Every lease request requires Idempotency-Key. Acquire sends { "action": "acquire", "ttlMs": 60000 }. Renew and release send their action in the body plus X-ContextRepo-Lease-Id and X-ContextRepo-Lease-Fence. Successful acquire and renew responses expose X-ContextRepo-Lease-Expires-At.

StatusReasonRecovery
409LEASE_CONFLICT, FENCE_MISMATCH, or operation in progressReload coordination state; don't reuse a stale fence
412REVISION_MISMATCHGET the document again and use its exact ETag
422IDEMPOTENCY_KEY_REUSED or DOCUMENT_NOT_COORDINATABLEUse a new key for changed inputs, or wait for a complete canonical snapshot
428PRECONDITION_REQUIREDAdd the required revision, key, or lease headers

Scrape URL into Document

POST /v1/documents/scrape

Auth: documents.write

Scrapes a webpage and creates a new document from the extracted content using intelligent main-content extraction.

FieldTypeRequiredDescription
urlstringYesThe URL to scrape (auto-prefixed with https:// if no protocol is provided)
collectionIdsstring[]NoCollections to add the resulting document to
optionsobjectNoExtraction options (e.g., onlyMainContent, waitFor) — see Documents — Web Scraping for details
Example Request
curl -X POST "https://api.contextrepo.com/v1/documents/scrape" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/blog/api-design-patterns",
    "collectionIds": ["col_collection123"]
  }'
Example Response (202 Accepted)
{
  "data": {
    "documentId": "d_scraped789"
  }
}

Scraping returns 202 Accepted because extraction happens asynchronously. The document is created and populated in the background. This endpoint has a separate, stricter rate limit than standard CRUD operations.


Collections

List Collections

GET /v1/collections

Auth: documents.read

ParameterTypeRequiredDescription
limitnumberNoMaximum results (default: 20, max: 100)
cursorstringNoPagination cursor (base64-encoded offset)
searchstringNoFilter by name or description substring
workspacestringNoFilter by workspace ID
tagsstringNoComma-separated list of tags. Items must match all supplied tags (AND semantics). See Filtering by tags.
Example Request
curl -X GET "https://api.contextrepo.com/v1/collections?limit=10" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": [
    {
      "id": "col_collection123",
      "name": "Engineering Standards",
      "description": "API guidelines, coding standards, and review checklists",
      "color": "#3b82f6",
      "icon": "📐",
      "isPublic": false,
      "itemCount": 12,
      "lastActivityAt": 1710518400000
    }
  ],
  "pagination": {
    "cursor": "MjA=",
    "hasMore": false
  }
}

Get Collection

GET /v1/collections/{id}

Auth: documents.read

Returns a single collection with its metadata.

Example Request
curl -X GET "https://api.contextrepo.com/v1/collections/col_collection123" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": {
    "id": "col_collection123",
    "name": "Engineering Standards",
    "description": "API guidelines, coding standards, and review checklists",
    "color": "#3b82f6",
    "icon": "📐",
    "isPublic": false,
    "tags": ["engineering"],
    "itemCount": 12,
    "lastActivityAt": 1710518400000,
    "createdAt": 1710432000000,
    "updatedAt": 1710518400000
  }
}

A stats object (total items, per-type counts, top contributors) is appended only when the caller authenticates with a Clerk session token. API-key and machine-token requests receive the response without stats.

Get Collection Items

GET /v1/collections/{id}/items

Auth: documents.read

Returns the prompts and documents in a collection.

ParameterTypeRequiredDescription
limitnumberNoMaximum items (default: 20, max: 100)
cursorstringNoPagination cursor
includeContentstringNoInclude document content (true or false)
Example Request
curl -X GET "https://api.contextrepo.com/v1/collections/col_collection123/items?limit=10" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": [
    {
      "itemType": "prompt",
      "itemId": "k57abc123def456",
      "title": "Code Review Prompt",
      "summary": "Reviews code for bugs and style issues"
    },
    {
      "itemType": "document",
      "itemId": "d_doc123abc",
      "title": "API Design Guidelines",
      "summary": null
    }
  ],
  "pagination": {
    "cursor": "eyIxIjoiMTAifQ==",
    "hasMore": false
  }
}

Create Collection

POST /v1/collections

Auth: documents.write

FieldTypeRequiredDescription
namestringYesCollection name
descriptionstringNoCollection description
colorstringNoHex color code (e.g., #3b82f6)
iconstringNoEmoji icon (e.g., 📐)
workspaceIdstringNoWorkspace to create the collection in
parentCollectionIdstringNoParent collection for nesting
tagsstring[]NoTags for cross-type organization. See Filtering by tags.
Example Request
curl -X POST "https://api.contextrepo.com/v1/collections" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Product Roadmap",
    "description": "Planning docs and feature specs",
    "icon": "🗺️",
    "color": "#10b981"
  }'
Example Response (201 Created)
{
  "data": {
    "id": "col_newcol789",
    "name": "Product Roadmap",
    "description": "Planning docs and feature specs",
    "icon": "🗺️",
    "color": "#10b981",
    "isPublic": false,
    "tags": [],
    "itemCount": 0,
    "lastActivityAt": 1710604800000,
    "createdAt": 1710604800000,
    "updatedAt": 1710604800000
  }
}

Update Collection

PATCH /v1/collections/{id}

Auth: documents.write

Send only the fields you want to change.

FieldTypeRequiredDescription
namestringNoNew name
descriptionstringNoNew description
colorstringNoNew hex color code
iconstringNoNew emoji icon
isPublicbooleanNoMake collection public or private
tagsstring[]NoReplaces the collection's tag set. Pass [] to clear all tags.

Reparenting (changing parentCollectionId) is not currently supported via PATCH. Set the parent only at creation time via POST.

Example Request
curl -X PATCH "https://api.contextrepo.com/v1/collections/col_collection123" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Engineering Standards v2", "color": "#8b5cf6" }'
Example Response
{
  "data": {
    "id": "col_collection123",
    "name": "Engineering Standards v2",
    "description": "API guidelines, coding standards, and review checklists",
    "color": "#8b5cf6",
    "icon": "📐",
    "isPublic": false,
    "tags": ["engineering"],
    "itemCount": 12,
    "lastActivityAt": 1710518400000,
    "createdAt": 1710432000000,
    "updatedAt": 1710691200000
  }
}

Delete Collection

DELETE /v1/collections/{id}

Auth: documents.write

Returns 200 with body { "success": true, "id": "<collectionId>" } on success. Deleting a collection does not delete the prompts and documents inside it — they remain in your workspace.

Example Request
curl -X DELETE "https://api.contextrepo.com/v1/collections/col_collection123" \
  -H "Authorization: API-Key gm_your_api_key"

Add Items to Collection

POST /v1/collections/{id}/items

Auth: documents.write

Adds prompts or documents to a collection.

FieldTypeRequiredDescription
itemIdsstring[]YesArray of prompt or document IDs to add
itemTypestringYesType of items: document or prompt
Example Request
curl -X POST "https://api.contextrepo.com/v1/collections/col_collection123/items" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "itemIds": ["k57abc123def456", "k57xyz789ghi012"],
    "itemType": "prompt"
  }'
Example Response
{
  "data": {
    "added": 2,
    "alreadyInCollection": 0
  }
}

Remove Items from Collection

PUT /v1/collections/{id}/items

Auth: documents.write

Removes prompts or documents from a collection. Uses PUT instead of DELETE because the request requires a JSON body.

FieldTypeRequiredDescription
itemIdsstring[]YesArray of prompt or document IDs to remove
itemTypestringYesType of items: document or prompt
Example Request
curl -X PUT "https://api.contextrepo.com/v1/collections/col_collection123/items" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "itemIds": ["k57abc123def456"],
    "itemType": "prompt"
  }'
Example Response
{
  "data": {
    "removed": 1
  }
}

Search Across Resources

GET /v1/search

Auth: At least one of prompts.read or documents.read

Searches across prompts, documents, and collections. Supports both semantic (AI embeddings) and literal (substring matching) modes.

ParameterTypeRequiredDescription
q or querystringYesSearch query
typestringNoFilter by type: prompts, documents, collections, or all (default: all)
semanticstringNoUse semantic search (default: true). Set to false for literal matching
limitnumberNoMaximum results per type (default: 10, max: 50)
scoreThresholdnumberNoMinimum relevance score for semantic results (default: 0.35)
tagsstringNoComma-separated list of tags. Applied symmetrically across prompts, documents, and collections. Items must match all supplied tags (AND semantics). See Filtering by tags.
Example Request — Semantic Search
curl -X GET "https://api.contextrepo.com/v1/search?q=API+design+best+practices&type=all" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response — Semantic
{
  "data": {
    "documents": [
      {
        "documentId": "d_doc123abc",
        "title": "API Design Guidelines",
        "score": 0.87,
        "highlight": "...every endpoint declares explicit request and response contracts...",
        "tags": ["engineering", "standards"]
      }
    ],
    "prompts": [
      {
        "promptId": "k57abc123def456",
        "title": "Code Review Prompt",
        "description": "Reviews code for bugs and style issues",
        "score": 0.74,
        "tags": ["engineering"]
      }
    ],
    "collections": []
  },
  "meta": {
    "query": "API design best practices",
    "semantic": true,
    "latencyMs": 142
  }
}
Example Request — Literal Search
curl -X GET "https://api.contextrepo.com/v1/search?q=API+Design&semantic=false&type=documents" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response — Literal
{
  "data": {
    "documents": [
      {
        "documentId": "d_doc123abc",
        "title": "API Design Guidelines",
        "tags": ["engineering", "standards"],
        "highlight": "...every endpoint in our API Design standard declares explicit request and response contracts...",
        "chunkId": "hc_chunk789xyz"
      }
    ],
    "prompts": [],
    "collections": []
  },
  "meta": {
    "query": "API Design",
    "semantic": false
  }
}

Literal document hits matched in the content preview or body carry an optional highlight snippet. Hits matched in the body also carry a chunkId, which can be passed to the progressive disclosure endpoints (GET /v1/pd/read/{chunkId}, POST /v1/pd/expand) to read or navigate around the matching passage.

Semantic search uses AI embeddings to find conceptually related content — it doesn't require exact keyword matches. Literal search matches substrings in titles, descriptions, and indexed document body text via hierarchical chunks — full-body literal matching, eventually consistent with chunking. Title and preview matches are immediate; body matches appear once a document's chunks are indexed.

Filtering by tags

Every list endpoint and /v1/search accepts a tags query parameter that filters the response by item-level tags. Tags are free-form string labels stored on the collections, prompts, and documents rows themselves; they apply uniformly across all three resource types.

Encoding: comma-separated values in a single query parameter.

?tags=draft,roadmap-q3

Whitespace around each value is trimmed. Empty segments (?tags=,foo,) are dropped. Tag values must not contain a literal comma — the parser uses , as the separator and there is no escape syntax.

Semantics: AND. A row is included in the response only if every supplied tag is present in its tag array. Searching with ?tags=alpha,beta excludes any item that has alpha but not beta, and vice versa. Pass a single tag (?tags=alpha) for one-axis filtering. Omit the parameter entirely to disable tag filtering.

Supported endpoints:

  • GET /v1/prompts
  • GET /v1/documents
  • GET /v1/collections
  • GET /v1/search — applied symmetrically to the prompts, documents, and collections branches in both literal and semantic modes.

Setting tags: POST and PATCH on prompts, documents, and collections all accept a tags: string[] body field. Sending tags: [] clears the tag set; omitting the field on a PATCH leaves the existing tags untouched.

Read shape: every read response (list, get, search) projects a tags: string[] field. Rows that have never had tags assigned project [], never null or undefined.

```bash title="Example — list collections tagged both draft AND q3-roadmap" curl -X GET "https://api.contextrepo.com/v1/collections?tags=draft,q3-roadmap"
-H "Authorization: API-Key gm_your_api_key"


```bash title="Example — search across all types, scoped to a project tag"
curl -X GET "https://api.contextrepo.com/v1/search?q=migration&tags=customer-x" \
  -H "Authorization: API-Key gm_your_api_key"

Progressive Disclosure

Progressive disclosure endpoints let you search and navigate through document content at different levels of detail, from summaries down to individual paragraphs.

Search Content

POST /v1/pd/search

Auth: documents.read

Searches document content with configurable detail level and returns ranked chunks.

FieldTypeRequiredDescription
querystringYesSearch query
sessionIdstringNoSession ID for deduplication across searches
maxTokensnumberNoMaximum tokens in response
limitnumberNoMaximum chunks to return (default: 10)
detailLevelstringNosummary (default) returns condensed chunk content; full returns the complete chunk text
documentIdstringNoFilter to a specific document
collectionIdstringNoFilter to a specific collection
Example Request
curl -X POST "https://api.contextrepo.com/v1/pd/search" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "authentication best practices",
    "limit": 5
  }'
Example Response
{
  "data": {
    "results": [
      {
        "chunkId": "hc_chunk001",
        "content": "Use JWT tokens with short expiration windows...",
        "level": "section",
        "score": 0.89,
        "parentId": "hc_parent001",
        "siblingIds": { "prev": null, "next": "hc_chunk002" },
        "documentId": "d_doc123abc",
        "documentTitle": "Security Guidelines"
      }
    ],
    "meta": { "query": "authentication best practices", "totalResults": 1, "latencyMs": 142 }
  }
}

Expand Chunk

POST /v1/pd/expand

Auth: documents.read

Navigates the document hierarchy from a specific chunk. You can move up (parent), down (children), next/previous (siblings), or get surrounding context.

FieldTypeRequiredDescription
chunkIdstringYesThe chunk ID to expand from
directionstringYesNavigation direction: up, down, next, previous, or surrounding
countnumberNoNumber of chunks to return
Example Request
curl -X POST "https://api.contextrepo.com/v1/pd/expand" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{
    "chunkId": "hc_chunk001",
    "direction": "down",
    "count": 3
  }'
Example Response
{
  "data": {
    "chunks": [
      {
        "_id": "hc_chunk002",
        "content": "JWT tokens should be signed with RS256...",
        "level": "paragraph",
        "parentId": "hc_chunk001",
        "chunkIndex": 0,
        "documentId": "d_doc123abc",
        "documentTitle": "Security Guidelines"
      }
    ]
  }
}

On this endpoint the chunk id field is named _id (not chunkId). An empty chunks array means there is nothing in the requested direction — including chunk IDs that no longer exist after a document was re-chunked.

Read Chunk

GET /v1/pd/read/{chunkId}

Auth: documents.read

Returns a single chunk with its full content and hierarchy metadata.

Example Request
curl -X GET "https://api.contextrepo.com/v1/pd/read/hc_chunk001" \
  -H "Authorization: API-Key gm_your_api_key"
Example Response
{
  "data": {
    "chunkId": "hc_chunk001",
    "content": "Use JWT tokens with short expiration windows and rotate signing keys regularly.",
    "level": "section",
    "hierarchy": {
      "documentId": "d_doc123abc",
      "documentTitle": "Security Guidelines",
      "sectionPath": "Security Guidelines > Authentication",
      "position": {
        "chunkIndex": 2,
        "parentChunkId": "hc_parent001",
        "prevSiblingId": null,
        "nextSiblingId": "hc_chunk002"
      }
    },
    "metadata": {
      "startIndex": 1042,
      "endIndex": 1138,
      "wordCount": 14,
      "sectionPath": "Security Guidelines > Authentication",
      "headingText": "Authentication"
    }
  }
}

Create Session

POST /v1/pd/session

Auth: Any valid authentication

Creates a search session for deduplication. Pass the returned sessionId to the search endpoint to avoid seeing the same chunks across multiple queries.

FieldTypeRequiredDescription
ttlnumberNoSession time-to-live in seconds
Example Request
curl -X POST "https://api.contextrepo.com/v1/pd/session" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "ttl": 3600 }'
Example Response (201 Created)
{
  "data": {
    "sessionId": "sess_abc123",
    "createdAt": 1710604800000,
    "expiresAt": 1710608400000
  }
}

Reasoning

Synthesize an Answer

POST /v1/reason

Auth: Delegated user authentication, or a scoped API-key/machine credential with documents.read

Ask a question and get a best-effort, cited answer composed across your documents — not a list of chunks. Bounded retrieval feeds a strict assessment of cited statements and limitations, which is projected into the answer, inline citations to the exact chunks used, and best-effort gaps. The gaps list is non-exhaustive; an empty list doesn't prove complete coverage. Read-only.

See Reasoning for guidance on choosing a scope, reading citations, and interpreting gaps and disagreements.

FieldTypeRequiredDescription
querystringYesThe natural-language question to answer across your documents. It must contain at least one non-whitespace character; leading and trailing whitespace is trimmed.
limitnumberNoMaximum number of evidence chunks in the synthesis packet. Defaults to 50; non-integers are truncated and values are clamped to 1–50.
maxTokensnumberNoToken budget for gathered evidence passed to synthesis (default: 8000). Finite values are truncated; negative values become zero.
documentIdstringNoRestrict reasoning to a single document
collectionIdstringNoRestrict reasoning to a single collection
Example Request
curl -X POST "https://api.contextrepo.com/v1/reason" \
  -H "Authorization: API-Key gm_your_api_key" \
  -H "Content-Type: application/json" \
  -d '{ "query": "What is our refund policy for annual plans?", "limit": 8 }'
Example Response (200 OK)
{
  "data": {
    "answer": "Claim:\nAnnual plans are refundable within the first 14 days. [[hc_chunk001]]",
    "citations": [
      {
        "chunkId": "hc_chunk001",
        "documentId": "doc_abc123",
        "documentTitle": "Billing Policy"
      }
    ],
    "gaps": ["No stated policy for partial-year downgrades"],
    "meta": {
      "chunksGathered": 8,
      "citationsDropped": 0,
      "latencyMs": 1840
    }
  }
}

The answer field uses server-generated [[chunkId]] tokens that resolve to entries in citations. Disagreements appear as ordinary cited statements. The model preserves supplied source differences without choosing a winner unless the evidence establishes one.

The server validates admitted chunk IDs and requires each quote to occur in the admitted chunk after both values collapse whitespace runs and trim their edges. Invalid dependent content is withheld. citationsDropped counts references withheld by failed mechanical validation; retained duplicate references do not increase it. This diagnostic is not a semantic-correctness score. Exact citation validation proves source linkage, not semantic entailment. gaps contains best-effort limitations noticed in this run, including facts not established by the retrieved evidence within the requested scope and retrieval limits. It is non-exhaustive and does not prove repository-wide absence. Disagreements appear as ordinary cited statements in answer.

Reason uses the progressive-search result list directly, preserves its order, and applies the final limit and evidence budget to content, titles, and wrappers together. It does not enumerate extra collection members or add ancestors, children, or heading matches. Similarity scores remain internal to the unscoped relevance guard and are omitted from provider evidence and public citations.

If no evidence is available, the endpoint skips synthesis and returns the scoped no-evidence sentence in both answer and gaps. Weak unscoped evidence also skips synthesis. A nonempty result from an explicit documentId or collectionId scope reaches synthesis even when its best score is below Reason's fixed relevance guard; progressive retrieval thresholds and authorization still apply. Retrieval or token limits can exclude eligible context without adding a generic partial-evidence warning.


MCP Capabilities

Get MCP Capabilities

GET /v1/mcp/capabilities

Auth: None (public)

Returns the MCP protocol capabilities supported by Context Repo.

Example Request
curl -X GET "https://api.contextrepo.com/v1/mcp/capabilities"
Example Response
{
  "version": "1.0.0",
  "capabilities": {
    "prompts": {
      "rest": true,
      "list": true,
      "get": true,
      "create": true,
      "update": true,
      "delete": true,
      "versions": true,
      "searchQueryParam": true
    },
    "documents": {
      "rest": true,
      "list": true,
      "get": true,
      "create": true,
      "update": true,
      "delete": true,
      "versions": true,
      "scrape": true
    },
    "collections": {
      "rest": true,
      "list": true,
      "get": true,
      "create": true,
      "update": true,
      "delete": true,
      "items": true
    },
    "search": { "rest": true },
    "progressiveDisclosure": {
      "search": true,
      "expand": true,
      "read": true,
      "session": true
    },
    "reason": { "rest": true },
    "auth": { "bearer": true, "apiKey": true }
  }
}

Error Codes

All error responses use the same envelope format with a numeric code and a message string:

{
  "error": {
    "code": 404,
    "message": "Document not found"
  }
}
HTTP StatusMeaningCommon Causes
400Bad RequestMissing required fields, invalid JSON body, malformed IDs, invalid parameters
401UnauthorizedMissing Authorization header, expired JWT token, invalid API key
403ForbiddenValid authentication but the API key lacks the required permission scope
404Not FoundResource doesn't exist or you don't have access to it
429Rate LimitedToo many requests — wait and retry. Rate limit headers are included in the response
500Internal Server ErrorUnexpected server error — retry the request or contact support