Skip to main content
memories.create_from_file uploads a file, or a piece of text, and Synap extracts the text on the server. That text then goes through the same ingestion pipeline as memories.create: it is split if it is long, its memories are extracted, and they are stored under the person you named. The call returns an ingestion_id right away and the work happens in the background.

Upload a file

Pass the content in exactly one of three ways:

Use the right identity: relationship_type

create_from_file takes a relationship_type that the other ingestion calls do not, and it defaults to "b2c". Set it to match your instance: On a B2B instance the default is wrong and fails silently. With relationship_type="b2c", the server treats the user as the whole identity and replaces your customer_id with the user_id. The upload succeeds, but its memories are filed under a customer named after the user, and fetches for that user under your real customer do not find them. Check which kind your instance is in B2C vs B2B.
TypeScript SDK on a B2C instance (0.5.11 and earlier). When you leave customer_id out, create_from_file sends the text "undefined" as the customer id, and a B2C instance refuses any customer id. Until a fixed release, pass customer_id: '' on B2C: the SDK and the server both treat an empty value as absent. The Python SDK is not affected.
create_from_file always files memories at user scope, because user_id is required. For a document a whole customer or your whole organization should share, such as a policy or a product manual, extract the text and call memories.create with customer_id only (B2B) or with no ids at all; see Identifiers and scopes.

Accepted files

Synap reads text only. Pictures and charts inside a PDF, DOCX or PPTX are not read. Uploads that cannot be read are refused before anything is stored:

Set the document type

Synap does not detect the type from the file. If you leave document_type out, the upload is processed as "document", whatever its extension. The type tells the pipeline what kind of text it is reading; for example, when a long text has to be split, a chat is split at turn and session boundaries and other text at paragraph boundaries. create_from_file passes the value through without checking it, and the server processes a value it does not recognize as "document". memories.create checks the value against the types the published SDKs accept:

When to extract the text yourself

Extract the text in your own code and call memories.create with a document_type when:
  • The format is not accepted, such as CSV, HTML, .doc or saved email files.
  • The PDF is scanned. Run OCR first and send the text.
  • The file is larger than 10 MB.
  • You need the document’s date. create_from_file has no document_created_at, so Synap cannot tell when the document was written, and a statement like “the contract renews next March” cannot be tied to the right year. memories.create takes the date.
  • You need document_id or a scope path. Neither SDK sends a scope path from create_from_file (the TypeScript options declare scope, but releases up to 0.5.11 do not send it). On a scope ladder with a level between customer and user, use memories.create with scope.
  • The document is shared by a customer or your whole organization, as described above.
Remember that memories.create defaults to ai-chat-conversation. Set document_type whenever the text is not a chat.

Long documents

Text too long for one extraction pass, a few thousand tokens or more, is split into parts before extraction: conversations at session and turn boundaries, other text at paragraph boundaries. Each later part carries a short excerpt of the text before it, so its extraction has some context from the earlier parts. Each part is processed as its own ingestion job, and the ingestion_id you get back belongs to the first part. When memories.status reports completed for that id, the first part is done; later parts may still be in progress.

Duplicates

Synap fingerprints the text it extracted, ignoring differences in whitespace, and remembers the fingerprint for seven days for each user and customer. Uploading the same content again for the same person within that window returns the earlier response, with the same ingestion_id and document_id, and nothing is processed again. That response repeats the status from the first upload, usually queued, so call memories.status to see where the work actually is. memories.create shares the same check, so the same text sent through it for the same person is also treated as a duplicate. The same file uploaded for a different user is processed for that user. After seven days, the same content is processed again.

Track processing

memories.status returns where an ingestion is: queued, processing, completed, failed or partial_success, along with memories_created, memory_ids and error_message. memories.wait_for_completion polls it for you, every 2 seconds for up to 300 seconds by default.
The two SDKs end a wait differently: Python raises TimeoutError when time runs out, and TypeScript returns the last status it saw.

Common mistakes

  • Leaving relationship_type at its default on B2B. The upload succeeds and its memories land under the wrong customer. Pass relationship_type="b2b" with your customer_id.
  • Passing file without filename. The upload is named upload, has no extension, and is refused as an unsupported type.
  • Expecting the type to come from the extension. Without document_type, every upload is processed as "document".
  • Uploading a scanned PDF. There is no text layer, so nothing can be extracted. OCR it and send the text.
  • Uploading shared documents with create_from_file. They are filed under the one user you named. Use memories.create without user_id for content a whole customer or your whole organization should see.
  • Treating completed as done for a long document. The returned id covers the first part only.
  • Expecting a re-upload to be processed again. Within seven days, the same content for the same person returns the earlier ingestion.
  • Sending non-chat text to memories.create without a type. It is processed as a chat conversation.