API Reference
Memory Record
Record operations use the Vault named in X-Ragionex-Vault-Id, or the account's default Vault; see Vault selection and the Vaults guide. A full live record has exactly nine fields:
| Field | Type | Meaning |
|---|---|---|
id | string | Server-generated record ID. IDs accepted by record operations contain 1–14 ASCII letters, digits or underscores. |
vault_id | string | The Vault containing this record. Use this ID in X-Ragionex-Vault-Id for follow-up operations. |
content | string | Saved text. Search, view and current-record export return the full text. List, trash and version lists return its first 200 characters without an added ellipsis; a single-version read returns full text. Write, update and restore acknowledgements omit content. |
created_at | string | Creation time in RFC 3339 UTC, such as 2024-04-12T00:00:00Z. |
updated_at | string | Last update, trash or restore time in RFC 3339 UTC. It equals creation time when no later change exists. |
status | string | processing, ready or failed. Trash items show trashed; version entries can also show trashed. Only ready records appear in search. |
revision | integer | Starts at 1 and increases for each changed update, trash or restore. Processing status changes and identical-content updates do not increase it. |
created_by | string | Account ID that originally created the record. It does not change on later edits, trash or restore. |
updated_by | string | Account ID responsible for the most recent content change, trash or restore. It initially equals created_by. |
Creator and editor attribution use account IDs, not key names. Renaming or revoking a key does not change these IDs. Identical-content updates, duplicate saves and matching write retries preserve the existing attribution; actor IDs remain stored even if their accounts are later deleted.
Save accepts only content. Update requires id, expected_revision and replacement content. Keep any contextual labels, references or supporting text inside content; there are no extra record metadata fields.
Write, update and restore return success: true with the eight record metadata fields above, omitting content. Search returns nine-field records in results; list and view use memories. Export groups records under Vaults. Status polling returns separate progress metadata, including the Vault and actor IDs, without content or creation time.
Key Permissions
Send X-API-Key on every Memory request. Send Content-Type: application/json for JSON bodies. A valid key without the required effective grant receives HTTP 403 with no_access. Use X-Ragionex-Vault-Id to select a Vault. Knowing a record ID never grants access to another Vault.
| Method and endpoint | Required grant | Usage charge |
|---|---|---|
| GET /v1/memory/identity | Any valid key | None |
| POST /v1/memory/write | create | One request per accepted write, including duplicate saves and matching retries |
| POST /v1/memory/search | read | One request per page |
| GET /v1/memory/list | read | None |
| POST /v1/memory/view | read | None |
| GET /v1/memory/export | read | None |
| PUT /v1/memory/update | update | One request per accepted update, including identical content |
| DELETE /v1/memory/delete | delete | None |
| GET /v1/memory/trash | read | None |
| GET /v1/memory/versions/{id} | read | None |
| GET /v1/memory/versions/{id}/{revision} | read | None |
| POST /v1/memory/restore | update | One request per accepted restore |
| GET /v1/memory/status/{memory_id} | read | None |
The grants are independent: create permission does not grant search or status access. A read-before-update workflow needs both read and update. Rate limits still apply to operations that are not counted as requests.
Shared Vault permissions
In a Vault you own, the key's permissions control the operation. In a shared Vault, the required permission must be granted both to the key and to your account's membership. For example, a key with read and create permissions can only read a shared Vault whose owner gave you read permission.
The Vault owner invites members and manages their permissions in the dashboard; an invitation gives access only after it is accepted. Sharing a Vault does not require sharing an API-key secret; each member uses a key from their own account.
Memory Identity
GET /v1/memory/identity
List your account's reachable Vaults and inspect the key's permissions. This endpoint needs a valid key but no record permission, ignores the Vault-selection header and is not counted as a request. It still works when the account has no default Vault.
Python
import requests
response = requests.get(
"https://api.ragionex.com/v1/memory/identity",
headers={"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
)
response.raise_for_status()
data = response.json() JavaScript
const res = await fetch("https://api.ragionex.com/v1/memory/identity", {
headers: { "X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" }
});
if (!res.ok) throw new Error(await res.text());
const data = await res.json(); curl
curl -X GET https://api.ragionex.com/v1/memory/identity \
-H "X-API-Key: rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" {
"success": true,
"account_id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"key": {
"key_id": 1,
"label": "Example key",
"permissions": [
"read",
"create",
"update",
"delete"
]
},
"vaults": [
{
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"vault_name": "My vault",
"access": "owner",
"permissions": [
"read",
"create",
"update",
"delete"
],
"is_default": true
},
{
"vault_id": "cccccccccccccccccccccccccccccccc",
"vault_name": "Team notes",
"access": "shared",
"permissions": [
"read"
],
"is_default": false
}
]
} account_id is your account ID. key contains key_id, the current label and the key's fixed permissions. Every item in vaults contains vault_id, vault_name, access (owner or shared), effective permissions and is_default. Shared Vaults are never the account default. The list can be empty; identity does not itself choose a Vault.
Memory Write
POST /v1/memory/write
Store text in the selected Vault. New content is processed in the background before it becomes searchable; use status polling to check progress.
https://api.ragionex.com/v1/memory/write
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
content | string | required | The text to save, stored unchanged. It must contain a non-whitespace character and fit the Vault owner's content limit. Empty, null and whitespace-only content are invalid. Extra body fields are rejected. |
Idempotency-Key is an optional request header, not a body field. It accepts 1–128 ASCII letters, digits, dots, underscores, colons or hyphens.
The example token names one save operation. Choose a fresh token for each new operation, and retain the same token and original content when retrying an uncertain save. The token is scoped to your account, across its keys, and its first acceptance binds it to one Vault. A matching retry checks your current create access to that original Vault, even if the default or supplied Vault header changes.
Example Request
Python
import requests
response = requests.post(
"https://api.ragionex.com/v1/memory/write",
headers={
"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"Idempotency-Key": "save-preference-001"
},
json={
"content": "User prefers TypeScript over JavaScript. Always use strict mode and explicit types."
}
)
response.raise_for_status()
data = response.json()
print(f"Memory ID: {data['id']}") JavaScript
const res = await fetch("https://api.ragionex.com/v1/memory/write", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"Idempotency-Key": "save-preference-001"
},
body: JSON.stringify({
content: "User prefers TypeScript over JavaScript. Always use strict mode and explicit types."
})
});
if (!res.ok) throw new Error(await res.text());
const data = await res.json(); curl
curl -X POST https://api.ragionex.com/v1/memory/write \
-H "Content-Type: application/json" \
-H "X-API-Key: rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Idempotency-Key: save-preference-001" \
-d '{
"content": "User prefers TypeScript over JavaScript. Always use strict mode and explicit types."
}' Response
{
"success": true,
"id": "mem_K7X2P9Q4R1",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"created_at": "2024-04-12T00:00:00Z",
"updated_at": "2024-04-12T00:00:00Z",
"status": "processing",
"revision": 1,
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
} Repeated identical content in the same Vault returns the existing record's metadata without starting another processing job, even without an Idempotency-Key. Content is compared exactly, including case and whitespace. An edit removes that record from this original-save duplicate check, so a later write can create a new record.
A matching Idempotency-Key replay returns the accepted record's current metadata, including its Vault ID, status, revision and creator/editor account IDs, without content. It does not restore the original content if the record has since been edited. The retry body must still contain the content originally accepted for that token.
Using the token with different content returns HTTP 409 with idempotency_mismatch. Once a record accepted for the token has been deleted, a valid replay request returns HTTP 410 with record_deleted, even if its content differs. It does not recreate the record. A quota refusal does not accept a record.
Each accepted duplicate save or matching replay counts as one request; create permission, validation and minute limits still apply. Their returned status may already be ready or failed.
Memory Search
POST /v1/memory/search
Search records in the selected Vault. Only records with status: "ready" are included in search results.
https://api.ragionex.com/v1/memory/search
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | yes | One complete question, 5–512 characters after trimming. Send separate needs as separate requests. Send the same question on every page. |
cursor | string | later pages | The previous page's next_cursor, copied unchanged. It is opaque; do not build or edit it. |
start_date | string or integer | optional | Inclusive lower bound on record creation time. Prefer the ISO 8601 forms below. Search also accepts a bounded integer UTC Unix timestamp. Send the same value on every page. |
end_date | string or integer | optional | Inclusive upper bound on record creation time. Must be on or after start_date after conversion. Send the same value on every page. |
Search page size is fixed at 10. Do not send results, limit or queries. Extra body fields return HTTP 422.
Search returns up to 10 ready records with full content and all nine record fields. The response contains results and next_cursor. A string means another page is available; null means the search is complete. A search has at most 10 pages.
For the next page, send the same question, date filters and Vault header again, plus the returned value as cursor. Read access is checked again for every page. Each later page reflects current records and never repeats a record this search already returned; a newly ready record may appear later. A malformed cursor returns 400 invalid_cursor without a charge.
Every page counts as one request, including a successful empty page. Sending an earlier cursor again searches that page again against current records and counts as another request. When the usage period has no request left, the whole page is refused; server-side search failures give the request back.
Creation-date filters
For search and list, use YYYY-MM-DD or an ISO 8601 datetime such as 2024-04-12T10:00:00Z. A bare start date means 00:00:00 UTC; a bare end date means 23:59:59 UTC. Datetimes can carry an offset, which is converted to UTC. A datetime without a timezone is treated as UTC. Fractional seconds are reduced to whole seconds.
Date strings are limited to 40 characters before trimming. Empty or whitespace-only strings omit the bound; a JSON null also omits it in search. Converted timestamps must be between 1970-01-01T00:00:00Z and 2200-01-01T23:59:59Z, inclusive. Integer search bounds use the same range, from 0 to 7258204799. Send ISO strings, not integer strings, in list query parameters.
The filters use creation time, not edit time or a date mentioned inside content. If both bounds are present, end_date must be greater than or equal to start_date. Date validation failures return HTTP 422. For example, a reversed range reports end_date must be >= start_date; an out-of-range start reports start_date: must be between 1970-01-01 and 2200-01-01.
Writing search questions
Ask one focused, complete question about saved content. Send separate needs as separate requests. Use the date fields only when you want to restrict when records were created.
user language |
What programming language does the user prefer? |
For browsing without a topic, use list. Check returned content before using it as context; a returned record is not a guarantee that the requested fact was saved.
Example Request
Python
import requests
response = requests.post(
"https://api.ragionex.com/v1/memory/search",
headers={"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
json={"query": "What programming language does the user prefer?"}
)
response.raise_for_status()
data = response.json() JavaScript
const res = await fetch("https://api.ragionex.com/v1/memory/search", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
body: JSON.stringify({query: "What programming language does the user prefer?"})
});
if (!res.ok) throw new Error(await res.text());
const data = await res.json(); curl
curl -X POST https://api.ragionex.com/v1/memory/search \
-H "Content-Type: application/json" \
-H "X-API-Key: rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{"query": "What programming language does the user prefer?"}' if data["next_cursor"] is not None:
response = requests.post(
"https://api.ragionex.com/v1/memory/search",
headers={"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
json={
"query": "What programming language does the user prefer?",
"cursor": data["next_cursor"]
}
)
response.raise_for_status()
data = response.json() Response
{
"success": true,
"results": [
{
"id": "mem_K7X2P9Q4R1",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"content": "User prefers TypeScript over JavaScript. Always use strict mode and explicit types.",
"created_at": "2024-04-12T00:00:00Z",
"updated_at": "2024-04-12T00:00:00Z",
"status": "ready",
"revision": 1,
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
],
"next_cursor": null
} {
"success": true,
"results": [],
"next_cursor": null,
"message": "No matching memories found. A recently written memory may still be processing (check /v1/memory/status/{id}); otherwise try rephrasing your question."
} {
"success": true,
"results": [],
"next_cursor": null
} An empty result is a successful search, not an API error. Check a recently accepted record's status before treating it as missing. The error reference covers quota refusals and search outages.
Memory List
GET /v1/memory/list
List one page of records in the selected Vault, newest first. Rows use the same nine record fields; content contains the first 200 characters without an added ellipsis. Processing and failed records are included. Use view for full content before replacing a record.
https://api.ragionex.com/v1/memory/list
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | optional | Page size from 1 to 100. Default: 50. |
cursor | string | optional | The previous page's next_cursor, unchanged. Omit for the first page. Maximum length: 128 characters. |
start_date | string | optional | Inclusive lower creation-time bound. Uses the shared date rules. |
end_date | string | optional | Inclusive upper creation-time bound. Uses the shared date rules. |
Example Request
Python
import requests
response = requests.get(
"https://api.ragionex.com/v1/memory/list",
headers={"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
params={"limit": 50}
)
data = response.json() JavaScript
const res = await fetch("https://api.ragionex.com/v1/memory/list?limit=50", {
headers: {
"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
});
const data = await res.json(); curl
curl -X GET "https://api.ragionex.com/v1/memory/list?limit=50" \
-H "X-API-Key: rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" Response
{
"success": true,
"memories": [
{
"id": "mem_K7X2P9Q4R1",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"content": "User prefers TypeScript over JavaScript. Always use strict mode and explicit types.",
"created_at": "2024-04-12T00:00:00Z",
"updated_at": "2024-04-12T00:00:00Z",
"status": "ready",
"revision": 1,
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
{
"id": "mem_A1B2C3D4E5",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"content": "Project uses PostgreSQL for the main database with connection pooling.",
"created_at": "2024-04-11T23:00:00Z",
"updated_at": "2024-04-11T23:00:00Z",
"status": "processing",
"revision": 1,
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
],
"next_cursor": null
} next_cursor is a string when another page exists, otherwise null. Pass the returned value as cursor with the same date filters. Do not send the literal string null. Keep the same account, selected Vault and date filters while paging; send the same Vault header on each page.
Order is creation time descending, then record ID descending for ties. A cursor marks a position, not a stored snapshot; concurrent changes can affect later pages. A malformed cursor returns HTTP 400 with invalid_cursor; a value longer than 128 characters fails validation with HTTP 422.
Only limit, cursor, start_date and end_date are supported query parameters. Select another Vault with X-Ragionex-Vault-Id, not an extra query parameter.
Memory View
POST /v1/memory/view
Retrieve full records by ID from the selected Vault, including processing and failed records. Supply 1–50 IDs. Results follow input order, with repeated IDs collapsed to their first occurrence. The array limit is checked before duplicates are removed.
If any ID is missing or belongs to another Vault, the whole request returns HTTP 404 with code not_found and a not_found_ids array. No partial record list is returned.
https://api.ragionex.com/v1/memory/view
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| ids | array | required | Array of 1–50 record IDs. Each ID contains 1–14 ASCII letters, digits or underscores. |
Example Request
Python
import requests
response = requests.post(
"https://api.ragionex.com/v1/memory/view",
headers={"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
json={
"ids": ["mem_K7X2P9Q4R1", "mem_A1B2C3D4E5"]
}
)
data = response.json() JavaScript
const res = await fetch("https://api.ragionex.com/v1/memory/view", {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
body: JSON.stringify({
ids: ["mem_K7X2P9Q4R1", "mem_A1B2C3D4E5"]
})
});
const data = await res.json(); curl
curl -X POST https://api.ragionex.com/v1/memory/view \
-H "Content-Type: application/json" \
-H "X-API-Key: rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{
"ids": ["mem_K7X2P9Q4R1", "mem_A1B2C3D4E5"]
}' Response
{
"success": true,
"memories": [
{
"id": "mem_K7X2P9Q4R1",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"content": "User prefers TypeScript over JavaScript. Always use strict mode and explicit types.",
"created_at": "2024-04-12T00:00:00Z",
"updated_at": "2024-04-12T00:00:00Z",
"status": "ready",
"revision": 1,
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
{
"id": "mem_A1B2C3D4E5",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"content": "Project uses PostgreSQL for the main database with connection pooling.",
"created_at": "2024-04-11T23:00:00Z",
"updated_at": "2024-04-11T23:00:00Z",
"status": "processing",
"revision": 1,
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
]
} {
"success": false,
"error": "Not found",
"code": "not_found",
"not_found_ids": [
"mem_A1B2C3D4E5"
]
} Memory Export
GET /v1/memory/export
Export all current live records in the selected Vault, with full content, as one streamed JSON document. No filters are supported; query parameters do not narrow or expand the export. This API export excludes trash and version history.
The signed-in owner's dashboard export includes all retained memory data across the Vaults the account owns, in separate memories, trash and versions arrays. Every entry contains full text. Trash adds deleted_at and expires_at; earlier versions add operation, restored_from_revision, expires_at and is_current, which is false. A version is identified by its record id and revision together. Empty sections are empty arrays.
https://api.ragionex.com/v1/memory/export
Example Request
Python
import requests
response = requests.get(
"https://api.ragionex.com/v1/memory/export",
headers={"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
)
data = response.json() JavaScript
const res = await fetch("https://api.ragionex.com/v1/memory/export", {
headers: {
"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
});
const data = await res.json(); curl
curl -X GET "https://api.ragionex.com/v1/memory/export" \
-H "X-API-Key: rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" Response
{
"generated_at": "2024-04-12T00:01:00Z",
"vaults": [
{
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"vault_name": "My vault",
"memories": [
{
"id": "mem_K7X2P9Q4R1",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"content": "User prefers TypeScript over JavaScript. Always use strict mode and explicit types.",
"created_at": "2024-04-12T00:00:00Z",
"updated_at": "2024-04-12T00:00:00Z",
"status": "ready",
"revision": 1,
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
},
{
"id": "mem_A1B2C3D4E5",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"content": "Project uses PostgreSQL for the main database with connection pooling.",
"created_at": "2024-04-11T23:00:00Z",
"updated_at": "2024-04-11T23:00:00Z",
"status": "processing",
"revision": 1,
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
}
]
}
],
"count": 2,
"complete": true
} The top-level fields are generated_at, vaults, count and complete; there is no success field. generated_at is an RFC 3339 UTC string. In the API export, each Vault has vault_id, vault_name and a memories array. Each memory has the nine public record fields. count is the total number of entries actually emitted across the Vaults.
Export includes processing, ready and failed live records. An empty Vault still has an empty memories array. Records are newest first within each Vault, with record ID descending for creation-time ties.
The trailing "complete": true marks a finished export. If it is missing or the JSON does not parse, discard the partial document and retry the export. An HTTP 200 by itself does not prove that the stream finished.
The export is not a frozen snapshot of concurrent edits. Avoid changing records during export if you need a consistent account copy. The export limit (3 per hour, one at a time per account) applies even though exports are not counted as requests.
Memory Update
PUT /v1/memory/update
Replace a record's complete content using the revision returned by a read or search. A changed record returns to processing and is excluded from search until ready again. The request body has exactly these required fields:
https://api.ragionex.com/v1/memory/update
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
id | string | required | The record ID in this Vault, containing 1–14 ASCII letters, digits or underscores. |
expected_revision | integer | required | The revision you read, at least 1. Numeric strings and booleans are not accepted. |
content | string | required | Complete replacement text, including details you want to keep. It must not be empty, null or whitespace-only, and must fit the Vault owner's content limit. |
Missing required fields or extra body fields return HTTP 422. A missing record returns HTTP 404. A stale expected_revision returns HTTP 409 with code revision_conflict and changes nothing. Read the current record, reconsider the edit, then submit its revision if the change still belongs.
Example Request
Python
import requests
response = requests.put(
"https://api.ragionex.com/v1/memory/update",
headers={"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
json={
"id": "mem_K7X2P9Q4R1",
"expected_revision": 1,
"content": "User now prefers Python over TypeScript for data science projects."
}
)
data = response.json() JavaScript
const res = await fetch("https://api.ragionex.com/v1/memory/update", {
method: "PUT",
headers: {
"Content-Type": "application/json",
"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
body: JSON.stringify({
id: "mem_K7X2P9Q4R1",
expected_revision: 1,
content: "User now prefers Python over TypeScript for data science projects."
})
});
const data = await res.json(); curl
curl -X PUT https://api.ragionex.com/v1/memory/update \
-H "Content-Type: application/json" \
-H "X-API-Key: rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{
"id": "mem_K7X2P9Q4R1",
"expected_revision": 1,
"content": "User now prefers Python over TypeScript for data science projects."
}' Response
{
"success": true,
"id": "mem_K7X2P9Q4R1",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"created_at": "2024-04-12T00:00:00Z",
"updated_at": "2024-04-12T00:01:00Z",
"status": "processing",
"revision": 2,
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
} An accepted content change increases revision by 1 and updates updated_at. It counts as one request for the caller's account, keeps created_by and the creation time, and sets updated_by to the caller's account ID. Content is compared exactly, including case and whitespace.
The previous revision remains restorable for 30 days after replacement. There is no version count cap. Restoring an older version creates the next revision and keeps the other retained versions; it never moves the revision number backward.
With the current revision, identical content counts as one request but does not change timestamps, revision or status or restart processing. A stale revision is rejected even if the supplied content happens to match. To retry a failed record's processing, change its content.
Updates do not use Idempotency-Key replay. If the response is lost, read the record before deciding whether another update is needed. Do not blindly repeat an update with a new revision.
{
"success": false,
"error": "The record changed. Read it again before updating.",
"code": "revision_conflict"
} Memory Delete
DELETE /v1/memory/delete
Move one or more memories to trash for 30 days. Trashed records disappear from normal search, list, view and API-key export. They remain in the owner's dashboard export until their retention period ends. Restore them from the trash or the dashboard before that deadline.
https://api.ragionex.com/v1/memory/delete
Request Body
| Parameter | Type | Required | Description |
|---|---|---|---|
| ids | array | required | Array of 1–50 record IDs. Each ID contains 1–14 ASCII letters, digits or underscores. |
Example Request
Python
import requests
response = requests.delete(
"https://api.ragionex.com/v1/memory/delete",
headers={"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"},
json={
"ids": ["mem_K7X2P9Q4R1"]
}
)
data = response.json() JavaScript
const res = await fetch("https://api.ragionex.com/v1/memory/delete", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
body: JSON.stringify({
ids: ["mem_K7X2P9Q4R1"]
})
});
const data = await res.json(); curl
curl -X DELETE https://api.ragionex.com/v1/memory/delete \
-H "Content-Type: application/json" \
-H "X-API-Key: rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{
"ids": ["mem_K7X2P9Q4R1"]
}' Response
{
"success": true,
"deleted": 1
} Repeated IDs are collapsed; deleted counts unique records. The 50-item request limit applies before that collapse. Every ID must exist in this Vault. If any is missing, the response is HTTP 404 with code not_found and not_found_ids; this request deletes none of the records.
Deleting an already-trashed ID returns the same missing-ID error. Deletion is not counted as a request and does not give back earlier requests. Replaying an earlier write token for a trashed record returns HTTP 410 rather than recreating it, even if that record is later restored. Only the Vault owner can permanently delete trashed records or empty the trash, through the dashboard. Deleting a Vault or account permanently removes its live records, history and trash.
{
"success": false,
"error": "Not found",
"code": "not_found",
"not_found_ids": [
"mem_A1B2C3D4E5"
]
} Memory Trash
GET /v1/memory/trash
Requires read permission. Returns unexpired trash in the selected Vault, newest deletion first. This operation is not counted as a request.
| Parameter | Type | Meaning |
|---|---|---|
limit | integer | 1–100, default 50. |
cursor | string | Previous next_cursor, up to 128 characters. Omit for the first page. |
The response contains success, memories and next_cursor. Each item has the nine record fields, status trashed, a 200-character content preview, deleted_at and expires_at. Times are RFC 3339 UTC. Order is deletion time descending, then ID descending. Read the item's revision through the version route for full content.
A cursor marks a position, not a frozen snapshot. Invalid cursors return 400 invalid_cursor. Saving equal content creates a new live record; it does not restore the trash.
Memory Versions
GET /v1/memory/versions/{id}
Requires read permission. Lists retained versions of a live or trashed record, newest revision first. limit is 1–100, default 25. Pass the previous next_cursor as cursor to continue. The cursor is a canonical positive decimal revision string, at most 16 characters, within the JavaScript safe-integer range. A missing or out-of-Vault ID returns 404 not_found. A trashed record whose retention deadline has passed returns 410 record_expired.
The response contains success, current_revision, versions and next_cursor. Each version has the nine record fields with preview content, plus the fields below. The current live version has no expiry; a replaced version expires 30 days after replacement. A trashed current version expires 30 days after deletion. Older versions keep their own deadlines.
| Field | Type | Meaning |
|---|---|---|
operation | string | create, update, delete or restore. |
restored_from_revision | integer or null | The source revision for a restore. |
expires_at | string or null | Restore deadline in RFC 3339 UTC; null for the current live version. |
is_current | boolean | Whether this item is the record's current revision. |
GET /v1/memory/versions/{id}/{revision}
Returns success, current_revision and one version with its full content. A revision is a positive safe integer. A missing or expired revision returns 404 version_not_found. A trashed record in an accessible Vault whose deadline has passed returns 410 record_expired. A missing or out-of-Vault ID returns 404 not_found.
Version status describes that saved revision. created_by identifies the original creating account; updated_by identifies the account responsible for that saved revision. These reads are not counted as requests. Normal search never returns history.
Memory Restore
POST /v1/memory/restore
Requires update permission. Restore a trashed record or an older retained version. Each accepted restore counts as one request for the caller's account.
| Field | Type | Meaning |
|---|---|---|
id | string, required | Record ID in this Vault. |
expected_revision | integer, required | Current record revision from trash or history. Use the current head, not the old version number. |
revision | integer or null, optional | Version to restore. Required for a live record; omit or use null to restore the last content of a trashed record. |
Both revision fields accept only JSON integers from 1 to 9007199254740991. Numeric strings and booleans are rejected. Only the optional revision field accepts null.
The acknowledgement contains success and the eight live record metadata fields, without content. Restoring version 10 while the head is 15 creates revision 16, labeled restored from version 10 in history. It keeps the record ID, original creation time and created_by, and sets updated_by to the restoring account ID. Restoring a delete event restores its content; it does not delete the record again.
A restored record enters processing and becomes searchable when processing succeeds. Restores share the update rate limit. Equal text in another live record does not block a restore or remove either record.
A stale expected_revision returns 409 revision_conflict. Reread history before deciding what to do. Choosing the current live revision returns 409 version_is_current. Omitting a version for a live record returns 400 revision_required. A missing or out-of-Vault ID returns 404 not_found. A trashed record whose retention deadline has passed returns 410 record_expired. A missing or expired version returns 404 version_not_found. With no request left in the usage period, a restore returns 402 quota_exceeded and changes nothing. A rejected restore is not counted. Extra body fields, invalid IDs and invalid integer types return 422. No Idempotency-Key replay applies to restore. If a reply is lost, read history instead of automatically repeating the request.
Memory Status
GET /v1/memory/status/{memory_id}
Check an accepted record's processing status in the selected Vault. The response contains exactly success, id, vault_id, status, revision, updated_at, created_by, updated_by and message. updated_at uses RFC 3339 UTC and falls back to creation time. This is a progress response, not a record. An unknown, trashed or out-of-Vault ID returns 404 not_found.
https://api.ragionex.com/v1/memory/status/{memory_id}
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| memory_id | string | required | Record ID containing 1–14 ASCII letters, digits or underscores. |
Example Request
Python
import requests
response = requests.get(
"https://api.ragionex.com/v1/memory/status/mem_K7X2P9Q4R1",
headers={"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}
)
data = response.json() JavaScript
const res = await fetch("https://api.ragionex.com/v1/memory/status/mem_K7X2P9Q4R1", {
headers: {
"X-API-Key": "rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
});
const data = await res.json(); curl
curl -X GET https://api.ragionex.com/v1/memory/status/mem_K7X2P9Q4R1 \
-H "X-API-Key: rgx_memory_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" Response
{
"success": true,
"id": "mem_K7X2P9Q4R1",
"vault_id": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"status": "ready",
"revision": 1,
"updated_at": "2024-04-12T00:00:00Z",
"created_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"updated_by": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"message": "This memory is processed and searchable."
} Status Values
| Status | Exact message | Action |
|---|---|---|
processing | This memory is being processed and becomes searchable when processing finishes. | Check again later, within the minute limit. |
ready | This memory is processed and searchable. | Search or read the record. |
failed | This memory could not be processed. Update its content to try again. | Stop polling. Read and change its content using its current revision if you want another attempt. |
Polling is not counted as a request. There is no promised completion time. A record ID belongs in this route; a locally queued MCP operation ID belongs in the connector's connection check.