---
title: "Upload file contents for a draft"
method: PUT
path: "/drops/{slug}/blobs/{sha256}"
---

# Upload file contents for a draft

`PUT /drops/{slug}/blobs/{sha256}`

## Request

- Base URL: `https://ship.page`
- URL: `https://ship.page/drops/{slug}/blobs/{sha256}`
- Auth: HTTP bearer

Content-addressed: upload each new or changed file's bytes once, then reference its hash from PUT /drops/{slug}/draft. Up to 10 MB per file; uploading a hash the drop already has is a no-op.

## Response `200`

Already stored.

- object
  - `sha256` string
  - `bytes` integer

## Other responses

- `201`: Stored.
- `400`: hash_mismatch: the body doesn't hash to the path's sha256.
- `401`: Missing or invalid credential.
- `402`: Subscriber-gated feature on a free account. The body's `hint` and `upgrade_url` tell the user how to upgrade.
- `404`: Not found (also returned for resources owned by someone else).
- `409`: busy: open the drop with GET /drops/{slug}/tree first.
- `410`: The drop has expired (expired).
- `413`: too_large: over 10 MB.
- `429`: Rate limited. Back off per the Retry-After header (60s).
- `503`: Required backend unavailable. Password creation and rotation fail closed when billing cannot be verified; retry later.
- `507`: storage_full: this drop's or account's editor storage is full.

## Changes

- **2026-10-20** `99aad34506e8`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/ship/apis/ship-page/changes/drops/:slug/blobs/:sha256/put.md)

---

[API](https://skmtc.dev/ship/apis/ship-page.md) · [All operations](https://skmtc.dev/ship/apis/ship-page/llms.txt) · [OpenAPI document](https://skmtc.dev/ship/apis/ship-page/revisions/99aad34506e8?raw)
