REST API
POST /v1/episodes
Write a prose episode. Returns the extracted entities and edges.
Ingest a prose episode. Breeth extracts entities and edges synchronously, then runs narration, profile distillation, and (if you opted in) intent annotation asynchronously.
Scope required: write
Request
POST /v1/episodes
Authorization: Bearer ck_live_...
Content-Type: application/json{
"content": "Nandini Kulkarni shipped the migration in Q1 and was promoted to Staff Engineer.",
"group_id": "default",
"source_description": "api",
"extract_intent": false
}| Field | Type | Required | Notes |
|---|---|---|---|
content | string, ≥ 1 char | yes | The prose to ingest. |
group_id | string | no ("default") | Sub-namespace within your project. Letters, digits, dashes, underscores. |
source_description | string, ≤ 120 chars | no ("api") | Free-form label shown in the dashboard. |
extract_intent | bool | no (false) | Run intent annotation. Counts against monthly intents cap. See Intents. |
Response — 200 OK
{
"ok": true,
"episode_name": "api_1778498269735",
"extracted": {
"entities": 4,
"edges": 3
},
"group_id": "default",
"warning": null,
"cogram": {
"mode": "async",
"status": "pipeline_running_in_background",
"task_id": "0ef8c19d6381",
"note": "narrative/profile populate within ~15s"
},
"intent_suggestion": null
}| Field | Meaning |
|---|---|
episode_name | Unique name. Use it with GET /v1/episodes/{name} to retrieve the raw content. |
extracted.entities | Count of new + updated nodes in the graph. |
extracted.edges | Count of new edges. May be 0 for very terse content. |
warning | Present when entities extracted but no edges (terse content, pronouns, snake_case predicates). |
cogram.task_id | Background pipeline id. Poll GET /v1/tasks/{task_id} for narration / profile completion. |
intent_suggestion | If you did not pass extract_intent: true and the content looks high-signal, this carries {should_extract, confidence, reason}. The suggestion is free; acting on it costs an intent credit. |
Errors
| HTTP | Slug | When |
|---|---|---|
| 400 | invalid_request | Missing content or it's empty |
| 401 | unauthenticated | Bad / missing Bearer |
| 402 | payment_required | Subscription past-due |
| 403 | missing_scope | Key lacks write scope |
| 429 | quota_exceeded | Monthly writes cap hit — kind: "episodes_per_month" |
| 429 | quota_exceeded | Monthly intents cap hit (only when extract_intent: true) — kind: "intent_extractions" |
Examples
curl -X POST https://api.thebreeth.com/v1/episodes \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{
"content": "Sridhar prefers async Rust over Go for IO-heavy services.",
"extract_intent": true
}'import httpx
r = httpx.post(
"https://api.thebreeth.com/v1/episodes",
headers={"Authorization": f"Bearer {KEY}"},
json={
"content": "Sridhar prefers async Rust over Go for IO-heavy services.",
"extract_intent": True,
},
)
r.raise_for_status()
print(r.json())const r = await fetch("https://api.thebreeth.com/v1/episodes", {
method: "POST",
headers: {
"Authorization": `Bearer ${KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
content: "Sridhar prefers async Rust over Go for IO-heavy services.",
extract_intent: true,
}),
});
if (!r.ok) throw new Error(await r.text());
console.log(await r.json());Related
POST /v1/facts— write a single subject/predicate/object triplePOST /v1/search— retrieve facts after writing- Episodes concept