Upload a file for an attachment field
Two steps, on purpose.
POST/v1/tables/{tableId}/files
This one takes the BYTES and answers with a descriptor: { id, name, size, mime, key, uploadedAt }. Writing that descriptor into an attachment field is an ordinary record write, so a file lands on a record through the same permission check, the same op log and the same undo as any other value. Send the file as multipart/form-data under file; recordId says which record it will belong to, so an upload that is never used can be swept. A descriptor you did not get from here is refused: its key names an R2 object, and inventing one would be naming somebody else’s bytes.
Requires the records:write scope. Operation files.upload. Not an MCP tool: a file is bytes and a tool call is JSON; upload with REST or the CLI. CLI, once published: gtable files upload.
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
tableId | string | yes |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
Idempotency-Key | string | no | Any unique string. Sending the same key with the same request again returns the first response (marked Idempotency-Replayed: true) instead of running it twice. Reusing it for a different request is refused with 409. Kept for 24 hours. Up to 255 characters. |
Request body
Sent as multipart/form-data.
| Field | Type | Required | Description |
|---|---|---|---|
file | string | yes | The bytes. |
recordId | string | yes | The record the file will be attached to, so an upload never attached can be swept. |
Response
Success
dataobjectrequiredRefused
errorobjectrequired