Returns the bytes of a file the agent wrote into a thread's workspace
| Time | Status | User Agent | |
|---|---|---|---|
Retrieving recent requests… | |||
Returns the bytes of a file the agent wrote into this thread's workspace, with the API key alone.
This is the endpoint for anything create_artifact produced — which is most of what a turn makes. Those files are ephemeral to the thread and are not project artifacts: they do not appear in the project artifact list, and no artifact SSE frame announces them. Only save_artifact_to_project promotes a file into the project library, and the agent does that when the user asks to keep it — so you cannot rely on it having happened.
The path is workspace, not artifacts, precisely because these are the files the project artifact list does not return.
Addressing a file
Both parts come off the stream:
| Part | Where it comes from |
|---|---|
threadId | The turn's leading init frame. |
filename | The create_artifact tool_result payload. |
The tool result reports the filename rather than a URL, so the route can change shape without stranding a client on a stale link.
filename is a single filename, not a path. A value containing / or .. is rejected with 400.
Basic Usage
curl --request GET \
--url 'https://cloud.getwren.ai/api/v2/projects/1/threads/5/workspace/q3-revenue.html' \
--header 'Authorization: Bearer <API_KEY>'The response body is the file — there is no JSON envelope and no URL to follow:
<!doctype html>
<html>
<head><title>Q3 revenue</title></head>
<body>...</body>
</html>The content type is inferred from the filename extension, falling back to application/octet-stream.
Query Parameters
| Parameter | Type | Accepted values | Default | Description |
|---|---|---|---|---|
mode | string | preview · download | preview | preview serves the bytes inline; download adds Content-Disposition: attachment carrying the filename. |
modedefaults topreviewhere, whereas the presigned-URL endpoint defaults todownload. That endpoint mints a link for a browser to follow; this one is normally read by your own code.
Security headers
| Header | When |
|---|---|
X-Content-Type-Options: nosniff | Always. |
Cache-Control: private, max-age=30 | Always. |
Content-Security-Policy: sandbox | Renderable documents — HTML, SVG, XML. |
Referrer-Policy: no-referrer | Renderable documents. |
Artifact markup is generated by the agent, so it is treated as untrusted and kept on an opaque origin. Filenames the agent chose may be non-ASCII — on download the Content-Disposition carries an ASCII fallback plus an RFC 6266 filename* with the real name.
Error handling
| Status | When |
|---|---|
400 | Invalid project_id or thread_id, or a filename that is empty, ., .., or contains / or \. |
401 | Missing or invalid API key. |
404 | The project, the thread, or the file does not exist. A thread belonging to another project is reported the same way. |
405 | Method not allowed — this endpoint is GET only. |
501 | The artifact service is not configured on this deployment. |
A file the thread never wrote and a git-server outage both surface as
404. If reads start failing across every thread, suspect the latter.
See Artifacts for how this compares with the project library, and a worked example.
