# What to send and how to split it
> The unit recall reads best, the size of one data point, the shape of its text, and the procedure for a historical load.
## The unit
One data point is one thing that happened. It is one piece of raw text plus its time. The unit of replacement and deletion is the data point. Send one `content` value per data point, and set `label` and `timestamp` for each one.
## Size
- `content`: at most 500,000 characters. It must be non-blank and must not contain U+0000.
- Batch: 1 to 1,000 items and at most 16 MiB of UTF-8 in total per batch request.
- `label`: at most 200 characters.
- `id`: at most 512 characters, with no `/`.
- `metadata`: a JSON object of at most 64 KiB when serialized.
`content` over the limit returns `413 content-too-large`. Any other field over its limit returns `400 invalid-ingestion`, and its `debugMessage` names the field.
## What the text looks like
The source can be a chat or thread, an email, a call transcript, a CSV row, a JSON record or a document. Cut a long source into parts, one thing that happened per part. A chat message looks like this:
```text
#support, 2026-04-02
Ana: The export is ready for review.
Ben: Thanks, sending it to the client now.
```
## Ids
The default `id` is the lowercase SHA-256 of `content`. Set your own `id` when you need to replace the data point later, because a send with the same `id` and changed content becomes a new revision.
For a long source split into parts, use `.` as the `id` of each part.
## Timestamps
Send `timestamp` in ISO 8601 with a zone, for example `2026-10-26T09:14:00+01:00`. Send the time the thing happened, not the time you send it. If you omit it, a resend keeps the stored value and a first send uses the current time. Recall returns it as `occurredAt` and filters on it with `queryTimestamp`, `occurredFrom` and `occurredTo`.
## Load old data
Use these steps to bring in data you already have, such as past emails, chats, call transcripts and documents. This is called a historical load.
1. Cut the old source into data points that follow the rules above.
2. Estimate the load with `POST /v1/memory/ingest/estimate`. It cuts and batches your files without sending them, so you see the batches before any data leaves your side.
3. Send the data points in batches with `POST /v1/memory/ingest/batch`. Set one `idempotencyKey` per batch. A retry with the same key and the same body returns the original receipt. A reused key with a different body returns `409 idempotency-conflict`.
4. Wait for the send to settle. Poll `GET /v1/memory/ingest/{ingestionId}`. `status` is `processing`, `failed` or `completed`. `settled` is true when nothing is queued. `blocked` is true when items are set aside after repeated failures and nothing is queued.
5. Verify the result with a recall, and check `readiness` and `failure`. For a refusal at item k, the batch error carries `data.accepted`. Send the rest again with the same `idempotencyKey` and body, and the send resumes at k. To re-run a send that stopped, call `POST /v1/memory/ingest/{ingestionId}/retry`.
## Corrections and deletion
- To correct a data point, send the same `id` with the new `content`. Harny deletes the memories built on the old text and then ingests the new text. Fields you leave out keep their stored values.
- To delete a send, call `DELETE /v1/memory/ingest/{ingestionId}`. It returns `204`.
- To delete one data point, call `DELETE /v1/memory/data-points/{sourceId}`. It returns `202`.
- To delete many, call `POST /v1/memory/data-points/delete` with up to 1,000 `ids`. A missing id returns `404` and nothing is deleted.
- A deleted `id` sent again returns `409 data-point-deleted`.
Deleting a data point removes the memories the send created. Memories that existed before and were shared with it stay.