Upload document
well_upload_documentUpload a document (invoice, receipt, statement) into the workspace by sending its bytes as base64.
⚠️ THIS IS A WIDGET'S WRITE, NOT YOURS. The card's drop zone reads the file the person dropped or chose, encodes it, and calls this tool itself. Do NOT call it: a model holds no file, so a call made from a conversation can only carry bytes nobody supplied. When a person says they have the invoice, point them at the drop zone on the gap card.
Send content_base64 WITHOUT a data-URI prefix — the raw base64 only, no data:application/pdf;base64, header.
Accepted content: PDF, JPEG, PNG, GIF, HEIC, HEIF, AVIF, WEBP, TIFF, plain text, CSV, XML. The bytes are checked against the declared mime_type (file signature, not just the claim), so a PNG announced as a PDF is refused.
Size ceiling: 5 MB of file (before base64). A larger file is refused with its actual size — upload it through the web app instead, which accepts up to 15 MB.
Pass source_transaction_id to anchor the document to the bank transaction it pays. That is what makes a dropped invoice land on the right line instead of in a general inbox.
Well extracts the document after upload; the extraction is asynchronous and this call returns as soon as the file is stored. A file already in the workspace is deduplicated by content and returns the existing document rather than a copy.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| filename | Yes | The file's name WITH its extension, e.g. `invoice-2026-03.pdf`. The extension resolves the content type when `mime_type` is generic. | |
| mime_type | Yes | The file's content type, e.g. `application/pdf`. Send `application/octet-stream` when unknown and the extension decides. | |
| workspace_id | No | Target workspace. Omit when the token authorizes one workspace. Required when it authorizes several — a write lands in exactly one workspace and this call would not say which. | |
| content_base64 | Yes | The file's bytes, base64, with no data-URI prefix. | |
| source_task_id | No | The task this document answers. | |
| conversation_id | No | The conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation. | |
| idempotency_key | No | Optional client-supplied key. A retried write with the same key returns the original result instead of re-applying the operation. | |
| source_transaction_id | No | The bank transaction this document is the proof for. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| error | No | ||
| outcome | No | ||
| success | Yes | ||
| filename | No | ||
| max_bytes | No | ||
| mime_type | No | ||
| error_code | No | ||
| size_bytes | No | ||
| document_id | No | ||
| actual_bytes | No | ||
| deduplicated | No | ||
| source_task_id | No | ||
| conversation_id | No | The conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation. | |
| conversation_id_note | No | Present only when the server opened a fresh lane, stating that no choice recorded earlier was read. | |
| source_transaction_id | No | ||
| conversation_id_source | No | Where the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened. |