POST /v1/import takes a file, stores it, and hands it to a background worker that parses, chunks, embeds and links it. POST /v1/import/transcript does the same for a conversation where you only want one speaker’s contributions attributed to the subject.
Before you start
- A key with the
writescope. See Scopes. - The file on disk, or in memory as bytes.
- For a per-end-user product, the subject provisioned first. See One memory per end user.
The shortest call that works
What you can import
The contract publishes no maximum file size, so this site does not either. Chunk your own uploads if you have an unusually large archive, and watch the job rather than assuming.
If you are holding a string rather than a file, do not write it to a temp file to import it. Use
POST /v1/ingest instead, which takes JSON. See Ingesting content.Importing a transcript
A meeting transcript contains several people. You usually want one person’s thinking in the graph, not everyone in the room.target_speaker names whose turns are attributed to the subject. The rest of the file still informs the parse, it is just not recorded as the subject’s belief.
target_speaker is required on this route. Match the speaker label as it appears in the file.
Watching the job
Import returns 202 and nothing is in the graph yet. Poll until the job reaches a terminal status.job.completed instead of holding a loop open. See Reacting to change.
Import history
GET /v1/import returns the 20 most recent imports for the effective subject, newest first, as a flat array with no envelope.
nodesCreated and domainsDetected are null until the worker writes its result. completedAt is null until the job reaches a terminal status.
A row with status: "done" and nodesCreated: null should not happen, and is worth a support ticket with the request id.
After a large import
A big export creates a lot of nodes at once, and the layers built on top of those nodes are not instant. Identity extraction, the manifold, domains, insights and temporal phases are produced by a background cognition cycle that runs after the content lands. So the sequence a first-time developer actually sees is: import succeeds,POST /v1/retrieve starts returning sources, and GET /v1/recall/identity is still empty for a while longer. That is expected. See How a memory is made.
When it goes wrong
The job failed with a parse error
The job failed with a parse error
Corrupt files and embedding failures are terminal on the first attempt rather than retried, because retrying a file that cannot be parsed only burns the queue and delays everything behind it. Fix the file and import again.
errorMessage on the status response names the reason.A PDF imported successfully but retrieved nothing
A PDF imported successfully but retrieved nothing
The PDF probably has no text layer. Extraction reads embedded text, so a scanned document is a stack of images as far as the parser is concerned, and it produces no chunks. Run it through OCR first and import the result.
403 permission_denied
403 permission_denied
Either the key lacks
write, or the X-Exo-Subject value is not provisioned. Exo refuses an unknown subject selector rather than defaulting to the key owner, so an import can never silently land in the wrong person’s partition. See permission_denied.422 validation_error
422 validation_error
Usually a missing
file part, a hand-set Content-Type that broke the multipart boundary, or a missing target_speaker on the transcript route. The problem body’s errors[] names the field. See validation_error.I imported the same file twice
I imported the same file twice
Send an
Idempotency-Key next time and a retry returns the original job id. If duplicates already landed, forget the extra nodes with DELETE /v1/graph/nodes/{id}, which erases their content and tombstones the node. See Forgetting and portability.Next
Coding session history
A different shape of import: transcripts already on your disk.
Ingesting content
The JSON routes, for content you already hold as a string.