# Quickstart > Get a key, send a fact, send the fact that supersedes it, wait for the send to complete, then recall as one user. ## Before the first call 1. Sign up for an account, or let your coding agent set Harny up with no account: it follows [harny.ai/auth.md](https://harny.ai/auth.md) and hands you a link to claim the app later. 2. Create an app key in the console. The app key is the secret your server sends with every call to prove the call is yours. It starts with `fsa_`. Store the value as `HARNY_APP_KEY`. The key value is shown once. 3. Send every call to `https://api.harny.ai/v1/memory` with two headers. `Authorization: Bearer $HARNY_APP_KEY` carries your app key. `X-Harny-User: ` names the person the memory belongs to, using the id your app already uses for that person. A user key (starts with `fsk_`) names its own user and needs no `X-Harny-User`. Call the API from your server. Do not put a key in a browser. ## Four calls The example sends two notes about one account, 175 days apart, then asks for the budget as of now. ```bash tab=cURL # 1. Send the fact at its original time. curl -X POST https://api.harny.ai/v1/memory/ingest \ -H "Authorization: Bearer $HARNY_APP_KEY" \ -H "X-Harny-User: demo-user" \ -H "Content-Type: application/json" \ -d '{ "id": "call-8820", "content": "Nadia confirmed the Acme pilot ships March 14. Budget is 32k.", "label": "Account review call", "timestamp": "2026-02-03T09:00:00Z" }' # 2. Send the fact that supersedes it. curl -X POST https://api.harny.ai/v1/memory/ingest \ -H "Authorization: Bearer $HARNY_APP_KEY" \ -H "X-Harny-User: demo-user" \ -H "Content-Type: application/json" \ -d '{ "id": "call-8821", "content": "Budget for the Acme pilot moved to 40k.", "label": "Email from Nadia", "timestamp": "2026-07-28T16:00:00Z" }' # 3. Poll the ingestionId from the last response until status is completed. curl https://api.harny.ai/v1/memory/ingest/$INGESTION_ID \ -H "Authorization: Bearer $HARNY_APP_KEY" \ -H "X-Harny-User: demo-user" # 4. Recall as one user. curl -X POST https://api.harny.ai/v1/memory/recall \ -H "Authorization: Bearer $HARNY_APP_KEY" \ -H "X-Harny-User: demo-user" \ -H "Content-Type: application/json" \ -d '{ "query": "what is the Acme pilot budget?", "identity": "demo-user", "level": "medium" }' ``` ```python tab=Python import os import time import requests BASE = "https://api.harny.ai/v1/memory" HEADERS = { "Authorization": f"Bearer {os.environ['HARNY_APP_KEY']}", "X-Harny-User": "demo-user", } # 1. Send the fact at its original time. requests.post(f"{BASE}/ingest", headers=HEADERS, json={ "id": "call-8820", "content": "Nadia confirmed the Acme pilot ships March 14. Budget is 32k.", "label": "Account review call", "timestamp": "2026-02-03T09:00:00Z", }) # 2. Send the fact that supersedes it. receipt = requests.post(f"{BASE}/ingest", headers=HEADERS, json={ "id": "call-8821", "content": "Budget for the Acme pilot moved to 40k.", "label": "Email from Nadia", "timestamp": "2026-07-28T16:00:00Z", }).json() # 3. Poll until this send is completed. while requests.get(f"{BASE}/ingest/{receipt['ingestionId']}", headers=HEADERS).json()["status"] != "completed": time.sleep(2) # 4. Recall as one user. print(requests.post(f"{BASE}/recall", headers=HEADERS, json={ "query": "what is the Acme pilot budget?", "identity": "demo-user", "level": "medium", }).json()) ``` ```typescript tab=TypeScript const BASE = "https://api.harny.ai/v1/memory"; const headers = { Authorization: `Bearer ${process.env.HARNY_APP_KEY}`, "X-Harny-User": "demo-user", "Content-Type": "application/json", }; const post = (path: string, body: unknown) => fetch(`${BASE}${path}`, { method: "POST", headers, body: JSON.stringify(body) }).then((r) => r.json()); // 1. Send the fact at its original time. await post("/ingest", { id: "call-8820", content: "Nadia confirmed the Acme pilot ships March 14. Budget is 32k.", label: "Account review call", timestamp: "2026-02-03T09:00:00Z", }); // 2. Send the fact that supersedes it. const receipt = await post("/ingest", { id: "call-8821", content: "Budget for the Acme pilot moved to 40k.", label: "Email from Nadia", timestamp: "2026-07-28T16:00:00Z", }); // 3. Poll until this send is completed. while ((await fetch(`${BASE}/ingest/${receipt.ingestionId}`, { headers }).then((r) => r.json())).status !== "completed") { await new Promise((r) => setTimeout(r, 2000)); } // 4. Recall as one user. console.log(await post("/recall", { query: "what is the Acme pilot budget?", identity: "demo-user", level: "medium", })); ``` The recall response: ```json { "asOf": "2026-07-29T00:00:00Z", "usedEvidenceTokens": 18, "results": [ { "id": "39d9d745-c9f4-4884-a602-e538def76815", "rank": 1, "occurredAt": "2026-07-28T16:00:00Z", "content": "Acme pilot budget: currently 40k.", "artifact": { "id": "39d9d745-c9f4-4884-a602-e538def76815", "kind": "observation", "occurredAt": "2026-07-28T16:00:00Z" }, "sources": [ { "sourceId": "call-8821", "occurredAt": "2026-07-28T16:00:00Z", "label": "Email from Nadia", "excerpts": [] } ] } ] } ``` ## Read the page Each result is one memory with `id`, `rank`, `occurredAt` and `content`. Its `artifact` carries the memory id, its `kind` and the date it happened. The `sources` array lists the data points the memory rests on, each with your `sourceId`, its date and its `label`. `usedEvidenceTokens` counts the tokens the kept results use. `level` sets the token budget: `low` is 8,000, `medium` 16,000, `high` 24,000 and `extra-high` 32,000. A send answers `202` with an `ingestionId` while it is still being processed. Poll `GET /v1/memory/ingest/{ingestionId}` until `status` is `completed`. If you recall before then, the response carries `pending`, which says how many of your sends are still queued. Send `queryTimestamp` with a recall to read as of an earlier time. Results that happened after it are dropped, so a read before July 28 sees the February value.