Skip to content

File Upload ​

When Priya sends her lab report through your chat widget, your agent needs to read it — not just acknowledge it. Perfox stores the file, extracts its content, and hands it to your agent together with her message so it can respond with context.

You're looking at the right page if you're adding file-upload support to your widget embed. By the end you'll know how to enable it, what the API expects, and what your agent receives. The Public Widget API page covers the broader widget surface if you need that first.

Enabling uploads ​

Upload is off by default. Open your agent, click the Web Chat trigger node, and on the Configure tab turn on Enable file upload under Capabilities. Publish the agent. The widget then shows an attach button, and /init reports file_upload: true in its capabilities.

If the switch is on but something the feature needs isn't ready, /init reports file_upload: false with a capability_warnings entry explaining why, and the upload endpoint answers with one of these codes:

StatusCodeWhat it means
403file_upload_not_enabledThe switch is off.
503no_workflow_configuredNo published agent handles this widget.
503file_upload_prereq_failedA prerequisite check failed — the response includes a remediation hint.
503missing_credentialFile storage isn't available.

How attaching works in the widget ​

A file is context for a message, not a message of its own:

  1. The visitor picks, drops or pastes up to 5 files at a time, each up to 25 MB. Photos are shrunk in the browser before they upload.
  2. Each file uploads and is processed in the background while the visitor keeps typing; a chip on the composer shows its progress.
  3. Send unlocks once every attached file is ready. The files ride along with that message — even with an empty caption — and the agent answers with them in view.

Accepted types are the same as the knowledge base: PDF, Word, Excel, PowerPoint, OpenDocument, RTF, EPUB, CSV/TSV, text, Markdown, HTML, JSON, XML, YAML, email files (EML, MSG, MBOX), calendar and contact cards, images, audio and video.

Sending a file yourself ​

Custom clients upload with:

POST /api/public/widget/upload
Content-Type: multipart/form-data
X-Perfox-Site: sa_site_live_…
Origin: https://your-page.example.com

Point the request at your API host (<slug>-api.perfox.ai). Include these fields:

FieldRequiredWhat
fileYesOne file, up to 25 MB.
conversation_idRecommendedThe conversation from /init, so the file belongs to it.
customer_idNoThe customer from /init.
workflow_idNoThe agent to use, if you pinned one.
user_contextNoThe visitor's identity, as a JSON string.

The response comes back once the file is stored and its content extracted:

json
{
  "upload_id": "01HQ…",
  "file_id":   "01HQ…",
  "file_name": "receipt.pdf",
  "file_url":  "https://…signed-url…",
  "file_key":  "…",
  "mime_type": "application/pdf",
  "status":    "ready"
}

upload_id is the handle you use from here on (file_id is the same value, kept for older clients). file_url is a short-lived signed link for showing the file in your own UI. To attach the file, send it with the next message:

json
POST /api/public/widget/send
{ "conversation_id": "…", "text": "Here's my receipt", "file_refs": ["01HQ…"] }

text may be empty when file_refs is present. You can check a file's state at any time with GET /api/public/widget/upload/<upload_id>?conversation_id=<id>, which returns its status (uploading, parsing, ready or failed) and, once available, a one-line summary.

Other upload errors: 400 unsupported_type for a file type Perfox can't process, and 400 too_many_files when five files are already processing for the conversation.

What Perfox does with the file ​

The file is stored privately — your data stays private to your workspace — and its content is extracted according to its type:

CategoryHow it's processed
ImagesVision-based description
PDF / Word / Excel / slidesVision, OCR, or structured extraction
AudioTranscription
VideoFrames and audio
Text formatsRead as-is

The full extracted text is kept with the upload, and a short summary is generated shortly after. The AI model that powers extraction is included and managed by Perfox — there is nothing to configure.

What your agent sees ​

On the turn a file is attached, Perfox adds an attached files note to the agent's context listing each file's name, id and a fresh file_url. Small documents are included in full; larger ones get their summary plus a nudge to read more with a tool. Very large documents (roughly 20,000 characters of text or more) are also indexed, so the agent can search inside them instead of reading them end to end.

Worked example — a customer attaches a receipt ​

Setup. Asha runs Acme Support. The Web Chat trigger on her agent has Enable file upload turned on.

Action. Priya opens the Acme Support chat, attaches returns-receipt.pdf, waits for the chip to show it's ready and types "Can I return these?".

Result. The agent reads the order date and item from the receipt and replies with the correct return window, without asking Priya to repeat anything.

What just happened. The widget uploaded the PDF in the background, Perfox extracted its text, and the message Priya sent carried the file with it — so the receipt was in the agent's context on the very turn she asked.

Passing the file itself to a tool ​

Extraction puts the file's text in front of your agent. A different job is handing the file itself to a tool that takes a URL — your own submit_order_form({ file_url }), a document extractor, or a WhatsApp send with a media link. Two built-in tools cover that, and your agent is told about attached files automatically, so it does not have to go looking.

ToolArgumentsReturns
list_attachmentsnone — scoped to the current conversationOne row per upload: id, name, type, size, status (uploading → parsing → ready | failed), timestamps. Metadata only — no text, no link. Cheap, so the agent can call it freely.
get_attachmentupload_id, optional query, optional max_charsMetadata, the extracted text, and a freshly signed file_url. Pass query to search the document and get only the relevant passages; omit it for the full text (default 8,000 characters, maximum 20,000).

Your agent already has the link. The attached-files note carries a fresh file_url for each file. That is what lets an agent pass a file straight to your tool instead of describing it back to the customer.

Write your persona to pass the link, not invent one

"When a tool needs the file, pass the exact file_url you were given — never construct one." Perfox already instructs the model this way; saying it in your own persona too makes it stick.

Worked example — the agent files a customer's order sheet ​

Setup. Vijay's agent has file upload enabled and an Integration sub-node exposing submit_order_form({ file_url, customer_phone }) from the customer's own server.

  1. The customer attaches order-sheet.xlsx and types "here's our order for Diwali".
  2. The agent sees the attached-files note — name, upload_id, and a signed link — with no tool call needed.
  3. It calls submit_order_form, passing that link verbatim as file_url.
  4. The customer's server downloads the sheet from the link and returns an order id.
  5. The agent replies with the confirmation.

Had it needed the contents first, it would have called get_attachment(upload_id) — or get_attachment(upload_id, "total quantity") to pull just the relevant rows.

Things to design around ​

  • Links last about an hour. Fetch when you need it; don't store it. If yours has expired, call get_attachment again for a fresh one.
  • A failed extraction still gives you the file. If Perfox could not read a spreadsheet's text, the link is still returned — your tool may well handle the format better than a text extractor.
  • attachments_not_ready (409) on send means a file was still processing. It is a backstop; the composer normally waits. Poll the upload until each file reports ready — dropping any that failed — then send again.
  • Files expire with your retention window (365 days by default). After that the record remains but the bytes are gone, so a link for a very old attachment may not resolve.

You can now accept files in your widget ​

Your widget can receive files, extract their content, and give your agent the full context in the same turn.

Next steps:

  • Public Widget API — the full widget API surface, including authentication and conversation management.
  • Voice & Dial-Out — the other opt-in widget capabilities.
  • Knowledge Base & RAG — for documents you want every conversation to draw on, add them to a knowledge base instead.