Memory API

The Memory API keeps a set of facts for your account and applies them to a frozen open language model when you query it. Facts are added, corrected and removed without training. Every change is appended to a receipt chain for your account, which you can export and check with the Verification API or the open verifiers. Your facts are separate from those of every other account.

Limitations

  • Name the subject for reliable answers. A query that names the subject and relation of a stored fact (mode keyed) is answered from that fact. A relation worded differently from the stored one usually does not match: the service is set to avoid wrong answers rather than to catch paraphrases. When nothing is stored for the subject, the model answers as it would without the service.
  • Place addresses are exact keys. A fact can carry a place address such as home/kitchen/shelf. Lookup by address (mode address) is an exact match on the address and, when given, the relation. It does not interpret free text, does not match a similar or partial address, and abstains when nothing is stored at the address. Listing by prefix matches whole segments only.
  • Free-text questions are best effort. Mode natural looks for a stored subject named literally in the text and for the relation's words. It does not resolve paraphrases, synonyms, pronouns or misspellings, and every such response carries best_effort true. Use mode keyed or mode address when the answer matters.
  • Answer length. An answer can be up to 8 tokens of the model's vocabulary, which is usually a few words. Longer answers are refused with the code answer_too_long, and an answer the model cannot be made to produce is refused with answer_not_expressible, together with suggestions.
  • Completion prompts, not chat. Facts are applied when the model continues a prompt as given, with no chat template. A stored answer is not guaranteed to appear inside a chat-formatted conversation or after different wording, while the answer field of the response always gives the stored answer. Generation is greedy, so the same request gives the same output.
  • Output is unchanged where no fact applies. When no stored fact of the requesting account matches, the output is identical to the unmodified model, whatever this or any other account has stored. The proof endpoint shows this on the account's own facts.
  • Size of a knowledge base. An account holds up to the number of facts of its plan, at most 2,048. Larger knowledge bases are offered under an Organisation agreement after testing on the customer's data.
  • One fixed open model. The service runs one open model, Qwen/Qwen3-0.6B, with its weights unchanged, on CPU. It does not check whether a stored fact is true; the content of the facts is the customer's responsibility.
  • Typical response times. Storing or correcting a fact takes about one second. A keyed query without generation takes a few milliseconds, and generating a short answer takes under one second. Requests that use the model are processed one at a time, so times grow under load.
  • What the receipt chain proves. Every registration, correction and removal appends a receipt to the account's SHA-256 hash chain, which can be exported and checked with the open verifiers. The chain shows that the record was not altered after it was written; it does not show that the service did what a receipt says, and its timestamps come from the service's clock. A shortened or fully re-hashed chain is detected only against a head held by a second party.
  • What the signatures prove. Each receipt hash and each head statement is signed with the service's Ed25519 key, published at /keys. A signature stops someone who holds only the exported file from altering it unnoticed. It does not stop the holder of the signing key from rewriting the history, so keep a dated head statement with a second party when that matters.

GET /v1/memory/keys

Signing keys

The Ed25519 public key that signs receipt hashes and head statements.

Responses

200Success.
401Missing or invalid API key.
413Error codes: payload_too_large.
500Error codes: internal_error.

Example request

curl -X GET "https://api.qriton.com/v1/memory/keys" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "keys": [
    {
      "key_id": "4f0c2a9e71b3d856",
      "algorithm": "Ed25519",
      "public_key_hex": "a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1",
      "public_key_pem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n",
      "created_utc": "2026-11-14T09:00:00Z",
      "status": "active"
    }
  ],
  "signed": "Each receipt_hash (its 64 ASCII characters) and each head statement."
}

GET /v1/memory/facts

List facts

Lists the live facts of the account.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
413Error codes: payload_too_large.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X GET "https://api.qriton.com/v1/memory/facts" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "facts": [
    {
      "fact_id": "f0",
      "prompt": "The capital of Wakanda is",
      "subject": "Wakanda",
      "relation": "capital",
      "answer": "Rome",
      "address": "atlas/africa/wakanda",
      "target_ids": [
        21718
      ],
      "tokens": 1,
      "slot": 0,
      "receipt": "7aaaacb941d407c23e2a6be5183bcd63e06ed7ea9f491b55beaf861aeb647c23",
      "created_utc": "2026-11-14T10:15:02.418233Z",
      "updated_utc": "2026-11-14T10:15:02.418233Z"
    }
  ],
  "count": 1
}

POST /v1/memory/facts

Register a fact

Stores a fact in the frozen model and appends an inject receipt. The answer is screened first; a refusal writes nothing.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Request body (application/json)

FieldTypeDescription
prompt requiredstringThe text the answer follows, for example 'The capital of Wakanda is'.
answer requiredstringThe text that follows the prompt after one space. At most 8 tokens of the model's vocabulary.
subject requiredstring
relation requiredstring
addressstringA place address: 1 to 5 segments of lowercase letters, digits and hyphens, separated by slashes, for example home/kitchen/shelf. It is a key you choose; it is matched exactly and never interpreted.

Responses

201Success.
400Missing or invalid API key.
401Missing or invalid API key.
403Error codes: fact_limit_reached, subject_capacity_reached.
409Error codes: key_collision, address_taken.
413Error codes: payload_too_large.
422Error codes: validation_error, answer_not_expressible, answer_too_long, invalid_address.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X POST "https://api.qriton.com/v1/memory/facts" \
  -H "Authorization: Bearer $QRITON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt":"The capital of Wakanda is","answer":"Rome","subject":"Wakanda","relation":"capital","address":"atlas/africa/wakanda"}'

Example response

{
  "fact": {
    "fact_id": "f0",
    "prompt": "The capital of Wakanda is",
    "subject": "Wakanda",
    "relation": "capital",
    "answer": "Rome",
    "address": "atlas/africa/wakanda",
    "target_ids": [
      21718
    ],
    "tokens": 1,
    "slot": 0,
    "receipt": "7aaaacb941d407c23e2a6be5183bcd63e06ed7ea9f491b55beaf861aeb647c23",
    "created_utc": "2026-11-14T10:15:02.418233Z",
    "updated_utc": "2026-11-14T10:15:02.418233Z"
  }
}

GET /v1/memory/facts/{fact_id}

Get a fact

Returns one live fact.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.
fact_id requiredpathstring

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
404Error codes: fact_not_found.
413Error codes: payload_too_large.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X GET "https://api.qriton.com/v1/memory/facts/{fact_id}" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "fact": {
    "fact_id": "f0",
    "prompt": "The capital of Wakanda is",
    "subject": "Wakanda",
    "relation": "capital",
    "answer": "Rome",
    "address": "atlas/africa/wakanda",
    "target_ids": [
      21718
    ],
    "tokens": 1,
    "slot": 0,
    "receipt": "7aaaacb941d407c23e2a6be5183bcd63e06ed7ea9f491b55beaf861aeb647c23",
    "created_utc": "2026-11-14T10:15:02.418233Z",
    "updated_utc": "2026-11-14T10:15:02.418233Z"
  }
}

DELETE /v1/memory/facts/{fact_id}

Forget a fact

Removes the fact from memory and appends a forget receipt. Its earlier receipts are kept.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.
fact_id requiredpathstring

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
404Error codes: fact_not_found.
413Error codes: payload_too_large.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X DELETE "https://api.qriton.com/v1/memory/facts/{fact_id}" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "forgotten": "f0",
  "receipt": "c9ef98e55fb075d4c3b5921f98573f981072dd9f6607aeea9f90353e960b994b",
  "reverted_to_base": true
}

POST /v1/memory/facts/edit

Correct a fact

Replaces the answer of a live fact, optionally moving it to a new address, and appends an edit receipt.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Request body (application/json)

FieldTypeDescription
answer requiredstring
fact_idstring
addressstringA place address: 1 to 5 segments of lowercase letters, digits and hyphens, separated by slashes, for example home/kitchen/shelf. It is a key you choose; it is matched exactly and never interpreted.
relationstring
new_addressstringA place address: 1 to 5 segments of lowercase letters, digits and hyphens, separated by slashes, for example home/kitchen/shelf. It is a key you choose; it is matched exactly and never interpreted.

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
404Error codes: fact_not_found.
409Error codes: address_taken, address_ambiguous.
413Error codes: payload_too_large.
422Error codes: validation_error, answer_not_expressible, answer_too_long, invalid_address.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X POST "https://api.qriton.com/v1/memory/facts/edit" \
  -H "Authorization: Bearer $QRITON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fact_id":"f0","answer":"Paris"}'

Example response

{
  "fact": {
    "fact_id": "f0",
    "prompt": "The capital of Wakanda is",
    "subject": "Wakanda",
    "relation": "capital",
    "answer": "Paris",
    "address": "atlas/africa/wakanda",
    "target_ids": [
      12095
    ],
    "tokens": 1,
    "slot": 0,
    "receipt": "c9ef98e55fb075d4c3b5921f98573f981072dd9f6607aeea9f90353e960b994b",
    "created_utc": "2026-11-14T10:15:02.418233Z",
    "updated_utc": "2026-11-14T10:15:02.418233Z"
  }
}

POST /v1/memory/facts/forget

Forget a fact by id or address

Same as DELETE /facts/{fact_id}, but the fact may be named by its address.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Request body (application/json)

FieldTypeDescription
fact_idstring
addressstringA place address: 1 to 5 segments of lowercase letters, digits and hyphens, separated by slashes, for example home/kitchen/shelf. It is a key you choose; it is matched exactly and never interpreted.
relationstring

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
404Error codes: fact_not_found.
409Error codes: address_ambiguous.
413Error codes: payload_too_large.
422Error codes: validation_error, invalid_address.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X POST "https://api.qriton.com/v1/memory/facts/forget" \
  -H "Authorization: Bearer $QRITON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"address":"atlas/africa/wakanda","relation":"capital"}'

Example response

{
  "forgotten": "f0",
  "receipt": "c9ef98e55fb075d4c3b5921f98573f981072dd9f6607aeea9f90353e960b994b",
  "reverted_to_base": true
}

GET /v1/memory/places

List place addresses

Lists the addresses in use under a prefix, with their facts. The prefix matches whole segments: home/kitchen matches home/kitchen/shelf but not home/kitchenette.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.
prefixquerystring

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
413Error codes: payload_too_large.
422Error codes: invalid_address, validation_error.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X GET "https://api.qriton.com/v1/memory/places" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "prefix": "atlas/africa",
  "count": 1,
  "places": [
    {
      "address": "atlas/africa/wakanda",
      "facts": [
        {
          "fact_id": "f0",
          "relation": "capital",
          "subject": "Wakanda",
          "answer": "Rome"
        }
      ]
    }
  ]
}

POST /v1/memory/query

Query the memory

Looks up a fact by key (mode keyed: subject and relation), by place address (mode address: exact match, no text interpretation) or from free text (mode natural: best effort). With generate true the model continues the text, steered by the matched fact. When nothing matches, the output is bit-identical to the unmodified model.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Request body (application/json)

FieldTypeDescription
modestring: "keyed", "address", "natural"keyed: you give subject and relation (reliable). address: you give a place address and optionally the relation (reliable, exact). natural: the service looks for a stored subject in the text (best effort).
textstringPrompt to continue when generate is true; required in mode natural.
subjectstring
relationstring
addressstringA place address: 1 to 5 segments of lowercase letters, digits and hyphens, separated by slashes, for example home/kitchen/shelf. It is a key you choose; it is matched exactly and never interpreted.
generateboolean
max_new_tokensinteger
logits_hashbooleanReturn SHA-256 hashes of the first-position logits with and without memory, to check bit identity yourself.

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
409Error codes: address_ambiguous.
413Error codes: payload_too_large.
422Error codes: validation_error, invalid_address, text_required.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X POST "https://api.qriton.com/v1/memory/query" \
  -H "Authorization: Bearer $QRITON_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"mode":"keyed","subject":"Wakanda","relation":"capital","text":"The capital of Wakanda is","generate":true,"max_new_tokens":6}'

Example response

{
  "mode": "keyed",
  "best_effort": false,
  "route": {
    "subject": "Wakanda",
    "relation": "capital",
    "fired": true,
    "fact_id": "f0",
    "cosine": 1,
    "matched_prompt": "The capital of Wakanda is",
    "matched_answer": "Rome",
    "matched_address": "atlas/africa/wakanda"
  },
  "answer": "Rome",
  "prompt_used": "The capital of Wakanda is",
  "response": " Rome, and the capital of",
  "response_token_ids": [
    21718,
    11,
    323,
    279,
    6722,
    315
  ],
  "memory_applied_steps": 1
}

POST /v1/memory/proof/locality

Locality proof

Runs a positive control on one stored fact, then compares the logits with and without memory on near misses (a stored subject under another relation) and unrelated prompts.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
409Error codes: knowledge_base_empty.
413Error codes: payload_too_large.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X POST "https://api.qriton.com/v1/memory/proof/locality" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "model": "Qwen/Qwen3-0.6B",
  "facts_loaded": 3,
  "control": {
    "fact_id": "f0",
    "fired": true,
    "base_says": "a",
    "memory_says": "Rome",
    "output_changed": true
  },
  "rows": [],
  "identical": 4,
  "total": 4,
  "near_miss_total": 2,
  "near_miss_leaked": 0,
  "route_threshold": 0.93,
  "valid": true,
  "informative": true,
  "disclosures": []
}

POST /v1/memory/proof/tamper

Tamper demonstration

Verifies the account's chain, alters one receipt in a copy and shows that verification of the copy fails. Nothing stored is changed.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
409Error codes: not_enough_receipts.
413Error codes: payload_too_large.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X POST "https://api.qriton.com/v1/memory/proof/tamper" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "receipts": 3,
  "intact_verifies": true,
  "tampered_index": 1,
  "tampered_verifies": false,
  "first_problem": {
    "position": 1,
    "problem": "receipt_hash"
  },
  "detected": true
}

GET /v1/memory/receipts

List receipts

The account's receipts in order, each with its signature.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.
limitqueryinteger
offsetqueryinteger

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
413Error codes: payload_too_large.
422Error codes: validation_error.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X GET "https://api.qriton.com/v1/memory/receipts" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "receipts": [
    {
      "sequence": 0,
      "timestamp_utc": "2026-11-14T10:15:02.418233Z",
      "operation": "inject",
      "previous_hash": null,
      "payload": {
        "fact_id": "f0",
        "prompt": "The capital of Wakanda is",
        "subject": "Wakanda",
        "relation": "capital",
        "answer": "Rome",
        "target_id": 21718,
        "slot": 0,
        "address": "atlas/africa/wakanda"
      },
      "receipt_hash": "7aaaacb941d407c23e2a6be5183bcd63e06ed7ea9f491b55beaf861aeb647c23",
      "signature": "5d1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
      "key_id": "4f0c2a9e71b3d856"
    }
  ],
  "total": 1,
  "limit": 100,
  "offset": 0
}

GET /v1/memory/receipts/verify

Verify the chain

Recomputes every link of the account's chain and checks every signature.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
413Error codes: payload_too_large.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X GET "https://api.qriton.com/v1/memory/receipts/verify" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "valid": true,
  "links_valid": true,
  "receipts": 3,
  "head": "c9ef98e55fb075d4c3b5921f98573f981072dd9f6607aeea9f90353e960b994b",
  "first_problem": null,
  "signed_receipts": 3,
  "signatures_valid": true,
  "key_id": "4f0c2a9e71b3d856"
}

GET /v1/memory/receipts/export

Export the chain

The account's chain as JSON Lines in the published receipt-chain format (six fields per receipt), ready for the open verifiers. Signatures are not part of this file; they are listed by GET /receipts. The X-Chain-Head header carries the head hash.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
413Error codes: payload_too_large.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X GET "https://api.qriton.com/v1/memory/receipts/export" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

"{\"sequence\": 0, \"timestamp_utc\": \"2026-11-14T10:15:02.418233Z\", \"operation\": \"inject\", \"previous_hash\": null, \"payload\": {\"fact_id\": \"f0\", \"prompt\": \"The capital of Wakanda is\", \"subject\": \"Wakanda\", \"relation\": \"capital\", \"answer\": \"Rome\", \"target_id\": 21718, \"slot\": 0}, \"receipt_hash\": \"7aaaacb941d407c23e2a6be5183bcd63e06ed7ea9f491b55beaf861aeb647c23\"}\n"

GET /v1/memory/head

Signed head statement

A dated statement of the account's current chain head, signed with the service key. Keep a copy with a second party: only an earlier head held elsewhere reveals a rewritten or shortened chain.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
413Error codes: payload_too_large.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X GET "https://api.qriton.com/v1/memory/head" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "statement": {
    "type": "memory-chain-head",
    "version": 1,
    "tenant": "acc_3f9a1c0b7d2e4a51",
    "receipts": 3,
    "head": "c9ef98e55fb075d4c3b5921f98573f981072dd9f6607aeea9f90353e960b994b",
    "issued_utc": "2026-11-14T10:15:02.418233Z",
    "key_id": "4f0c2a9e71b3d856"
  },
  "algorithm": "Ed25519",
  "signature": "5d1c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
  "signed_bytes": "the statement serialised with keys sorted, no whitespace and non-ASCII characters escaped, encoded as UTF-8"
}

GET /v1/memory/usage

Usage

Live facts, the fact limit in force, receipts and the chain head of the account.

Parameters

NameInTypeDescription
X-Tenant requiredheaderstringAccount identifier, set by the gateway.

Responses

200Success.
400Missing or invalid API key.
401Missing or invalid API key.
413Error codes: payload_too_large.
500Error codes: internal_error.
503Error codes: model_loading, model_unavailable.

Example request

curl -X GET "https://api.qriton.com/v1/memory/usage" \
  -H "Authorization: Bearer $QRITON_API_KEY"

Example response

{
  "tenant": "acc_3f9a1c0b7d2e4a51",
  "facts": 12,
  "fact_limit": 500,
  "receipts": 15,
  "chain_head": "c9ef98e55fb075d4c3b5921f98573f981072dd9f6607aeea9f90353e960b994b"
}