Memories

Developer·4 minutes to read

Verified against docs/superpowers/specs/2026-09-15-p4-a-typed-http-api-openapi-webhooks.md §4.3, §4.4, §5.2, §6; re-verified against the code at close-out.

What it does

A memory is a typed claim a bot reads back: a subject, what is claimed about it, how confident the claim is, and where it came from. These endpoints list, create, read, change and delete them (F-MEM-1 to F-MEM-7 — typed claim rows, the three scopes, the third-party limits, the style profile, consolidation, the knowledge base and versioning with the bot).

Authentication

An organisation API key. GET needs scope read or wider; the writes need write or wider. A memory written through this surface is recorded as the key's person, with provenance member and source api, and it is recalled under exactly the same rules as one typed in the app. Nothing here lets a bot write a memory: a bot's own memory writes stay on their own path (F-APR-6). See Authentication and keys.

Request

GET /memories

<!-- generated:begin GET /memories --> <!-- generated:end GET /memories -->

POST /memories

<!-- generated:begin POST /memories --> <!-- generated:end POST /memories -->

GET /memories/{id}

<!-- generated:begin GET /memories/{id} --> <!-- generated:end GET /memories/{id} -->

PATCH /memories/{id}

<!-- generated:begin PATCH /memories/{id} --> <!-- generated:end PATCH /memories/{id} -->

DELETE /memories/{id}

<!-- generated:begin DELETE /memories/{id} --> <!-- generated:end DELETE /memories/{id} -->

GET /memories takes an optional scope and an optional botId.

The product has three scopes — organisation, bot and member — and this API writes two of them. A create carries organisation or bot, and botId is required for a bot-scoped claim and refused for an organisation-scoped one. Member-scoped memory is a person's own and is not written from a script.

A claim's kind is up to 60 characters and its subject up to 200; the value is up to 4 000. subjectKind says whether the subject is a member, a third party or the organisation, and defaults to organisation; a third-party claim is the one to think twice about, because the product limits which kinds may be held about a person who is not a member. confidence is between 0 and 1 and defaults to 1. A PATCH names at least one of value, confidence, validTo and lawfulBasis.

curl -sS -X POST "$BOTSEON_API_ORIGIN/api/v1/memories" \
  -H "authorization: Bearer $BOTSEON_API_KEY" \
  -H "idempotency-key: 1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f" \
  -H "content-type: application/json" \
  -d '{"scope":"organisation","kind":"billing_contact","subject":"Accounts payable","subjectKind":"organisation","value":"Invoices go out on the last working day of the month."}'
const res = await fetch(
  `${process.env.BOTSEON_API_ORIGIN}/api/v1/memories?scope=organisation&limit=50`,
  {
    headers: {
      authorization: `Bearer ${process.env.BOTSEON_API_KEY}`,
      accept: 'application/json',
    },
  },
);
if (!res.ok) throw new Error(`memories: ${res.status}`);
const page = (await res.json()) as {
  data: Array<{ id: string; kind: string; subject: string; value: string; confidence: number }>;
  nextCursor: string | null;
};
for (const claim of page.data) console.log(claim.kind, claim.subject, claim.confidence);

Response

{
  "id": "3e4f5a6b-7c8d-4e9f-a0b1-c2d3e4f5a6b7",
  "scope": "organisation",
  "botId": null,
  "kind": "billing_contact",
  "subject": "Accounts payable",
  "subjectKind": "organisation",
  "value": "Invoices go out on the last working day of the month.",
  "confidence": 1,
  "validTo": null,
  "provenance": "member",
  "createdAt": "2026-09-18T08:00:00.000Z"
}

provenance says where the claim came from: member for one a person or their script wrote, run for one a bot wrote, import for one that arrived with a template, and run-tainted for one a tainted run proposed. A tainted run's memory write raises a card for a human rather than landing silently.

Errors

StatusCodeWhenWhat to do
401unauthenticatedThe credential is missing, refused, or below the scope the route needs.Use a write key for the writes.
400invalid_requestbotId is set on an organisation-scoped claim or missing on a bot-scoped one, a field is outside its bounds, a PATCH names no field, or the POST carries no Idempotency-Key.Read details.
404not_foundNo such memory in this organisation, or the bot is not visible to this key's person.List first.
403forbiddenThe claim is not this person's to write.Ask an admin.
429rate_limitedA bucket is full.Wait for Retry-After.

Rate limits

Every call on this page is counted against two one-minute buckets: 300 requests per key and 1 000 per organisation. A full bucket answers rate_limited with Retry-After: 60; wait that many seconds and retry. Failed authentication is counted separately, against the caller's address, so a working key's allowance is never spent by somebody else's bad credential. See Envelopes, errors, idempotency and paging.

Last verified against build c0f77aa.