> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tape.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Uploads

Standard S3 write operations land data on the bucket's tape as certified tracks.

<Note>
  Writes need two things set up first: a SigV4 credential with write scope, and the bucket tape's on-chain delegation to the gateway. [Configuration](/tools/s3-gateway/configuration) covers both.
</Note>

## PutObject

A single-request upload. The gateway handles it one of two ways, depending on how your client sends the payload: signed-hash uploads are buffered and verified against the checksum before anything lands, while declared-size, chunked, and unsigned payloads stream with bounded memory. The ceilings are gateway configuration (256 MiB buffered, 5 GiB overall by default).

What lands on-chain depends on size too: one track for objects up to 64 MiB, segment tracks plus a manifest for anything larger. Certified either way ([how tracks work](/protocol/architecture/tracks)).

Object keys follow the protocol's naming rules, up to 1024 bytes ([names](/protocol/architecture/objects#names)). The gateway additionally rejects keys containing control bytes (below `0x20`, or `0x7F`), which keeps keys well-formed for standard tooling.

<Tabs>
  <Tab title="aws CLI">
    ```bash theme={null}
    aws s3 cp ./report.pdf s3://my-bucket/reports/q2.pdf --profile tapedrive
    ```
  </Tab>

  <Tab title="rclone">
    ```bash theme={null}
    rclone copy ./report.pdf tapedrive:my-bucket/reports/
    ```
  </Tab>

  <Tab title="boto3">
    ```python theme={null}
    s3.upload_file("report.pdf", "my-bucket", "reports/q2.pdf")
    ```
  </Tab>
</Tabs>

## Multipart uploads

For large files and unreliable links: create the upload, send parts, complete. Each part is independently retryable, so a failed part re-uploads without restarting the whole transfer.

Multipart state is store-backed and survives a gateway restart. An upload you started yesterday completes today. The S3-standard 5 MiB minimum part size applies (smaller parts return `EntityTooSmall`), and listing in-flight uploads and aborting both work.

<Tabs>
  <Tab title="aws CLI (automatic)">
    ```bash theme={null}
    # the CLI switches to multipart automatically for large files
    aws s3 cp ./dataset.tar s3://my-bucket/datasets/dataset.tar --profile tapedrive
    ```
  </Tab>

  <Tab title="Explicit sequence">
    ```bash theme={null}
    aws s3api create-multipart-upload --bucket my-bucket --key datasets/dataset.tar
    aws s3api upload-part --bucket my-bucket --key datasets/dataset.tar \
      --part-number 1 --body part-1.bin --upload-id "$UPLOAD_ID"
    aws s3api complete-multipart-upload --bucket my-bucket --key datasets/dataset.tar \
      --upload-id "$UPLOAD_ID" --multipart-upload file://parts.json
    ```
  </Tab>
</Tabs>

## Overwrites

Writing to an existing key is last-write-wins: a new track under the same name, with reads resolving to the latest write ([objects](/protocol/architecture/objects)). There is no versioning. The previous track still occupies capacity until you delete it ([deletions](/tools/s3-gateway/deletions)).
