Skip to content

Guest drops

Stable

Generated 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.

Open a drop session through a link.

Invariants 26–30 in order: the link admits the file and reserves its caps in one store operation, then the owner’s quota is charged, then the declaration is checked. A drop the owner’s quota will not admit is 403 error.quota.exceeded, or 403 error.quota.suspended while the operator has suspended the owner’s quota.

Authentication: none.

ParameterInTypeDescription
opaque_idpathstringRequired. The opaque id.

Request body (required, application/json): CreateDropRequest

StatusBodyDescription
201CreateDropResponse
application/json
A drop session is open and accepting chunks. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
400CodedProblem
application/problem+json
Bad Request; Malformed drop. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
403CodedProblem
application/problem+json
Passphrase required; Quota exceeded; Quota suspended. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
404CodedProblem
application/problem+json
Not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
409CodedProblem
application/problem+json
Link capacity exhausted. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
413FileTooLargeProblem
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.
415CodedProblem
application/problem+json
Unsupported Media Type. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
422CodedProblem
application/problem+json
Unprocessable Entity. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
425CodedProblem
application/problem+json
Too early. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
429DropRateLimitedProblem
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.
500CodedProblem
application/problem+json
Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.

Report a drop session’s state, and its deposit’s outcome once it has one.

The completing chunk is answered waiting_for_processing before the deposit’s re-hash runs, so this is where a guest learns whether the drop was filed or refused: completed, or failed_processing with the deposit’s error.* code. A guest polls it with backoff.

Authorized exactly as a chunk is: the link’s opaque id, live for chunks, plus a session that is a drop under that link’s owner. Read-only — it starts nothing, so polling it cannot change what it reports — and it charges no limiter: it reveals nothing the holder of the two ids does not already own, and a poll spending the per-source budget would refuse the guest’s next drop.

Authentication: none.

ParameterInTypeDescription
opaque_idpathstringRequired. The opaque id of the link the session belongs to.
upload_idpathstringRequired. The session id.
StatusBodyDescription
200DropStatusResponse
application/json
The drop session’s state. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
400CodedProblem
application/problem+json
Bad Request. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
404CodedProblem
application/problem+json
Not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
413CodedProblem
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.
500CodedProblem
application/problem+json
Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.

Append one chunk to a drop session.

The link is the credential: possession of the opaque id, plus a session that belongs to it. Everything after that is [crate::upload::chunk::write_range] — the album path’s own function.

Authentication: none.

ParameterInTypeDescription
X-Capsule-Checksumheaderstring | nullThe chunk’s SHA-256, bare lowercase hex. Required: the idempotency tuple is undefined without it.
X-Capsule-Offsetheaderstring | nullWhere in the blob this chunk starts.
opaque_idpathstringRequired. The opaque id of the link the session belongs to.
upload_idpathstringRequired. The session id.

Request body (required, application/octet-stream): string

StatusBodyDescription
204—the request succeeded and there is no content to send. Headers: X-Capsule-Min-Client-Build, X-Capsule-Offset, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Capsule-Upload-Status, X-Request-Id.
400CodedProblem
application/problem+json
Bad Request; Malformed request; Malformed chunk. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
404CodedProblem
application/problem+json
Not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
408CodedProblem
application/problem+json
Request timeout. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
409CodedProblem
application/problem+json
Chunk refused. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
413CodedProblem
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.
415CodedProblem
application/problem+json
Unsupported media type. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
425CodedProblem
application/problem+json
Too early. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
500CodedProblem
application/problem+json
Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
503DropChunkUnavailableProblem
application/problem+json
Service unavailable. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
507DropChunkStorageFullProblem
application/problem+json
Insufficient storage. Headers: Retry-After, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.

The caller’s pending drops.

Authentication: required — bearer.

ParameterInTypeDescription
X-Capsule-Crypto-SuiteheaderintegerThe crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400.
X-Capsule-ProtocolheaderstringRequired. 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-SchemaheaderintegerThe sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400.
StatusBodyDescription
200InboxResponse
application/json
OK. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
400CodedProblem
application/problem+json
Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
401CodedProblem
application/problem+json
Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
403CodedProblem
application/problem+json
Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
413CodedProblem
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.
500CodedProblem
application/problem+json
Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.

Provision an upload link.

A link is metadata growth: an owner past their quota grace window is refused 403 error.quota.grace_locked, and one whose quota the operator suspended 403 error.quota.suspended.

Authentication: required — bearer.

ParameterInTypeDescription
X-Capsule-Crypto-SuiteheaderintegerThe crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400.
X-Capsule-ProtocolheaderstringRequired. 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-SchemaheaderintegerThe 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): ProvisionLinkRequest

StatusBodyDescription
201ProvisionLinkResponse
application/json
The upload link is provisioned and accepting drops. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
400CodedProblem
application/problem+json
Bad Request; Malformed upload link; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
401CodedProblem
application/problem+json
Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
403CodedProblem
application/problem+json
Forbidden; Quota grace expired; Quota suspended. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
413CodedProblem
application/problem+json
Payload 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.
415CodedProblem
application/problem+json
Unsupported Media Type. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
422CodedProblem
application/problem+json
Unprocessable Entity. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
425CodedProblem
application/problem+json
Too early. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
426CodedProblem
application/problem+json
Protocol version unsupported. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
500CodedProblem
application/problem+json
Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.

Revoke one of the caller’s links.

Never consults the quota: a revocation frees nothing but is admitted in every state, suspended and past the grace window included.

Indistinguishable and idempotent, for the same reason a share revocation is: saying “there was nothing to revoke” would be a lookup.

Authentication: required — bearer.

ParameterInTypeDescription
X-Capsule-Crypto-SuiteheaderintegerThe crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400.
X-Capsule-ProtocolheaderstringRequired. 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-SchemaheaderintegerThe sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400.
opaque_idpathstringRequired. The opaque id.
StatusBodyDescription
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.
400CodedProblem
application/problem+json
Bad Request; Malformed upload link; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
401CodedProblem
application/problem+json
Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
403CodedProblem
application/problem+json
Forbidden; Quota grace expired; Quota suspended. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
413CodedProblem
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.
425CodedProblem
application/problem+json
Too early. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
426CodedProblem
application/problem+json
Protocol version unsupported. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
500CodedProblem
application/problem+json
Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.

Discard a pending drop.

The bytes become unreferenced and the collector reclaims them; the link’s cap is not refunded, because the drop did happen — a guest deposited a file and the owner chose not to keep it, which is not the same as a link slot never having been used.

Authentication: required — bearer.

ParameterInTypeDescription
X-Capsule-Crypto-SuiteheaderintegerThe crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400.
X-Capsule-ProtocolheaderstringRequired. 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-SchemaheaderintegerThe sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400.
drop_idpathstringRequired. The drop’s identifier.
StatusBodyDescription
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.
400CodedProblem
application/problem+json
Bad Request; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
401CodedProblem
application/problem+json
Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
403CodedProblem
application/problem+json
Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
404CodedProblem
application/problem+json
Not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
413CodedProblem
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.
425CodedProblem
application/problem+json
Too early. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
426CodedProblem
application/problem+json
Protocol version unsupported. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
500CodedProblem
application/problem+json
Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.

Adopt a pending drop into an album.

Invariant 32. The manifest re-runs the create battery — a drop that skipped it would be the one write on this server that entered an album unvalidated — and its ciphertext_hash must name a blob in the caller’s own inbox, which is what stops an adoption from minting an asset over somebody else’s bytes.

The row is claimed, written, then settled. Across two ports there is no transaction, and the two failure directions are not equal: writing first and deleting after can duplicate a photo, taking first and failing to write loses one. A claim leaves a crash visible in the owner’s own inbox instead, marked adopting.

Authentication: required — bearer.

ParameterInTypeDescription
X-Capsule-Crypto-SuiteheaderintegerThe crypto suite id from the primitives inventory. Sent on writes; a suite this server does not implement is refused with 400.
X-Capsule-ProtocolheaderstringRequired. 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-SchemaheaderintegerThe sidecar schema version declared at sidecar_schema field 0. Sent on metadata updates; a schema newer than this server indexes is refused with 400.
drop_idpathstringRequired. The drop’s identifier.

Request body (required, application/json): AdoptRequest

StatusBodyDescription
200AdoptResponse
application/json
OK. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
400CodedProblem
application/problem+json
Bad Request; Adoption refused; Malformed handshake. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
401CodedProblem
application/problem+json
Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
403CodedProblem
application/problem+json
Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
404CodedProblem
application/problem+json
Not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
413CodedProblem
application/problem+json
Payload 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.
415CodedProblem
application/problem+json
Unsupported Media Type. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
422CodedProblem
application/problem+json
Unprocessable Entity. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
425CodedProblem
application/problem+json
Too early. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
426CodedProblem
application/problem+json
Protocol version unsupported. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
500CodedProblem
application/problem+json
Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.

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.

The owner’s signed create over a drop already in their inbox.

The same shape a POST /v1/upload create carries, minus everything about transferring bytes: the blob is already committed, so there is no size to negotiate and no session to open. What remains is the manifest, which is the whole point — a drop becomes an asset only when the owner signs for it.

FieldTypeDescription
album_idstringRequired. The album to adopt into.
asset_idstringRequired. The asset the drop becomes.
sizeintegerRequired. The blob’s declared size — the inbox row’s, restated and checked against it.
hashstringRequired. The ciphertext hash, which must name this drop’s blob.
content_typestringRequired. The declared content type.
crypto_suite_idintegerRequired. The crypto suite.
protocol_versionstringRequired. The protocol version the manifest is written against.
key_modestringRequired. How the asset’s key is carried. derived or wrapped (invariant 32).
manifest_envelopeManifestEnvelopeRequired. The signed manifest envelope, verbatim.

What adoption produced.

FieldTypeDescription
asset_idstringRequired. The asset the drop became.

An RFC 9457 problem detail.

FieldTypeDescription
typestringRequired.
titlestring—
statusintegerRequired.
detailstring—
instancestring—
codestringRequired. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders.
request_idstringThe 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.

A guest’s declared drop.

No album_id, no amk_version, no manifest, no provenance. deny_unknown_fields is what enforces invariant 30’s absence clause: a drop that names an album is a 400 rather than a field the server quietly ignores, because ignoring it would let a guest believe they had written into an album.

FieldTypeDescription
content_typestringRequired. The declared content type, from the link’s pinned protocol enum (invariant 27).
sizeintegerRequired. The ciphertext’s total length.
ciphertext_hashstringRequired. The lowercase-hex SHA-256 finalization verifies against.
kem_ctstringRequired. K encapsulated to the link’s Drop Key, base64. Length fixed by the suite (invariant 30).
passphrase_proofstring | nullThe Argon2id proof for a passphrase-gated link, base64. Required exactly when the link carries a verifier, and absent otherwise. The passphrase itself is never transmitted: what travels is the derived proof, and the KDF’s cost is what rate-limits guessing on top of the per-link limiter. It gates a write and adds no confidentiality — the guest already encrypts every asset. What it limits is who may spend the owner’s quota (Web Upload).
suggested_filenamestring | nullGuest-supplied and unverified. Advisory only.

The session a guest uploads into.

FieldTypeDescription
upload_idstringRequired. The session id, and the last path segment of the chunk endpoint.
suggested_chunk_sizeintegerRequired. The chunk size to start with.

An RFC 9457 problem detail.

FieldTypeDescription
typestringRequired.
titlestring—
statusintegerRequired.
detailstring—
instancestring—
codestringRequired. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders.
request_idstringThe 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_afterintegerWhen the guest may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The guest waits, then resends the same chunk at the same offset.

An RFC 9457 problem detail.

FieldTypeDescription
typestringRequired.
titlestring—
statusintegerRequired.
detailstring—
instancestring—
codestringRequired. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders.
request_idstringThe 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_afterintegerWhen the guest may retry, as Unix seconds; the Retry-After header carries the same instant as a delay. The guest waits, then resends the same chunk at the same offset.

An RFC 9457 problem detail.

FieldTypeDescription
typestringRequired.
titlestring—
statusintegerRequired.
detailstring—
instancestring—
codestringRequired. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders.
request_idstringThe 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_afterintegerWhen the caller may retry, as Unix seconds. From the limiter’s own window when a budget is spent, and an upper bound of one window when the limiter is at capacity.

What a guest’s drop session is doing, as its status probe reports it.

The session’s own state and nothing else: no drop id, no owner, no link totals. Every field is one the guest already holds or is owed — the bytes they sent, the size they declared, and the outcome of the deposit they started.

FieldTypeDescription
statusstringRequired. Where the session is in its state machine: pending, uploading, waiting_for_processing while its deposit runs, then completed once the drop is in its owner’s inbox, or failed_processing once the deposit refused it.
received_bytesintegerRequired. Bytes durably accepted so far — the offset a resumed upload continues from.
total_sizeintegerRequired. The declared total.
error_codestring | nullFor a failed_processing session, the error.* code the deposit failed with. Absent for every other state.

An RFC 9457 problem detail.

FieldTypeDescription
typestringRequired.
titlestring—
statusintegerRequired.
detailstring—
instancestring—
codestringRequired. The stable error.* catalog code. The client localizes this; detail stays English. Present on every problem this server renders.
request_idstringThe 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.
limitintegerThe largest file this drop link accepts, in bytes.

One drop waiting for the owner.

FieldTypeDescription
drop_idstringRequired. The drop’s identifier, which adoption and discard name.
opaque_idstringRequired. The link it arrived through.
ciphertext_hashstringRequired. The ciphertext’s content address.
sizeintegerRequired. How many bytes.
content_typestringRequired. The guest’s declared content type.
kem_ctstringRequired. K encapsulated to the link’s Drop Key, base64. The owner decapsulates.
suggested_filenamestring | nullGuest-supplied and unverified. A guest chose this text. A client rendering it treats it as untrusted input — it is the one field on this surface an anonymous party authored.
received_atstringRequired. When it landed, RFC 3339.
adoptingbooleanRequired. Whether an adoption currently holds this row. Surfaced rather than hidden: a crash between claim and settle leaves a row here, and an owner who cannot see it cannot act on it.

The owner’s pending drops.

FieldTypeDescription
dropsInboxEntryResponse[]Required. Everything waiting, oldest first.

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.

FieldTypeDescription
crypto_suite_idintegerRequired. The crypto suite the blob was sealed under. Must equal the top-level declaration.
protocol_versionstringRequired. The protocol date the manifest was written under (YYYY-MM-DD).
album_idstring | nullThe album the asset belongs to. Must equal the top-level declaration.
file_idstringRequired. The asset this blob belongs to — the same id across the bundle’s members.
amk_versionintegerRequired. The album-key epoch the manifest was written under.
ciphertext_hashstringRequired. 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_sizeintegerRequired. The plaintext length the manifest commits to.
chunk_sizeintegerRequired. The STREAM plaintext chunk size.
key_modestringRequired. derived or wrapped.
metadata_blob_hashstring | nullThe content hash of the bundle’s metadata blob, when the manifest commits to one.
original_blob_hashstring | nullThe 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_rolestring | nullThe 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_formatstring | nullThe 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_userstringRequired. The account that created the asset.
created_by_devicestringRequired. The device that created it, as a UUID — invariant 7’s subject.
client_versionstringRequired. The client build that wrote the manifest.
timestampstringRequired. The manifest’s self-asserted RFC3339 timestamp — invariants 7 and 8’s subject.
actionstringRequired. The lifecycle action. create or replace on this surface — the two that move blob bytes — and see [GateReject::ActionNotAllowed] for the rest.
prior_provenance_hashstring | nullThe provenance chain position this write continues from.
retention_untilstring | nullThe retention floor the manifest carries, when it carries one.

A link the owner is provisioning.

FieldTypeDescription
opaque_idstringRequired. The 128-bit opaque id, 32 lowercase hex characters, from the client’s CSPRNG.
drop_pubkeystringRequired. The Drop Key’s public half, base64. Opaque here — the server never decapsulates.
crypto_suite_idintegerRequired. The suite a drop must be sealed under.
expires_atstring | nullWhen the link stops accepting drops, RFC 3339.
max_total_bytesinteger | nullCumulative bytes across every drop on this link.
max_file_countinteger | nullHow many files the link may deposit.
max_file_sizeinteger | nullThe largest single file.
single_usebooleanWhether the link dies after its first successful drop.
passphrase_verifierstring | nullAn Argon2id verifier, base64, when the link is passphrase-gated. A verifier and never a passphrase: this is an abuse gate the server checks, which is why it is stored here at all — unlike a share link’s passphrase, which protects decryption and which the server never sees in any form.

Confirmation that a link is live.

FieldTypeDescription
opaque_idstringRequired. The opaque id, echoed.