POST/api/v1/runs/{runId}/files
Each file is persisted as an artifact (source of truth) and, if the
container is live, immediately written to the workdir via a
file:inject WebSocket frame.
Where a file is kept
Every injected file is written to the working directory. Whether a copy
is also kept in flow storage depends on the flow’s .flowignore:
| Working directory | Flow storage (shared, pushed to git) | |
|---|---|---|
| Ordinary path | yes | yes — returned in persisted |
Matched by .flowignore | yes | no — returned in instanceOnly |
A file matched by .flowignore is not dropped. It is instance-only:
it lives in the working directory, is preserved by that instance’s
snapshot, and is restored when the container respawns — it simply is
not stored as a flow file and never reaches your git repo. This is the
same rule the container’s own file sweep applies, so a path behaves
identically whether it is written by the flow or injected through this
endpoint.
Because an instance-only file has nowhere to live but a running
container’s working directory, injecting one into a sleeping run
returns 409 CONTAINER_NOT_RUNNING rather than accepting the request
and discarding the file.
The response reports which paths were persisted, which were
instanceOnly, and whether the write was also liveDelivered to the
running container.
Text by default, binary when you say so
content is UTF-8 text and is written to the workdir exactly as sent.
For a file that is not text — an image, a font, an archive — set
encoding: "base64" and send the base64 of the bytes. It is decoded
once, on arrival, and the bytes are stored and written verbatim.
Do not base64-encode without declaring it. The string is then written to the workdir as the file, which is what happens to any content sent as text. This was previously the only outcome, because the field did not exist and was silently discarded.
Each file object accepts path, content and encoding, and nothing
else. An unrecognised field is a 400, not a silent omission: a
request we do not fully understand must not be answered 202, since
that status is a promise the write happened as asked.
Limits
| Limit | Value |
|---|---|
| Files per call | no limit — the body size bounds it |
| Bytes per file | 1,000,000 |
| Bytes per request body | 26,214,400 (25 MiB) |
The per-file limit is set by Firestore: each file becomes a document,
and a document cannot exceed 1 MiB. Both file limits are measured in
bytes, not characters — one multi-byte character costs more than
one. Exceeding the body limit returns 413 PAYLOAD_TOO_LARGE with the
size sent and the limit in the message, so a client can decide how far
to split a batch instead of guessing.
Authentication
Requires a project API key — see Authentication.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
runId | path | string | required | UUID of the run. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
files | array | required |
Responses
| Status | Description |
|---|---|
202 | Files accepted. |
400 | Request body or query parameters failed validation. |
404 | Resource not found or not accessible to this project. |
413 | Request body exceeded 26,214,400 bytes (25 MiB). The message names the size sent and the limit. Split the files across multiple calls. |
Tag: Interactions