Upload
StableGenerated from capsule-server/openapi.json, the OpenAPI 3.2 document
capsule-server emits and mise run openapi-check-kynos keeps current. To change a
description on this page, change the annotation on the handler or model it comes from
and regenerate — this file is build output. The auth model, error contract, and
conventions common to every endpoint are on the REST API overview.
POST /v1/upload
Section titled “POST /v1/upload”Open an upload session for one blob of an asset bundle.
Runs the refuse-by-default envelope battery — invariants 1–8 and the top-level↔envelope
consistency family — before anything is written, then stages the session’s file and
records the session. A request whose (owner, hash, album) tuple already has an active
session gets that session back rather than a second one.
The quota is checked here and nowhere later: a declared size that would cross the hard limit
is 403 error.quota.exceeded, and an account whose quota the operator suspended is
403 error.quota.suspended, both before anything is charged or staged.
A finalized (owner, hash, album) is 409 error.upload.duplicate_blob naming the asset that
holds the bytes. When the request is a create for a different asset, the server first
records the existing blob against the requesting asset — custody-receipted and ledgered as a
finalization is — so the merge the client performs on the 409 leaves both assets holding a
reference, and purging one cannot collect bytes the other depends on.
Authentication: required — bearer.
| Parameter | In | Type | Description |
|---|---|---|---|
X-Capsule-Crypto-Suite | header | integer | The crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400. |
X-Capsule-Protocol | header | string | Required. The YYYY-MM-DD protocol version this request is written against. Outside the server’s [X-Capsule-Protocol-Min, X-Capsule-Protocol-Max] window the request is refused with 426. |
X-Capsule-Sidecar-Schema | header | integer | The sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400. |
Request body (required, application/json): CreateUploadRequest
| Status | Body | Description |
|---|---|---|
200 | CreateUploadResponse application/json | The active session for these bytes, to resume. Headers: Location, X-Capsule-Advice, X-Capsule-Committed, X-Capsule-Min-Client-Build, X-Capsule-Offset, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Capsule-Session-Expires-In, X-Capsule-Session-Idle-Expires-In, X-Capsule-Upload-Status, X-Request-Id. |
201 | CreateUploadResponse application/json | Upload session created. Headers: Location, X-Capsule-Advice, X-Capsule-Committed, X-Capsule-Min-Client-Build, X-Capsule-Offset, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Capsule-Session-Expires-In, X-Capsule-Session-Idle-Expires-In, X-Capsule-Upload-Status, X-Request-Id. |
400 | CodedProblem application/problem+json | Bad Request; Invalid upload; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
403 | CodedProblem application/problem+json | Forbidden; Account suspended; Upload not permitted; Quota exceeded; Quota suspended. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
409 | DuplicateBlobProblem application/problem+json | Album quiescing; Duplicate blob. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
413 | CodedProblem application/problem+json | Payload Too Large; File too large; the request body exceeds the configured limit. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
415 | CodedProblem application/problem+json | Unsupported Media Type. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
422 | CodedProblem application/problem+json | Unprocessable Entity. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
425 | CodedProblem application/problem+json | Too early. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
426 | CodedProblem application/problem+json | Protocol version unsupported. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
429 | UploadCreateRateLimitedProblem application/problem+json | Too many requests. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
503 | UploadCreateUnavailableProblem application/problem+json | Service unavailable. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
507 | UploadCreateStorageFullProblem application/problem+json | Insufficient storage. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
GET /v1/upload/sessions
Section titled “GET /v1/upload/sessions”Every upload the caller can resume.
Oldest first, which is the order the store promises and the order a client wants: the oldest in-flight session is the one closest to eviction.
Authentication: required — bearer.
| Parameter | In | Type | Description |
|---|---|---|---|
X-Capsule-Crypto-Suite | header | integer | The crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400. |
X-Capsule-Protocol | header | string | Required. The YYYY-MM-DD protocol version this request is written against. Outside the server’s [X-Capsule-Protocol-Min, X-Capsule-Protocol-Max] window the request is refused with 426. |
X-Capsule-Sidecar-Schema | header | integer | The sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400. |
status | query | string | null | Return only sessions in this state. One of pending, uploading, waiting_for_processing, completed, failed_processing — the same tokens the X-Capsule-Upload-Status header carries, so a client filters on the value it was already given rather than on a second vocabulary. |
| Status | Body | Description |
|---|---|---|
200 | SessionsResponse application/json | OK. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
400 | CodedProblem application/problem+json | Bad Request; Invalid status filter; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
403 | CodedProblem application/problem+json | Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
413 | CodedProblem application/problem+json | the request body exceeds the configured limit. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
500 | CodedProblem application/problem+json | Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
DELETE /v1/upload/{id}
Section titled “DELETE /v1/upload/{id}”Cancel a session: its record, its accepted chunks and its staged bytes, together.
Refused while finalization is running — it is not interruptible — and refused once the session is terminal, because there is nothing left to cancel and the receipt is what a client should read instead.
Authentication: required — bearer.
| Parameter | In | Type | Description |
|---|---|---|---|
X-Capsule-Crypto-Suite | header | integer | The crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400. |
X-Capsule-Protocol | header | string | Required. The YYYY-MM-DD protocol version this request is written against. Outside the server’s [X-Capsule-Protocol-Min, X-Capsule-Protocol-Max] window the request is refused with 426. |
X-Capsule-Sidecar-Schema | header | integer | The sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400. |
id | path | string | Required. The session’s identifier, as POST /v1/upload returned it. |
| Status | Body | Description |
|---|---|---|
204 | — | the request succeeded and there is no content to send. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
400 | CodedProblem application/problem+json | Bad Request; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
403 | CodedProblem application/problem+json | Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
404 | CodedProblem application/problem+json | Upload session not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
409 | CodedProblem application/problem+json | Session not active. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
413 | CodedProblem application/problem+json | the request body exceeds the configured limit. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
425 | CodedProblem application/problem+json | Too early. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
426 | CodedProblem application/problem+json | Protocol version unsupported. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
503 | UploadCancelUnavailableProblem application/problem+json | Service unavailable. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
HEAD /v1/upload/{id}
Section titled “HEAD /v1/upload/{id}”Report a session’s progress and state.
The resumption primitive: a client that lost a connection, an acknowledgement, or a process
asks here and learns the authoritative offset, the declared length and the session’s state.
The answer carries no body — HTTP forbids one on HEAD, which is why the protocol puts
all three on headers.
A session that holds every byte and whose finalization nobody claimed has its finalization
started before it is reported: a client resuming at an offset equal to the size sends nothing
more, so this may be the last request it makes about the session. The finalization is never
awaited — the answer is the state as it stands, waiting_for_processing — and the client
polls this operation, with backoff, until the state is terminal. A failed_processing state
carries the failure’s error.* code in X-Capsule-Upload-Error.
Authentication: required — bearer.
| Parameter | In | Type | Description |
|---|---|---|---|
X-Capsule-Crypto-Suite | header | integer | The crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400. |
X-Capsule-Protocol | header | string | Required. The YYYY-MM-DD protocol version this request is written against. Outside the server’s [X-Capsule-Protocol-Min, X-Capsule-Protocol-Max] window the request is refused with 426. |
X-Capsule-Sidecar-Schema | header | integer | The sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400. |
id | path | string | Required. The session’s identifier, as POST /v1/upload returned it. |
| Status | Body | Description |
|---|---|---|
200 | — | Progress and state on X-Capsule-* headers, no body. Headers: Cache-Control, X-Capsule-Advice, X-Capsule-Committed, X-Capsule-Content-Length, X-Capsule-Min-Client-Build, X-Capsule-Offset, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Capsule-Session-Expires-In, X-Capsule-Session-Idle-Expires-In, X-Capsule-Upload-Error, X-Capsule-Upload-Status, X-Request-Id. |
400 | CodedProblem application/problem+json | Bad Request; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
403 | CodedProblem application/problem+json | Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
404 | CodedProblem application/problem+json | Upload session not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
413 | CodedProblem application/problem+json | the request body exceeds the configured limit. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
503 | UploadHeadUnavailableProblem application/problem+json | Service unavailable. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
PATCH /v1/upload/{id}
Section titled “PATCH /v1/upload/{id}”Write one range of the blob, and finalize when the committed set reaches the declared size.
Every rule the chunk
contract fixes is
checked before a byte is written — the checksum against the received bytes first, so a
chunk corrupted in transit persists nothing, then admission against the committed set and the
ranges in flight ([chunk::admit]).
Authentication: required — bearer.
| Parameter | In | Type | Description |
|---|---|---|---|
X-Capsule-Checksum | header | string | null | The chunk’s SHA-256, bare lowercase hex. Required: the bytes are verified against it before any of them is written. |
X-Capsule-Crypto-Suite | header | integer | The crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400. |
X-Capsule-Offset | header | string | null | Where in the blob this chunk’s range starts: a multiple of 4 KiB, anywhere in the blob. |
X-Capsule-Protocol | header | string | Required. The YYYY-MM-DD protocol version this request is written against. Outside the server’s [X-Capsule-Protocol-Min, X-Capsule-Protocol-Max] window the request is refused with 426. |
X-Capsule-Sidecar-Schema | header | integer | The sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400. |
id | path | string | Required. The session’s identifier, as POST /v1/upload returned it. |
Request body (required, application/octet-stream): string
| Status | Body | Description |
|---|---|---|
204 | — | the request succeeded and there is no content to send. Headers: X-Capsule-Committed, X-Capsule-Min-Client-Build, X-Capsule-Offset, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Capsule-Upload-Status, X-Request-Id. |
400 | CodedProblem application/problem+json | Bad Request; Malformed request; Invalid chunk; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
403 | CodedProblem application/problem+json | Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
404 | CodedProblem application/problem+json | Upload session not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
408 | CodedProblem application/problem+json | Request timeout. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
409 | UploadChunkConflictProblem application/problem+json | Range conflict; Too many ranges in flight; Too fragmented; Session not active. Headers: Retry-After, X-Capsule-Committed, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
413 | CodedProblem application/problem+json | Chunk too large; the request body exceeds the configured limit. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
415 | CodedProblem application/problem+json | Unsupported media type. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
425 | CodedProblem application/problem+json | Too early. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
426 | CodedProblem application/problem+json | Protocol version unsupported. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
429 | UploadChunkRateLimitedProblem application/problem+json | Too many requests. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
500 | CodedProblem application/problem+json | Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
503 | UploadChunkUnavailableProblem application/problem+json | Service unavailable. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
507 | UploadChunkStorageFullProblem application/problem+json | Insufficient storage. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
GET /v1/upload/{id}/receipt
Section titled “GET /v1/upload/{id}/receipt”Fetch the custody receipt for a finalized upload.
Authentication: required — bearer.
| Parameter | In | Type | Description |
|---|---|---|---|
X-Capsule-Crypto-Suite | header | integer | The crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400. |
X-Capsule-Protocol | header | string | Required. The YYYY-MM-DD protocol version this request is written against. Outside the server’s [X-Capsule-Protocol-Min, X-Capsule-Protocol-Max] window the request is refused with 426. |
X-Capsule-Sidecar-Schema | header | integer | The sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400. |
id | path | string | Required. The session’s identifier, as POST /v1/upload returned it. |
| Status | Body | Description |
|---|---|---|
200 | string application/cbor | OK. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
400 | CodedProblem application/problem+json | Bad Request; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
403 | CodedProblem application/problem+json | Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
404 | CodedProblem application/problem+json | Not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
409 | CodedProblem application/problem+json | Receipt not available. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
413 | CodedProblem application/problem+json | the request body exceeds the configured limit. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
500 | CodedProblem application/problem+json | Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id. |
Schemas
Section titled “Schemas”The models these endpoints carry. A field whose type names another model links to it when this page documents that model, which it does when some path from an operation reaches it within 4 references. A model only ever reached deeper than that is named without being expanded.
CodedProblem
Section titled “CodedProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
CreateUploadRequest
Section titled “CreateUploadRequest”The body of POST /v1/upload.
Strict (deny_unknown_fields): an unknown field is a client bug and is refused rather than
ignored. Plaintext metadata — a filename, a capture date, dimensions — is deliberately
absent: it rides the encrypted metadata blob and never the wire request.
| Field | Type | Description |
|---|---|---|
size | integer | Required. The ciphertext length in bytes. Immutable for the session’s life. |
hash | string | Required. The ciphertext content hash, lowercase hex; the digest length is the suite’s. |
content_type | string | Required. The media type, from the closed enum this protocol version fixes. |
crypto_suite_id | integer | Required. The crypto suite the blob was sealed under. |
protocol_version | string | Required. The protocol date (YYYY-MM-DD) this session is pinned to. |
blob_role | WireBlobRole | Required. The blob’s role in its bundle. |
manifest_envelope | ManifestEnvelope | Required. The unencrypted manifest fields the server validates. |
album_id | string | null | The album the asset is filed into. Optional on the wire because the contract reserves the shape for owner-scoped kinds and for the album-upgrade ceremony; required by this server, which has no way to check invariant 6 without one and refuses rather than skipping it. |
owner_id | string | null | The owner the asset is filed under, when the client wants to say so. Advisory, never decisive: the asset is filed under the album’s owner, which the write authority answers from the album record — the uploader when it is their album, the owner when the uploader is a writer on its roster. A declared owner that is anyone else, the uploading member included, is refused error.upload.owner_not_permitted. |
intent_id | string | null | The album-upgrade intent this write belongs to, when it belongs to one. Carried onto the session verbatim and read by nobody in this port; the album-upgrade ceremony gives it meaning. |
CreateUploadResponse
Section titled “CreateUploadResponse”What a client needs to start sending bytes.
| Field | Type | Description |
|---|---|---|
id | string | Required. The session’s identifier. |
upload_url | string | Required. Where to send chunks. |
suggested_chunk_size | integer | Required. A starting chunk size. A suggestion only — the client owns adaptation. |
DuplicateBlobProblem
Section titled “DuplicateBlobProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
existing_asset | string | The asset already holding these exact bytes in the same album. Structured so a client merges rather than re-parsing a sentence. |
ManifestEnvelope
Section titled “ManifestEnvelope”The server-visible mirror of the signed manifest’s envelope fields, as declared at
POST /v1/upload.
Strict (deny_unknown_fields) like the rest of the transport JSON. The Postel asymmetry
the design draws — tolerant inside documents that outlive us, strict on the wire we own —
puts unknown-key tolerance in the signed CBOR interiors, never in this JSON projection.
| Field | Type | Description |
|---|---|---|
crypto_suite_id | integer | Required. The crypto suite the blob was sealed under. Must equal the top-level declaration. |
protocol_version | string | Required. The protocol date the manifest was written under (YYYY-MM-DD). |
album_id | string | null | The album the asset belongs to. Must equal the top-level declaration. |
file_id | string | Required. The asset this blob belongs to — the same id across the bundle’s members. |
amk_version | integer | Required. The album-key epoch the manifest was written under. |
ciphertext_hash | string | Required. The ciphertext content hash, lowercase hex. Must equal the top-level hash. This names the blob this session is uploading, not the manifest’s own ciphertext_hash. For the original the two coincide; for a metadata or provenance session they do not, and the projection reuses the manifest’s field name for a per-blob declaration. Invisible for a create, because the bundle is assembled in a pending row nobody can see and no member has to name another. It is not invisible for a replace, which is why [Self::original_blob_hash] exists. |
plaintext_size | integer | Required. The plaintext length the manifest commits to. |
chunk_size | integer | Required. The STREAM plaintext chunk size. |
key_mode | string | Required. derived or wrapped. |
metadata_blob_hash | string | null | The content hash of the bundle’s metadata blob, when the manifest commits to one. |
original_blob_hash | string | null | The content hash of the bundle’s original blob, when the manifest commits to one. The manifest’s own ciphertext_hash, under a name that cannot be confused with [Self::ciphertext_hash]‘s per-session meaning. Optional on the wire and required on a replace: a replace re-points roles that already have bytes, so it has to be applied as one act, and the only member of the bundle that can carry the whole change is the manifest — which therefore has to be able to name the original it commits to. A create may omit it. Its bundle is assembled incrementally in a row nobody can see, so no member needs to name another and requiring it would be a wire change for no gain. |
derivative_role | string | null | The derivative’s role — thumbnail, preview, or embedding — copied from its signed DerivativeManifest.role. Required on a derivative blob and refused on every other. The server cannot read the signed derivative manifest (it is key-free), so the closed still-format check the tier table requires of every receiver runs over this declared pair instead. A forged pair buys nothing: the client that verifies the signed manifest runs the same check over the signed values. |
derivative_format | string | null | The derivative’s format — DerivativeManifest.format, e.g. image/jxl. Required and refused exactly as [Self::derivative_role] is, and must equal the blob’s declared content_type. For a thumbnail or preview an unrecognised value is [GateReject::UnknownDerivativeFormat]. |
created_by_user | string | Required. The account that created the asset. |
created_by_device | string | Required. The device that created it, as a UUID — invariant 7’s subject. |
client_version | string | Required. The client build that wrote the manifest. |
timestamp | string | Required. The manifest’s self-asserted RFC3339 timestamp — invariants 7 and 8’s subject. |
action | string | Required. The lifecycle action. create or replace on this surface — the two that move blob bytes — and see [GateReject::ActionNotAllowed] for the rest. |
prior_provenance_hash | string | null | The provenance chain position this write continues from. |
retention_until | string | null | The retention floor the manifest carries, when it carries one. |
SessionSummary
Section titled “SessionSummary”One in-flight upload, as the resumption listing serves it.
Deliberately not the whole [UploadSessionRecord]. The manifest envelope, the expected hash
and the crypto pin are finalization’s inputs and are already the client’s own — echoing them
to every listing would put a signed document in a response nobody reads it from.
| Field | Type | Description |
|---|---|---|
id | string | Required. The session id, which is what PATCH /v1/upload/{id} resumes against. |
asset_id | string | Required. The asset the bundle belongs to, so a client can group a bundle’s sessions. |
album_id | string | null | The album it is filed into, when it named one. |
blob_role | string | Required. This blob’s role in its bundle: original, derivative, metadata, provenance or backup. |
status | string | Required. Where the session is in its state machine. |
received_bytes | integer | Required. The committed prefix — where a client sending in order resumes. One that sends out of order reads the full committed set from HEAD’s X-Capsule-Committed. |
total_size | integer | Required. The declared total. |
created_at | string | Required. When the session was created, RFC 3339. |
last_progress_at | string | Required. When the last chunk was accepted, RFC 3339, or the creation time if none. What the survival floor is measured from, so a client can tell which of its stalled sessions is closest to being evicted. |
error_code | string | null | For a failed_processing session, the error.* code finalization failed with — the same code HEAD carries in X-Capsule-Upload-Error. Absent for every other state. |
SessionsResponse
Section titled “SessionsResponse”The listing.
| Field | Type | Description |
|---|---|---|
sessions | SessionSummary[] | Required. Every session the caller can resume, oldest first, ties broken by upload id. |
UploadCancelUnavailableProblem
Section titled “UploadCancelUnavailableProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
retry_after | integer | When the caller may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The client waits, then resumes from HEAD at the authoritative offset. |
UploadChunkConflictProblem
Section titled “UploadChunkConflictProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
committed | string | null | On error.upload.range_conflict, the session’s committed set as X-Capsule-Committed spells it, which the response also carries: comma-separated inclusive byte ranges. The client re-plans from it. Absent on every other conflict. |
retry_after | integer | null | When the caller may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. Set on error.upload.too_many_in_flight, and on range_conflict and too_fragmented when a range of the session is in flight. |
UploadChunkRateLimitedProblem
Section titled “UploadChunkRateLimitedProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
retry_after | integer | When the caller may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The client waits, then resumes from HEAD at the authoritative offset. |
UploadChunkStorageFullProblem
Section titled “UploadChunkStorageFullProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
retry_after | integer | When the caller may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The client waits, then resumes from HEAD at the authoritative offset. |
UploadChunkUnavailableProblem
Section titled “UploadChunkUnavailableProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
retry_after | integer | When the caller may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The client waits, then resumes from HEAD at the authoritative offset. |
UploadCreateRateLimitedProblem
Section titled “UploadCreateRateLimitedProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
retry_after | integer | When the caller may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The client waits, then resumes from HEAD at the authoritative offset. |
UploadCreateStorageFullProblem
Section titled “UploadCreateStorageFullProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
retry_after | integer | When the caller may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The client waits, then resumes from HEAD at the authoritative offset. |
UploadCreateUnavailableProblem
Section titled “UploadCreateUnavailableProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
retry_after | integer | When the caller may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The client waits, then resumes from HEAD at the authoritative offset. |
UploadHeadUnavailableProblem
Section titled “UploadHeadUnavailableProblem”An RFC 9457 problem detail.
| Field | Type | Description |
|---|---|---|
type | string | Required. |
title | string | — |
status | integer | Required. |
detail | string | — |
instance | string | — |
code | string | Required. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders. |
request_id | string | The UUIDv7 this server minted for the request, as the X-Request-Id header carries it. Quote it when reporting the failure: it names the request’s log lines. |
retry_after | integer | When the caller may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The client waits, then resumes from HEAD at the authoritative offset. |
WireBlobRole
Section titled “WireBlobRole”A blob’s role in its asset bundle, as the wire spells it.
A wire type of its own rather than a serde derive on [BlobRole]: the state ports’
records deliberately derive no serde traits, so that a record cannot be smuggled through a
store built for another. The mapping is one match in one direction.
One of: original, derivative, metadata, provenance, backup, derivative_manifest.