Skip to content

Share links

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.

What a viewer needs to begin, for a live link.

Authentication: none.

ParameterInTypeDescription
opaque_idpathstringRequired. The opaque id.
StatusBodyDescription
200SharedMetadataResponse
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. 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.
429ShareMetadataRateLimitedProblem
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.

Ciphertext for one of the link’s blobs, ranged.

The membership check is the security property: a link serves the addresses its record enumerates and nothing else, so it cannot be walked sideways into the album’s unstripped metadata. A blob the link does not name is the same 404 as a link that does not exist.

A delivery that carries bytes is recorded in the owner’s activity log, aggregated: one share_link.served per link per window, naming the link and never the blob, and written off the response path so it neither slows nor refuses the serve.

Authentication: none.

ParameterInTypeDescription
If-MatchheaderstringThe entity tag the client’s copy was taken from, per RFC 9110 section 13.1.1.
If-Modified-SinceheaderstringThe date the client’s copy carries, per RFC 9110 section 13.1.3.
If-None-MatchheaderstringThe entity tag the client already holds, per RFC 9110 section 13.1.2.
If-RangeheaderstringThe entity tag the client’s partial copy came from, per RFC 9110 section 13.1.5. The Range is honoured only if it matches this representation under the strong comparison; otherwise the whole representation is sent.
If-Unmodified-SinceheaderstringThe date the client’s copy carries, refused if the representation changed since, per RFC 9110 section 13.1.4.
RangeheaderstringThe part of the representation to transfer, per RFC 9110 section 14.2. A field this operation cannot apply is ignored and the whole representation is sent. Example: bytes=0-1023.
hashpathstringRequired. The blob’s content address.
opaque_idpathstringRequired. The opaque id.
StatusBodyDescription
200string
application/octet-stream
the whole representation. Headers: Accept-Ranges, ETag, Last-Modified, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
206string
application/octet-stream
the part the request asked for. Headers: Accept-Ranges, Content-Range, ETag, Last-Modified, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
304—the client’s copy is current. Headers: ETag, Last-Modified, 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.
412—the representation is not the one the client’s copy came from. 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.
416CodedProblem
application/problem+json
Range Not Satisfiable. Headers: Content-Range, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
429ShareBlobRateLimitedProblem
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.

The passphrase-wrapped scope material, when there is one.

The octets the issuer registered as wrapped_secret, byte for byte. A viewer fetches this only for a passphrase-protected link; a link with no passphrase carries its scope in the sealed metadata blob instead.

A link with no passphrase answers 404 rather than 204 or an empty body: whether a link is passphrase-protected is already disclosed by the metadata record, and a second way to ask the same question with a different shape is a second thing to keep consistent.

Authentication: none.

ParameterInTypeDescription
opaque_idpathstringRequired. The opaque id.
StatusBodyDescription
200string
application/octet-stream
OK. 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.
429ShareSecretRateLimitedProblem
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.

Register a share link the caller’s client has issued.

A link is metadata growth: an account past its 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): IssueShareRequest

StatusBodyDescription
201IssueShareResponse
application/json
The share link is registered and servable. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min, X-Request-Id.
400CodedProblem
application/problem+json
Bad Request; Malformed share 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 exceeded; 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.

Idempotent from the caller’s side and indistinguishable: a link that was never theirs, a link that does not exist, and a link they already revoked are all 204. Revocation is the one operation where 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 share 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 exceeded; 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.

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.

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 link the owner’s client has issued.

FieldTypeDescription
opaque_idstringRequired. The 128-bit opaque id, 32 lowercase hex characters, drawn from the client’s CSPRNG. Minted by the client rather than the server because the client is what knows the fragment secret the id is paired with; the server checks its shape and stores it.
metadata_hashstringRequired. The metadata blob a viewer starts from. Must appear in serves. The blob is the issuer’s sealed share metadata record (share-metadata/v1, built by capsule_core::sharing::publish_share), opaque to this server.
servesstring[]Required. Every blob this link may serve, and nothing else. Enumerated by the issuing client, which is what makes the boundary-crossing strip stick: the client points the link at blobs it prepared for export, and the server has no path from an opaque id to anything outside this set.
wrapped_secretstring | nullThe passphrase-wrapped scope material, base64, when the link is passphrase-protected. Opaque to this server. The passphrase never crosses the wire — unwrap is client-side. Absent for a link with no passphrase, whose scope travels inside the sealed metadata blob.
expires_atstring | nullWhen the link stops being live, RFC 3339. Absent means no expiry.
metadata_blobstring | nullThe sealed metadata record itself, base64. Its SHA-256 must equal metadata_hash, and it may be at most 8 MiB decoded. The server stores it before it records the link, so a viewer’s first fetch finds it, and keeps it for as long as the link is live. It counts against the caller’s storage quota, and is refused when its new bytes would carry the account to its hard limit. Opaque to this server: it is sealed under material derived from the URL fragment, which never reaches it. Optional so an older client still registers a link; such a link serves its metadata only if the blob is already in the store.

Confirmation that a link is now servable.

FieldTypeDescription
opaque_idstringRequired. The opaque id, echoed.

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.

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.

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 viewer needs to start.

FieldTypeDescription
metadata_hashstringRequired. The metadata blob’s content address; fetch it from /s/{opaque_id}/blob/{hash}.
passphrase_protectedbooleanRequired. Whether a passphrase is required before the scope material can be opened. The one property of the link this path discloses, and it has to: a viewer cannot know to ask for a passphrase otherwise. It says nothing about what the link points at.