--- title: "Projects, data points, audiences, identities and traits" description: "The five nouns, what each one is for, and every limit in one table." canonical: https://past.dev/docs/memory-api/concepts last-updated: 2026-09-15 --- # Projects, data points, audiences, identities and traits > The five nouns, what each one is for, and every limit in one table. Product: past.dev Memory API. Source: https://past.dev/docs/memory-api/concepts A data point is what you send: one piece of text with the time it happened. A memory is a short statement past.dev derives from data points: a fact, a rule, a membership, a name or a dated event, kept with the excerpts that support it. A document is what a recall returns: a data point or a memory, with `excerpts`, the verbatim passages of the data points behind it, each carrying your `sourceId`. A result groups the documents of one memory; `artifactId` is that memory's id. A project holds all of them. An audience decides who can read a data point, an identity is the reader a recall answers as, and traits describe an identity. ### Project A project is the isolation boundary. A project key selects one project, so `projectId` is never sent in a request body. Data points, memory, audiences, identities and keys belong to exactly one project, and nothing crosses between projects. The console shows the current project in its header. Every project has one audience with the slug `project`. It reaches every identity of the project, and it is the scope of a data point sent without `audience`. Projects are created in the console or with `POST /api/v1/projects` and the management key. ### Data point A data point is one thing that happened, sent as raw text with the time it happened. It is the unit of replacement and of deletion. [Sending data](/docs/memory-api/sending-data) says how to cut a source into data points. | Field | What it is for | | --- | --- | | `id` (string) | Your stable id for this data point, unique in the project. Every response returns it as `sourceId`. A second send with the same id, content and audience changes nothing. Changed content replaces the data point and the memory derived from it. Supply it: when omitted, a hash of `content` is used, so a corrected text becomes a second data point. | | `content` (string, required) | The raw text, complete and unedited. Empty or whitespace-only content is refused. | | `timestamp` (ISO 8601) | When the thing happened. Every response returns it as `occurredAt`. When omitted, an existing id keeps its stored time and a new data point takes the send time. | | `label` (string) | A short title, stored with the data point. | | `metadata` (JSON) | Your own JSON, stored with the data point. Recall never filters on it. | | `audience` (string) | The slug of the audience that can read this data point. Omit it, or send `project`, for a data point every identity can read. | | `identity` (string) | Your id for the author of this data point. It creates the identity record on first sight and does not scope the data point. Set it only when the author is also a reader you want in the directory: every new value creates a record. The sample below sets it because Dana reads memory. | ```json { "id": "crm-note-8841", "content": "Renewal call with Acme. Sam asked for per-seat billing and a quote for 40 seats before month end.", "label": "Renewal call", "timestamp": "2026-04-03T14:00:00Z", "audience": "acme", "identity": "dana@example.com" } ``` ### Audience An audience is a named scope inside a project. Its slug, a short lowercase name used in URLs, is what a data point names in `audience`, and what a recall reaches through the identity. A slug has 2 to 40 characters: lowercase letters, digits and dashes, with a letter or digit at each end. Audiences are created on the Audiences screen of the console or with `PUT /api/v1/audiences/{slug}`. A data point that names a slug that does not exist is refused with `400 audience-unknown`. An audience you create has one of two kinds. A `fixed` audience lists the identity ids it reaches. A `rule` audience reaches every identity whose traits match its rule: `match` is `all` or `any`, over 1 to 20 conditions of the form trait, operator, values. The default audience `project` reports `kind` `default` on the wire. It reaches every identity, and it cannot be replaced or deleted. An audience whose list or rule names nobody holds memory that nobody can read until it names someone again. The memory of a deleted audience stays unreadable for good; the slug is free, and a new audience under that slug does not reach it. A change to a list, a rule or a trait applies to recall within a short window of seconds, and `POST /api/v1/audiences/{slug}/recompute` applies it now. A memory is never readable by more identities than the data points behind it: a reader must be able to read every data point a memory rests on. ```json { "kind": "rule", "name": "Acme", "rule": { "match": "all", "conditions": [ { "trait": "company", "operator": "is", "values": ["acme"] } ] } } ``` ### Identity An identity is your own id for a reader: a person, an agent or a service that calls recall. The id has 1 to 200 characters and is never generated by past.dev. Use a stable identifier your application already owns, such as an email address or a Slack user id. The same id is what every recall for that reader answers as. An identity record is created the first time the id is seen: in `identity` on a data point, in the list of a `fixed` audience, or through `PUT /api/v1/identities/{identity}`. A recall for an id that has no record reads project-visible memory only, and it never creates the record. `DELETE /api/v1/identities/{identity}` removes the record and its audience memberships. The memory stays. The Audiences screen of the console lists identities on its Identities tab. `origin` records how a record was created and never changes: `api` through the identity routes, `ingest` first seen on a data point, `audience` first named in a fixed list, `csv` a CSV import in the console, `console` created by hand in the console, `connector` a connected identity source. `lastSeenAt` is the time of the last data point or recall that carried the id, null until one does. ```json { "traits": { "company": "acme", "team": "sales" } } ``` ### Trait A trait is a string attribute of an identity: a key of 1 to 200 characters with one string value of up to 2,000 characters. Traits are written through the identity routes and the console, and audience rules match on them. `is`, `is_not`, `is_one_of`, `is_not_one_of` and `exists` match only an identity that has the trait; `does_not_exist` matches an identity without it, including one with no traits at all. - `is` and `is_not` take exactly one value. - `is_one_of` and `is_not_one_of` take 1 to 50 values. - `exists` and `does_not_exist` take no value. - `is_not` and `is_not_one_of` match only an identity that has the trait with another value. ### Metadata Metadata is your own JSON, stored with the data point. Recall has no metadata filter. Use an audience to decide who reads a data point, and use the identity to decide what a read reaches. When a re-send with the same `id` omits `metadata`, the stored value is kept. Six keys are reserved for the platform: `author`, `role`, `conversationId`, `sessionId`, `messageId` and `ordinal`. Every other key is stored as sent and has no meaning to the platform. ### What recall returns for an identity A recall names the identity it answers as. The read returns project-visible memory plus the memory of every audience the identity reaches, and nothing else. An identity reaches a `fixed` audience that lists it and every `rule` audience its traits match. `GET /api/v1/identities/{identity}` returns the slugs the identity reaches at that moment. A membership change reaches recall after a short window, so a read made in the seconds after the change can still use the previous membership. An id with no record reads project-visible memory only and raises no error, so validate the id on your side before the call. ### Limits | Limit | Value | | --- | --- | | Data points per batch | 1 to 1,000 | | Content per request | 16 MiB of UTF-8, single sends included | | Data point cut from a conversation | Under 16,000 characters per part; a longer source is split into parts, see Sending data | | Data point cut from a document | Under 32,000 characters per part | | Source id | Any non-blank string, trimmed; no length limit | | Identity id | 1 to 200 characters | | Trait key and value | Key 1 to 200 characters, value 1 to 2,000, one string per key | | Audience slug | 2 to 40 lowercase letters, digits and dashes, a letter or digit at each end | | Audience name | 1 to 200 characters | | Fixed audience list | No limit | | Rule | 1 to 20 conditions; 1 to 50 values for `is_one_of` and `is_not_one_of` | | Identities per bulk call | 1 to 1,000 | | Ids per delete call | 1 to 1,000 | | Recall `limit` | 1 to 200 documents, default 20. The page ends at `limit` or at `maxTokens`, whichever comes first. | | Recall `maxTokens` | Default 8,000 tokens, about four characters each. The evidence one recall returns is set by the plan; see the pricing page. | | Identity list page | 1 to 1,000, default 100 | | Idempotency key | Up to 200 characters, no expiry | | Project name | Up to 255 characters, at least two letters or digits | | Key name | 1 to 64 characters | | Credits | One per 350 bytes of content, at least one per data point; prices on the pricing page | | Requests per minute | Set by the plan; see the pricing page | | Projects per organization | Set by the plan; see the pricing page |