File uploads
Attach images and documents to actions — public URLs, the file-uploadable shape, and the base64 envelope for local bytes.
Some actions take files — an Instagram photo, a Google Drive upload, a LinkedIn image, a Canva import. ClawLink accepts files in two ways depending on the action's schema, and the easiest path is almost always a public URL, which ClawLink fetches and re-hosts for the provider automatically.
How file fields appear
An action's input exposes files in one of two shapes:
- A URL field — e.g. Instagram's
image_url. Pass a URL string directly. - A file-uploadable object — e.g. Google Drive's
file_to_uploador LinkedIn'simages[]. Pass an object:{ "name", "mimetype", "s3key" }.
Use GET /api/actions/{integration_id}/{action_id}
to see which fields an action has.
The easy path: a public URL
For either shape, hand ClawLink a public HTTPS URL and it does the rest — fetches the bytes server-side and uploads them to the provider. No client-side file handling needed, which makes this the right approach for raw HTTP, MCP, Hermes, and CLI callers.
{
"integration_id": "instagram",
"action_id": "post_ig_user_media",
"input": {
"image_url": "https://example.com/photo.jpg",
"caption": "Posted via ClawLink"
},
"confirm": true
}URL rules
- Must be publicly reachable and serve the raw file bytes — not an HTML page, and not behind a login.
- Share links are handled for you. Google Drive (
drive.google.com) and Dropbox links are automatically rewritten to direct-download form. Query-string / signed URLs and most CDNs work as-is. - Private/LAN addresses are rejected (
localhost,127.0.0.1,10.x,192.168.x, etc.) — the server can't reach them. - If a URL returns HTML instead of bytes, ClawLink makes one attempt to resolve a social
preview image (
og:image/twitter:image) before failing withmedia_url_not_a_file.
The file-uploadable shape
When a field is a file-uploadable object, its s3key is flexible:
namestringrequiredFilename, e.g. "photo.jpg".
mimetypestringrequiredMIME type, e.g. "image/jpeg", "application/pdf".
s3keystringrequiredOne of: a public HTTPS URL (re-hosted for you, above); an Apollo key returned by a prior ClawLink upload (passed through unchanged); or, only when using the OpenClaw npm plugin, a local file path under an OpenClaw media directory.
If you accidentally send the reference under url or path instead of s3key, the
relay still recovers it — but s3key is the documented field.
Uploading local bytes over raw HTTP
If your file is on your own machine (not a public URL), use the base64 files
envelope on the tool endpoint, POST /api/tools/{tool_name}/execute. This is the only
way to send raw bytes directly.
How it links up: set the file-uploadable field's s3key to any placeholder string, then
add a files[] entry whose pointer equals that same string. ClawLink matches
files[].pointer === arguments.<field>.s3key, uploads the bytes, and rewrites the key
before calling the provider.
curl -X POST https://claw-link.dev/api/tools/googledrive_upload_file/execute \
-H "Authorization: Bearer cllk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"arguments": {
"file_to_upload": { "name": "report.pdf", "mimetype": "application/pdf", "s3key": "report.pdf" }
},
"files": [
{
"pointer": "report.pdf",
"name": "report.pdf",
"mimetype": "application/pdf",
"md5": "9e107d9d372bb6826bd81d3542a419d6",
"dataBase64": "JVBERi0xLjQKJ…"
}
],
"confirmed": true
}'Each files[] entry requires all five string fields: pointer, name, mimetype,
md5 (hex MD5 of the decoded bytes), and dataBase64.
The base64 files envelope works only on /api/tools/{tool_name}/execute. The
canonical /api/executions endpoint does not accept files — there, put a public URL
in input instead.
Limits
| Limit | Value |
|---|---|
| Max size per file | 25 MB |
Max total bytes per /api/tools/.../execute request | 100 MB |
Agent-runtime upload (curl ingest)
When an agent (OpenClaw ClawHub plugin, CLI, MCP, Hermes) calls a tool with a local
path it can't read, the action fails with missing_file_bytes and the error hint
contains a ready-to-run curl line pointing at POST /api/files/ingest. The agent's
shell runs it to upload the bytes and gets back an Apollo s3key to retry with.
This endpoint is authenticated by a short-lived, single-use HMAC token that ClawLink mints
inside that error hint — you don't call it cold. As a direct HTTP caller, prefer a
public URL or the base64 files envelope above.
Local-file upload requires the server-side FILE_INGEST_SECRET to be configured. If it
isn't, /api/files/ingest returns 503 and only the URL / base64 paths are available.