Import conversations
This guide shows how to send a conversation between a user and an assistant with
POST /v1/memories/import. Alvia reads the turns in order and forms memories from the facts in
the user’s turns; the assistant’s turns give them context. Use it at the end of a chat session, or
to bring past conversations into Alvia.
For endpoint schemas and status codes, use the API reference.
Import one conversation
Section titled “Import one conversation”curl https://api.alvia.ai/v1/memories/import \ -H "Authorization: Bearer $ALVIA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "occurred_at": "2026-10-02T11:15:00-07:00", "scope": { "organization_id": "acme", "user_id": "u_4821" }, "messages": [ { "role": "user", "content": "We moved to the Enterprise plan yesterday." }, { "role": "assistant", "content": "Got it. Where should invoices go now?" }, { "role": "user", "content": "Send invoices to ap@acme.example from now on." } ] }'import osimport requests
API_KEY = os.environ["ALVIA_API_KEY"]
conversation = [ { "role": "user", "content": "We moved to the Enterprise plan yesterday.", }, { "role": "assistant", "content": "Got it. Where should invoices go now?", }, { "role": "user", "content": "Send invoices to ap@acme.example from now on.", },]
response = requests.post( "https://api.alvia.ai/v1/memories/import", headers={"Authorization": f"Bearer {API_KEY}"}, json={ "occurred_at": "2026-10-02T11:15:00-07:00", "scope": {"organization_id": "acme", "user_id": "u_4821"}, "messages": conversation, }, timeout=30,)response.raise_for_status() # 202 Accepted, empty bodyconst conversation = [ { role: "user", content: "We moved to the Enterprise plan yesterday.", }, { role: "assistant", content: "Got it. Where should invoices go now?", }, { role: "user", content: "Send invoices to ap@acme.example from now on.", },];
const response = await fetch( "https://api.alvia.ai/v1/memories/import", { method: "POST", headers: { Authorization: `Bearer ${process.env.ALVIA_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ occurred_at: "2026-10-02T11:15:00-07:00", scope: { organization_id: "acme", user_id: "u_4821" }, messages: conversation, }), },);// 202 Accepted, empty bodyif (!response.ok) { throw new Error(`${response.status}: ${await response.text()}`);}package main
import ( "bytes" "encoding/json" "io" "log" "net/http" "os" "time")
type message struct { Role string `json:"role"` Content string `json:"content"`}
func main() { conversation := []message{ { Role: "user", Content: "We moved to the Enterprise plan yesterday.", }, { Role: "assistant", Content: "Got it. Where should invoices go now?", }, { Role: "user", Content: "Send invoices to ap@acme.example from now on.", }, } payload, err := json.Marshal(map[string]any{ "occurred_at": "2026-10-02T11:15:00-07:00", "scope": map[string]string{ "organization_id": "acme", "user_id": "u_4821", }, "messages": conversation, }) if err != nil { log.Fatal(err) } req, err := http.NewRequest(http.MethodPost, "https://api.alvia.ai/v1/memories/import", bytes.NewReader(payload)) if err != nil { log.Fatal(err) } key := os.Getenv("ALVIA_API_KEY") req.Header.Set("Authorization", "Bearer "+key) req.Header.Set("Content-Type", "application/json")
client := &http.Client{Timeout: 30 * time.Second} resp, err := client.Do(req) if err != nil { log.Fatal(err) } defer resp.Body.Close() // 202 Accepted, empty body if resp.StatusCode != http.StatusAccepted { body, _ := io.ReadAll(resp.Body) log.Fatalf("%s: %s", resp.Status, body) }}using System.Net.Http.Json;
var key = Environment.GetEnvironmentVariable("ALVIA_API_KEY");using var http = new HttpClient();http.Timeout = TimeSpan.FromSeconds(30);http.DefaultRequestHeaders.Authorization = new("Bearer", key);
var conversation = new[]{ new { role = "user", content = "We moved to the Enterprise plan yesterday.", }, new { role = "assistant", content = "Got it. Where should invoices go now?", }, new { role = "user", content = "Send invoices to ap@acme.example from now on.", },};
var response = await http.PostAsJsonAsync( "https://api.alvia.ai/v1/memories/import", new { occurred_at = "2026-10-02T11:15:00-07:00", scope = new { organization_id = "acme", user_id = "u_4821" }, messages = conversation, });response.EnsureSuccessStatusCode(); // 202 Accepted, empty bodyBecause occurred_at is October 2 in the user’s time zone, “yesterday” resolves to October 1, 2026.
Prepare the messages
Section titled “Prepare the messages”- Send the
userandassistantturns. Import takes the conversation itself, so leave outsystem,developerandtoolturns. - Keep the turns in order. Alvia reads them as one conversation.
- Import one conversation per request. The
occurred_atdate anchors every relative date in the conversation, so two chats from different days need two requests. - Name other speakers. Alvia reads a
userturn withoutspeakeras the words of the person the memories are about, and its memories keep the first person: the example above can form “We moved to the Enterprise plan yesterday (October 1, 2026).” Setspeakerto a name, such as"Dana Reyes", when someone else said it. Write other memories in that scope in the same voice, so a new fact reads like the memory it changes.
Request fields
Section titled “Request fields”| Field | Required | Description |
|---|---|---|
messages |
Yes | 1 to 500 turns, in order. |
messages[].role |
Yes | user or assistant. |
messages[].content |
Yes | 1 to 16,000 characters, with no run of more than 2,000 characters without a space. |
messages[].speaker |
No | Who said the turn, when it is not the person the memories are about. 1 to 128 characters, on one line, not starting with a space. |
occurred_at |
Yes | When the conversation took place. See Point-in-Time Reasoning and change over time. |
scope |
No | Who or what the memories are about. See Projects and scope. |
All messages together can hold up to 320,000 characters. Very long conversations import best split into sessions: send each as its own request.
Response
Section titled “Response”A successful import returns 202 with an empty body. The memories become readable once
formation finishes, in less than a minute; see
Accepted means queued for formation and
Read memories.
Alvia splits a long conversation into chunks. Each chunk uses one write from your monthly allowance, and each fact formed from a chunk uses one more. See Limits and allowances.
When the write allowance runs out partway through an import, Alvia imports the chunks that fit, in
order, and still returns 202; the chunks past the allowance are not imported. The response does
not say which part of the conversation was left out, so you cannot resume from where it stopped.
Check the remaining allowance in the dashboard before a large import, and
send long histories in smaller imports that your application tracks.
Retries
Section titled “Retries”- Validation is all-or-nothing: a request with an invalid turn returns
400and imports nothing, so a fixed request imports cleanly. Do not retry a400unchanged. - Retry only requests that failed: network errors,
5xxresponses and429responses, after the wait inRetry-After. A202means Alvia accepted the import, so do not send it again. When you retry, send the same messages andoccurred_at. Each accepted request uses writes. See Retries in Store memories.
Errors
Section titled “Errors”| Error | Cause |
|---|---|
400 validation_error |
A field breaks a rule. errors names it, such as messages[2].role. |
400 invalid_argumentmessage_too_large_to_process |
One message is too large to process. Shorten it. |
400 invalid_argumentconversation_too_large_to_process |
The conversation is too large for one request. Split it. |
401 unauthorized |
The API key is missing or not valid. |
404 not_found |
The project’s deletion started while the request was in progress. |
409 conflictmemory_limit_reached |
The account holds its plan’s stored-memory limit. |
429 rate_limit_exceeded |
Too many requests per second. |
429 rate_limit_exceededmonthly_write_quota_reached |
The monthly write allowance is used up. |
See Errors for every code.
Filter sensitive information before imports
Section titled “Filter sensitive information before imports”Set the project’s memory policy before the import, with keyword exclusions and a meaning rule for PII or health disclosures that your application must not remember. See Filter memories. A policy controls what becomes memory, not what reaches Alvia; see Memory policies. Alvia keeps the conversation’s text for the life of the project, and deleting the project erases it along with every memory; see Data retention and deletion in Security.
Use the conversation’s original occurred_at for historical imports, so its facts keep their
real age. See Age and temporal decay.