--- title: "Quickstart" description: "Get a key, send a fact, send the fact that supersedes it, wait for the send to complete, then recall as one identity." canonical: https://past.dev/docs/memory-api/quickstart last-updated: 2026-10-09 --- # Quickstart > Get a key, send a fact, send the fact that supersedes it, wait for the send to complete, then recall as one identity. Product: past.dev Memory API. Source: https://past.dev/docs/memory-api/quickstart ### Before the first call 1. Sign up at https://sso.past.dev/sign-up, or sign in at https://app.past.dev. Sign-up needs no approval and starts with 150,000 credits, 400,000 with a work email. A new organization has one project, `default-project`, with no data points. 2. Pick the project in the header. Every key, audience and data point belongs to the project shown there. 3. Open API keys, create a key, and store it in your secret store as `PAST_API_KEY`. The console can reveal it again. ### Four calls - **Base URL**: `https://api.past.dev/api/v1` - **Auth**: `Authorization: Bearer $PAST_API_KEY` **cURL** ```curl # 1. Send the fact at its original time. curl -X POST https://api.past.dev/api/v1/ingest \ -H "Authorization: Bearer $PAST_API_KEY" \ -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.past.dev/api/v1/ingest \ -H "Authorization: Bearer $PAST_API_KEY" \ -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.past.dev/api/v1/ingest/7d9f2b6a-4c1e-4f8a-9b3d-2e5c8a1f6d40 \ -H "Authorization: Bearer $PAST_API_KEY" # 4. Recall as one identity. curl -X POST https://api.past.dev/api/v1/recall \ -H "Authorization: Bearer $PAST_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "query": "What is the Acme pilot budget?", "identity": "demo-user", "level": "medium" }' ``` **Python** ```python import os import time import requests API = "https://api.past.dev/api/v1" HEADERS = { "Authorization": "Bearer " + os.environ["PAST_API_KEY"], "Content-Type": "application/json", } # 1. Send the fact at its original time. requests.post(API + "/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", }).raise_for_status() # 2. Send the fact that supersedes it. receipt = requests.post(API + "/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(API + "/ingest/" + receipt["ingestionId"], headers=HEADERS).json()["status"] != "completed": time.sleep(2) # 4. Recall as one identity. page = requests.post(API + "/recall", headers=HEADERS, json={ "query": "What is the Acme pilot budget?", "identity": "demo-user", "level": "medium", }).json() print(page["results"][0]["content"]) ``` **TypeScript** ```typescript const API = "https://api.past.dev/api/v1"; const headers = { Authorization: "Bearer " + process.env.PAST_API_KEY, "Content-Type": "application/json", }; const call = (path: string, init: RequestInit = {}) => fetch(API + path, { headers, ...init }).then((response) => response.json()); // 1. Send the fact at its original time. await call("/ingest", { method: "POST", body: JSON.stringify({ 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 call("/ingest", { method: "POST", body: JSON.stringify({ 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 call("/ingest/" + receipt.ingestionId)).status !== "completed") { await new Promise((resolve) => setTimeout(resolve, 2000)); } // 4. Recall as one identity. const page = await call("/recall", { method: "POST", body: JSON.stringify({ query: "What is the Acme pilot budget?", identity: "demo-user", level: "medium", }) }); console.log(page.results[0].content); ``` Poll `status` until it is `completed`. An accepted send is processed in the background, and its memory is readable once its status is `completed`. The `settled` flag in the same response describes every send in the project; [How it works](/docs/memory-api/how-it-works) defines both. The recall answers as `demo-user`. A data point sent without `audience` is visible to every identity of the project, so the identity can be any id. `audience` on a data point decides who reads it. See [Concepts](/docs/memory-api/concepts). ```200ok { "asOf": "2026-09-22T10: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": "9f74f854-d11d-4bc4-bf68-5b2012ac9c15", "kind": "claim", "occurredAt": "2026-07-28T16:00:00Z" }, "sources": [ { "sourceId": "call-8821", "occurredAt": "2026-07-28T16:00:00Z", "label": "Email from Nadia", "excerpts": [ "Budget for the Acme pilot moved to 40k." ] } ] } ] } ``` ### Read the page Each result is one document with `id`, `rank`, `occurredAt`, and `content`. Its `artifact` carries the memory id, kind, occurrence date, and optional `supersededAt`. `artifact.kind` is `source` for an original data point or the kind of the derived memory. The sibling `sources` array groups this document’s supporting quotations by canonical `sourceId` and source date, with optional `metadata` and `label` and quotation strings in `excerpts`. These groups describe the supporting evidence for this returned document. An artifact can have additional provenance beyond the returned evidence. Original source documents keep their body in `content` without repeating it as a quotation. Pass `content` to your model in `rank` order and cite `sources[].sourceId`. An empty `results` array means nothing the identity may read matched the query. Both Quickstart data points stay in memory, each with its date. The sample returns the July value, the current one. A read with `queryTimestamp` before July 28 sees the February value as the current one.