---
title: "Upload a file for an attachment field, as the builder"
description: "The builder plane's half of `files.upload`."
canonical: "https://gtable.app/docs/builder-api/data/files-upload"
updated: "2026-10-05"
---

# Upload a file for an attachment field, as the builder

`POST https://studio.gtable.app/v1/apps/{appId}/tables/{tableId}/files`

The builder plane's half of `files.upload`.

Takes the BYTES as `multipart/form-data` under `file`, with `recordId` saying which record they will belong to, and answers with the descriptor to write into an attachment field. Attaching it is an ordinary record write, so the file arrives through the same op log and the same undo as any other value.

Requires the `records:write` scope. Operation `apps.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 apps files upload`.

## Path parameters

| Name      | Type   | Required | Description |
| --------- | ------ | -------- | ----------- |
| `appId`   | string | yes      |             |
| `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. |
