# API reference

> Every operation and schema of the runtime API, generated from openapi/runtime.yaml.

Memory for agents. Call decorate before every model call and submit what it returns; report the reply after.

Base URL: `https://api.threadlessai.com/v1`. Version 1.0.0. The raw spec is at [/openapi/runtime.yaml](https://threadlessai.com/openapi/runtime.yaml).

Authenticate every request with a project key: `Authorization: Bearer tl_live_…` (or `tl_test_…`). Errors share one shape, [Error](#error), with a `hint` saying what to do about it.

## Operations

| Operation | Method and path | Summary |
|---|---|---|
| [createMemory](#creatememory) | `POST /memories` | Create a memory: one per conversation. |
| [getMemory](#getmemory) | `GET /memories/{memory_id}` | A memory's size and activity. |
| [deleteMemory](#deletememory) | `DELETE /memories/{memory_id}` | Delete a memory and everything it holds. Cannot be undone. |
| [decorate](#decorate) | `POST /memories/{memory_id}/decorate` | Before every model call: hand over what is new, get back the request to submit. |
| [report](#report) | `POST /memories/{memory_id}/report` | After the model replies: hand over the reply. Returns at once. |
| [exportMemory](#exportmemory) | `GET /memories/{memory_id}/export` | Everything a memory holds: messages, episodes and facts. |

### createMemory

`POST https://api.threadlessai.com/v1/memories`

Create a memory: one per conversation.

Request body (optional): [CreateMemoryRequest](#creatememoryrequest)

| Status | Meaning | Body |
|---|---|---|
| 201 | Created. | [Memory](#memory) |
| 400 | The request is malformed. | [Error](#error) |
| 401 | The API key is missing or revoked. | [Error](#error) |
| 404 | No memory with this id in this project. | [Error](#error) |
| 429 | Too many requests, or the plan quota is used up. | [Error](#error) |

### getMemory

`GET https://api.threadlessai.com/v1/memories/{memory_id}`

A memory's size and activity.

| Parameter | In | Type | Required |
|---|---|---|---|
| `memory_id` | path | string `^mem_[A-Za-z0-9]{24}$` | yes |

| Status | Meaning | Body |
|---|---|---|
| 200 | The memory. | [Memory](#memory) |
| 400 | The request is malformed. | [Error](#error) |
| 401 | The API key is missing or revoked. | [Error](#error) |
| 404 | No memory with this id in this project. | [Error](#error) |
| 429 | Too many requests, or the plan quota is used up. | [Error](#error) |

### deleteMemory

`DELETE https://api.threadlessai.com/v1/memories/{memory_id}`

Delete a memory and everything it holds. Cannot be undone.

| Parameter | In | Type | Required |
|---|---|---|---|
| `memory_id` | path | string `^mem_[A-Za-z0-9]{24}$` | yes |

| Status | Meaning | Body |
|---|---|---|
| 204 | Deleted and verified gone. | none |
| 400 | The request is malformed. | [Error](#error) |
| 401 | The API key is missing or revoked. | [Error](#error) |
| 404 | No memory with this id in this project. | [Error](#error) |
| 429 | Too many requests, or the plan quota is used up. | [Error](#error) |

### decorate

`POST https://api.threadlessai.com/v1/memories/{memory_id}/decorate`

Before every model call: hand over what is new, get back the request to submit.

Returns the full request body for OpenAI: history with forgotten parts already out of view, remembered facts and recall in place, and the note ask when history is leaving. The `Server-Timing` header carries each step.

| Parameter | In | Type | Required |
|---|---|---|---|
| `memory_id` | path | string `^mem_[A-Za-z0-9]{24}$` | yes |

Request body: [DecorateRequest](#decoraterequest)

| Status | Meaning | Body |
|---|---|---|
| 200 | The request to submit. | [DecorateResult](#decorateresult) |
| 400 | The request is malformed. | [Error](#error) |
| 401 | The API key is missing or revoked. | [Error](#error) |
| 404 | No memory with this id in this project. | [Error](#error) |
| 429 | Too many requests, or the plan quota is used up. | [Error](#error) |

### report

`POST https://api.threadlessai.com/v1/memories/{memory_id}/report`

After the model replies: hand over the reply. Returns at once.

| Parameter | In | Type | Required |
|---|---|---|---|
| `memory_id` | path | string `^mem_[A-Za-z0-9]{24}$` | yes |

Request body: [ReportRequest](#reportrequest)

| Status | Meaning | Body |
|---|---|---|
| 202 | Accepted; the work runs in the background. | [ReportResult](#reportresult) |
| 400 | The request is malformed. | [Error](#error) |
| 401 | The API key is missing or revoked. | [Error](#error) |
| 404 | No memory with this id in this project. | [Error](#error) |
| 429 | Too many requests, or the plan quota is used up. | [Error](#error) |

### exportMemory

`GET https://api.threadlessai.com/v1/memories/{memory_id}/export`

Everything a memory holds: messages, episodes and facts.

| Parameter | In | Type | Required |
|---|---|---|---|
| `memory_id` | path | string `^mem_[A-Za-z0-9]{24}$` | yes |

| Status | Meaning | Body |
|---|---|---|
| 200 | The export. | [MemoryExport](#memoryexport) |
| 400 | The request is malformed. | [Error](#error) |
| 401 | The API key is missing or revoked. | [Error](#error) |
| 404 | No memory with this id in this project. | [Error](#error) |
| 429 | Too many requests, or the plan quota is used up. | [Error](#error) |

## Schemas

### Error

| Field | Type | Required | Description |
|---|---|---|---|
| `error` | object | yes |  |
| `error.code` | `"invalid_request"` or `"unauthorized"` or `"forbidden"` or `"not_found"` or `"conflict"` or `"rate_limited"` or `"quota_exceeded"` or `"internal"` | yes |  |
| `error.message` | string | yes |  |
| `error.hint` | string | no | What to do about it. |

### CreateMemoryRequest

| Field | Type | Required | Description |
|---|---|---|---|
| `metadata` | map of string, at most 512 | no | Up to 16 string pairs of your own, such as your conversation id. |

### DecorateRequest

| Field | Type | Required | Description |
|---|---|---|---|
| `format` | `"chat.completions"` or `"responses"` | yes | The OpenAI API the request is for: Chat Completions (`messages`) or Responses (`input` items). |
| `messages` | array of object or object | yes | Everything new since the last call: the reply plus the user message, or the reply plus tool results. System and developer messages are the instructions: the latest set replaces the stored one and always leads the request. |
| `messages[]` | object | | A Chat Completions message, exactly as it would be sent to OpenAI. |
| `messages[]` | object | | A Responses input item (message, function_call, function_call_output, reasoning, …). |
| `request` | object | yes | The rest of the request body as it would be sent to OpenAI (model, tools, tool_choice, temperature, instructions, …), without the history. `previous_response_id` and `store` are dropped. |
| `request.model` | string | yes |  |

### DecorateResult

| Field | Type | Required | Description |
|---|---|---|---|
| `request` | object | yes | The request body, ready to submit to OpenAI with your own key. |
| `memory` | object | yes |  |
| `memory.id` | string `^mem_[A-Za-z0-9]{24}$` | yes | A memory id, as `POST /v1/memories` returned it. |
| `memory.revision` | integer | yes | Increases with every change to the memory. |
| `memory.turn` | integer | yes | The current user turn, counting from 1. |
| `memory.notes_requested` | boolean | yes | True when this request asks the model for notes on history leaving live context. The model answers with the note tool. |
| `memory.recalled` | integer | yes | Facts and passages recalled into this request. |
| `memory.facts_in_view` | integer | yes | Remembered facts shown in this request. |
| `memory.tokens` | integer | yes | Our estimate of the request size, in tokens. |

### Memory

| Field | Type | Required | Description |
|---|---|---|---|
| `id` | string `^mem_[A-Za-z0-9]{24}$` | yes | A memory id, as `POST /v1/memories` returned it. |
| `object` | `"memory"` | yes |  |
| `created_at` | string (date-time) | yes |  |
| `last_activity_at` | string (date-time) or null | yes |  |
| `metadata` | map of string | yes |  |
| `turns` | integer | yes |  |
| `messages` | integer | yes |  |
| `episodes` | object | yes |  |
| `episodes.live` | integer | yes | In live context, messages and all. |
| `episodes.sealed` | integer | yes | Messages out of view; their facts still shown. |
| `episodes.forgotten` | integer | yes | Out of view entirely; held in long-term memory for recall. |
| `facts` | integer | yes |  |
| `bytes` | integer | yes | Stored size, the figure storage is billed on. |

### MemoryExport

| Field | Type | Required | Description |
|---|---|---|---|
| `memory` | [Memory](#memory) | yes |  |
| `messages` | array of object | yes |  |
| `messages[].seq` | integer | yes |  |
| `messages[].turn` | integer | yes |  |
| `messages[].at` | string (date-time) | yes |  |
| `messages[].item` | object | yes |  |
| `episodes` | array of object | yes |  |
| `episodes[].id` | integer | yes |  |
| `episodes[].state` | `"live"` or `"leaving"` or `"sealed"` or `"forgotten"` | yes |  |
| `episodes[].first_turn` | integer | yes |  |
| `episodes[].last_turn` | integer | yes |  |
| `episodes[].encoded_at` | string (date-time) | yes |  |
| `episodes[].message_seqs` | array of integer | yes |  |
| `facts` | array of object | yes |  |
| `facts[].id` | string | yes |  |
| `facts[].text` | string | yes |  |
| `facts[].entities` | array of string | yes |  |
| `facts[].milestone` | boolean | yes |  |
| `facts[].written_by` | `"model"` or `"system"` | yes |  |
| `facts[].written_at` | string (date-time) | yes |  |

### ReportRequest

| Field | Type | Required | Description |
|---|---|---|---|
| `format` | `"chat.completions"` or `"responses"` | yes | The OpenAI API the request is for: Chat Completions (`messages`) or Responses (`input` items). |
| `reply` | object | yes | The provider response, exactly as OpenAI returned it (usage included). |

### ReportResult

| Field | Type | Required | Description |
|---|---|---|---|
| `accepted` | `true` | yes |  |
| `revision` | integer | yes |  |
