REST API Reference
The Threadline REST API lets you manage persistent context for any user from any runtime. Every endpoint is authenticated with a bearer token.
Base URL & Auth
All requests are made to https://app.threadline.to and require a bearer token in the Authorization header.
curl https://app.threadline.to/api/context/inject \
-H "Authorization: Bearer tl_live_..." \
-H "Content-Type: application/json"Scopes
Context is organised into seven scopes:
preferencesgoalsknowledgehistoryrelationshipscommunication_stylegeneralA grant controls which scopes an agent may read and write for a given user. The first inject call for a user auto-provisions the grant it needs, so there is no separate grant call required to get started.
Explicit grant management via the API is documented with the Context Protocol spec. Until then, grants are visible and revocable in the dashboard.
Endpoints
/api/context/injectBuild an enriched system prompt from a user's stored context.
/api/context/updatePersist new facts and conversational turns into the user's context.
/api/context/{userId}Retrieve the full structured context object for a user. Requires an API key and an active grant.
/api/context/{userId}Permanently delete a user's stored context. Requires an API key and an active grant for that user; returns 403 FORBIDDEN with no active grant.
/api/healthLiveness check. No authentication required.
Inject
userId and basePrompt are required; agentId is optional.
curl -X POST https://app.threadline.to/api/context/inject \
-H "Authorization: Bearer tl_live_..." \
-H "Content-Type: application/json" \
-d '{
"userId": "user_42",
"basePrompt": "You are a helpful assistant.",
"agentId": "optional-agent-id"
}'
// Response
{
"injectedPrompt": "You are a helpful assistant.\n\nKnown facts about user_42:\n- Prefers concise replies\n- Lives in Berlin"
}When there is nothing to inject, injectedPrompt returns your base prompt unchanged and the response carries a machine-readable reason — one of no_grant, no_scopes, empty, or empty_capsule. This lets you tell “this user has no stored context yet” apart from “the agent was not granted the scopes it asked for”.
// Nothing to inject
{
"injectedPrompt": "You are a helpful assistant.",
"reason": "no_grant"
}Update
curl -X POST https://app.threadline.to/api/context/update \
-H "Authorization: Bearer tl_live_..." \
-H "Content-Type: application/json" \
-d '{
"userId": "user_42",
"userMessage": "I just moved to Lisbon.",
"agentResponse": "Welcome to Lisbon!"
}'The response reports whether a write occurred and what was refused. updated indicates whether anything was persisted, and delta contains the facts that were actually written, grouped by scope. When a turn produces a fact in a scope the grant does not permit, the response lists the denied scopes and a notice explaining the refusal, rather than silently dropping or silently storing it. When every extracted fact is denied, updated returns false and delta is empty. Every reason value is documented on the Response reasons page.
// Response
{
"updated": true,
"delta": {
"communication_style": "keeps answers terse"
},
"denied_scopes": ["relationships"],
"notice": "1 fact was not stored: the grant for this agent does not include the 'relationships' scope."
}Read & delete context
curl https://app.threadline.to/api/context/user_42 \
-H "Authorization: Bearer tl_live_..."
curl -X DELETE https://app.threadline.to/api/context/user_42 \
-H "Authorization: Bearer tl_live_..."Health
curl https://app.threadline.to/api/health