Memory API

How requests behave

Acceptance, completion, replacement, recall and deletion, as your application observes them.

Copy page
View as Markdown

Completion status

A send moves through processing, completed, or failed on GET /v1/memory/ingest/{ingestionId}. The status field reports processing while any item waits in the retry queue, failed if any item is set aside after repeated failures, and completed otherwise.

The response also carries settled and blocked:

  • settled is true when the raw, comprehension, and consolidation counters are 0 and failed is 0.
  • blocked is true when those three counters are 0 and failed is above 0.

The readiness object reports four counters for the user's whole space:

  • raw: queued, no attempt yet.
  • comprehension: queued with an attempt.
  • consolidation: always 0.
  • failed: set aside after repeated failures.

The failure field is null, or an object {code, message} with one of these codes: content-rejected (too large or permanent), model-unavailable (extraction exhausted), index-unavailable (transient exhausted), or internal.

Read failure.code to choose the next step. model-unavailable and index-unavailable are temporary: call POST /v1/memory/ingest/{ingestionId}/retry. content-rejected needs a change to the data point. internal goes to support with the X-Request-Id.

Source replacement

Send the same id again to replace a data point:

  • An identical body returns 200 with unchanged: true.
  • Any change creates a new revision. Harny deletes the memories built on the old revision, then ingests the new text. Fields you leave out of the resend keep their stored values.
  • If the new text is refused, the data point has no memories until you send it again. That resend counts as a change.
  • Sending an id that was deleted returns 409 with data-point-deleted.

Idempotency keys

An idempotency key is a label you choose for one send. If the same send arrives twice, Harny stores it once, so it is safe to retry after a timeout.

Send idempotencyKey (at most 200 characters) with POST /v1/memory/ingest or POST /v1/memory/ingest/batch. A key is scoped to the app and user, and keys never expire.

  • The same key with the same body returns the original receipt and original status code. Nothing new starts, including while the first request is still running. A claim still processing after 5 minutes is resumed.
  • The same key with a different body returns 409 with idempotency-conflict.

An omitted timestamp is not included in the hash, so a retry hashes the same.

Retries

A batch that is refused partway keeps the items accepted before the refusal. The error includes data: {ingestionId, accepted: k}. Retry with the same idempotencyKey and body to resume at item k.

To re-run a send that stopped, call POST /v1/memory/ingest/{ingestionId}/retry. A retry is free.

Point in time

Recall accepts three parameters:

  • queryTimestamp drops results whose occurredAt is later. Results with unknown time are kept. asOf echoes queryTimestamp, or the current time if it is omitted.
  • occurredFrom and occurredTo (inclusive) keep only results inside the window. Results with unknown time are dropped.

These are filters over the assembled result, not retrieval restrictions. occurredFrom later than occurredTo returns 400 with recall-range-invalid.

User and audience

Name the person with the X-Harny-User: <user> header on app-key calls (fsa_). A user key (fsk_) names its own user and needs no X-Harny-User header.

A body identity never selects the user. If you send one, it must match the acting user, or the call returns 403 with identity-mismatch.

audience accepts only the omitted value or project. Any other value returns 400 with audience-unknown.

Request ids

Every response carries an X-Request-Id header. Error bodies have the shape {code, status, debugMessage, data}, with data null unless given.

Health

GET https://api.harny.ai/health returns {"status": "ok"} with no key. Use it for a liveness check.

Limits and the meter

Harny meters monthly-active end users. The first 500 in your active app are free for good. A user counts in a month when they used the app that month. Pricing lists the plans.

Batch ingestion accepts up to 1,000 items and 16 MiB of UTF-8 in total. Each item in a batch counts against your quotas on its own. GET /v1/memory/usage reports the current month's count.

A call over the per-minute limit returns 429 with an empty body and a Retry-After header.