Lovely RouterDocs
Get a key
Browser agent

File uploads

Upload files once, let a run use them, and the agent attaches the right one to each upload field.

Forms often ask for a file: a resume, an ID scan, an invoice. Upload your files to Lovely Router once. When a run may use them, the agent attaches the file that fits each upload field, your CV for a "Resume" field and not your cover letter, even when both are PDFs.

Upload a file#

Send the raw bytes to PUT /v1/browser/files/{name}, with the file's type as Content-Type. An optional description query parameter helps the agent choose.

curl -X PUT "https://lovelyrouter.com/v1/browser/files/Maria_Garcia_CV_2026.pdf?description=Resume%2C%20updated%202026" \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "content-type: application/pdf" \
  --data-binary @Maria_Garcia_CV_2026.pdf

Or send a multipart form to POST /v1/browser/files, with the file in a file field. name (defaults to the uploaded file's name) and description are optional fields:

cURL
curl https://lovelyrouter.com/v1/browser/files \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -F "file=@Maria_Garcia_CV_2026.pdf;type=application/pdf" \
  -F "description=Resume, updated 2026"

Both return the stored file:

JSON
{
  "id": "file_7a3c9e1b5d2f8a4c6e0b",
  "name": "Maria_Garcia_CV_2026.pdf",
  "mime": "application/pdf",
  "bytes": 84213,
  "sha256": "5f2b8c…",
  "description": "Resume, updated 2026",
  "created_at": "2026-10-11T09:20:44.000Z",
  "last_used_at": null
}

Without a Content-Type, the file is stored as application/octet-stream; send the real type so the agent and the website see it. Uploading again under the same name replaces the file and keeps its id. Files are encrypted at rest, like vault secrets. The Python and Node.js samples use the API, H and headers setup from Run your first task.

LimitValue
File size10 MB
Files per account100
Name1 to 128 characters: letters, digits, spaces and . _ - ( ) + ,, starting with a letter, digit or _
Description300 characters (longer text is cut)

Let a run use your files#

Pass files when you start a run: a list of file names or ids, or "*" for all your files.

cURL
curl https://lovelyrouter.com/v1/browser/runs \
  -H "Authorization: Bearer $LOVELY_API_KEY" \
  -H "content-type: application/json" \
  -d '{
    "goal": "Apply for the Backend Engineer role as Maria Garcia (maria.garcia@example.com), based in Portland, Oregon. Attach her resume. Submit the application and tell me the application ID.",
    "start_url": "https://jobs.example.com/backend-engineer/apply",
    "files": ["Maria_Garcia_CV_2026.pdf", "Maria_Garcia_Cover_Letter.pdf"],
    "max_steps": 40
  }'

The agent can attach files only in runs that pass files, and only the files listed. An unknown name returns 400 with Unknown file(s): CV.pdf. Upload with PUT /v1/browser/files/{name}.

In the trace, an upload step's action starts with upload: and its description names the field. If the run pauses for your approval before submitting, needs.fields shows which file is attached, for example Resume: file "Maria_Garcia_CV_2026.pdf".

How the agent picks a file#

At each upload field, the agent compares your files with what the field asks for. It looks at:

  • each file's name, type, size and description
  • the field's label and the file types it accepts
  • your goal and the page around the field

It matches the document's purpose, not only its type. To help it:

  • Use descriptive names. Maria_Garcia_CV_2026.pdf beats scan_0412.pdf.
  • Add a description when the name can't say it all: "Resume, updated 2026", "Passport photo page".
  • Say in the goal which file to use when it matters: "Attach her resume (not the cover letter)".
  • Pass only the files the run needs rather than "*" when you have many similar files.

List and delete files#

cURL
# List your files, sorted by name
curl https://lovelyrouter.com/v1/browser/files -H "Authorization: Bearer $LOVELY_API_KEY"

# Delete by name or id
curl -X DELETE "https://lovelyrouter.com/v1/browser/files/Maria_Garcia_CV_2026.pdf" -H "Authorization: Bearer $LOVELY_API_KEY"

The list returns {"object": "list", "data": [...]} with one file object per file. last_used_at shows when a run last attached it. Deleting returns {"deleted": "<name or id>"}, or 404 with No such file. You can also upload and delete files in the console under Secrets & files.

Errors#

StatusMessageCause
400File names are 1-128 chars: letters, digits, space . _ - ( ) + ,The name has other characters or is too long.
400Empty fileThe body has no bytes.
400Send multipart/form-data with a "file" field (and optional "description", "name")The multipart form has no file field.
409file limit reached (100); delete some firstYou already have 100 files. Replacing an existing name still works.
413Files are limited to 10 MBThe file is larger than 10 MB.