# Apps, data points, memories, audiences, users and traits > The five nouns of every call, the memories that recall returns, and every limit in one place. ## App An app is the isolation boundary. An app key selects the app, and the app holds its own data points, memories and audiences. The app key starts with `fsa_`. Send it as `Authorization: Bearer $HARNY_APP_KEY`. Responses that name the app return it in the `projectId` field. The value is the app id. The field name stays `projectId`. Usage is read with the app key only (`GET /v1/memory/usage`). ## Data point A data point is one piece of raw text and its time. It is the unit of replacement and deletion. | Field | Type | Limit | Meaning | |---|---|---|---| | `id` | string | no `/`, at most 512 characters | Source id. Defaults to the lowercase SHA-256 of `content`. Returned as `sourceId`. | | `content` | string | required, non-blank, no U+0000, at most 500,000 characters | The text to store. | | `label` | string | at most 200 characters | A short label for the data point. | | `timestamp` | string | ISO 8601 with a time zone | When the content happened. Defaults to the stored value, else now. | | `metadata` | object | JSON object, at most 64 KiB serialized | Free-form metadata. | | `audience` | string | omitted or `project` only | Audience slug. Other values return `400 audience-unknown`. | | `identity` | string | at most 200 characters | The user this data point is for. | | `idempotencyKey` | string | at most 200 characters | Makes a retry safe. See Idempotency below. | An unknown field returns `400 invalid-ingestion`. Send a data point with `POST /v1/memory/ingest`. It returns `202` with `status: "queued"`, or `200` with `status: "completed"` and `unchanged: true` when the content, label, metadata and timestamp match the stored data point. Sending the same `id` with 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, and that resend counts as a change. A deleted `id` that is sent again returns `409 data-point-deleted`. ## Memory A memory is a short statement derived from a data point. It keeps a link to the data points it rests on. Memories are created when a data point is ingested. Deleting a data point deletes the memories that the send created. A send that created none, because its text overlapped existing facts, leaves existing memories in place. Recall returns memories as `results`. Each result has an `id`, a `rank`, an `occurredAt`, the `content`, an `artifact` object and a `sources` list. ## Audience An audience is a named group of users in an app. Audience kinds are `fixed`, `rule` and `default`. A `fixed` audience names its users. A `rule` audience matches all or any of 1 to 20 trait conditions. You choose the match mode. Every data point goes to the `project` audience, which is the default and holds every user. The `audience` field on a data point takes only `project` or nothing, so a group you create does not yet limit who reads a data point. Use one app for each customer whose memory must stay apart. Create, read, replace, delete and recompute audiences by slug with `/v1/memory/audiences`. The [API reference](/docs/memory-api/api-reference) lists each route. [Access control](/docs/memory-api/access-control) shows how to keep customers apart. ## User A user is the person whose memory is read or written. The API field is `identity`. For a recall, the user is the person the answer is given as. Requests that use an app key must name the user in the `X-Harny-User: ` header. A user key (starts with `fsk_`) names its own user and needs no `X-Harny-User` header. A body `identity` cannot select a different user. If you send one, it must equal the acting user's identifier or id. Otherwise the API returns `403 identity-mismatch`. ## Trait A trait is a string attribute of a user. The key can be up to 200 characters. The value can be up to 2,000 characters. Set traits when you create or update a user with `/v1/memory/identities`. Audience rules match on them. ## Metadata `metadata` on a data point is a JSON object of up to 64 KiB when serialized. Recall returns it in each result's `sources[].metadata`. ## What recall returns for a user `POST /v1/memory/recall` answers as the user named by `identity`, or by the `X-Harny-User` header. Request fields: `query` (required), `identity` (required), `limit` (1 to 200, default 100), `level` (`low` 8,000 default, `medium` 16,000, `high` 24,000, `extra-high` 32,000) or `maxTokens` (never both; floor 256), `queryTimestamp`, `occurredFrom`, `occurredTo` (inclusive), `sort` (`relevance` default, or `chronological`). Response fields: `asOf`, `usedEvidenceTokens`, `results[]` (`id`, `rank`, `occurredAt`, `content`, `artifact{id, kind, occurredAt, supersededAt}`, `sources[]{sourceId, occurredAt, label, metadata, excerpts}`), and `pending` while the user has queued items. `queryTimestamp` removes results that occurred later. Unknown times are kept. `occurredFrom` and `occurredTo` keep only results inside the window, and unknown times are dropped. `occurredFrom` after `occurredTo` returns `400 recall-range-invalid`. `excerpts` is always `[]`. `kind` is always `observation`. ## Limits | Limit | Value | |---|---| | `content` | at most 500,000 characters | | `label` | at most 200 characters | | `id` | at most 512 characters | | `metadata` | at most 64 KiB serialized | | `identity` | at most 200 characters | | `idempotencyKey` | at most 200 characters | | Batch items | 1 to 1,000 per batch | | Batch size | at most 16 MiB UTF-8 in total | | Trait key | at most 200 characters | | Trait value | at most 2,000 characters | | Audience rule conditions | 1 to 20 | | Recall `limit` | 1 to 200 (default 100) | | Recall `level` | low 8,000 (default), medium 16,000, high 24,000, extra-high 32,000 | | Recall `maxTokens` | floor 256 | | Delete ids (bulk) | 1 to 1,000 | A call over the per-minute limit returns `429` with an empty body and a `Retry-After` header. Rates and allowances per person and per app are on the [Limits](/docs/memory-api/limits) page.