Sync and blob fetch
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.
GET /v1/blob/{hash}
Section titled “GET /v1/blob/{hash}”Fetch a ciphertext blob by its content address, ranged.
Opaque octets: the server holds no key and this route never learns what it is serving. An
account fetches the blobs of its own assets and of the albums it is currently a member of; a
former member is told 403, and everyone else is told what an unknown address is told —
see [crate::serve] for the boundary and its reasons.
The one answer that is account-scoped is the transient 409: it reports the caller’s own
in-flight upload and nobody else’s (S-C40).
A federated peer fetches here with a capability instead of a session token (S-E5), through
the same resolution and the same authority.
Authentication: required — bearer.
| Parameter | In | Type | Description |
|---|---|---|---|
If-Modified-Since | header | string | The date the client’s copy carries, per RFC 9110 section 13.1.3. |
If-None-Match | header | string | The entity tag the client already holds, per RFC 9110 section 13.1.2. |
If-Range | header | string | The 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. |
Range | header | string | The 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. |
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. |
hash | path | string | Required. The blob’s ciphertext content address, lowercase hex. |
| Status | Body | Description |
|---|---|---|
200 | string 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. |
206 | string 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. |
304 | — | the client’s copy is current. Headers: ETag, Last-Modified, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
400 | CodedProblem application/problem+json | Bad Request. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
403 | CodedProblem application/problem+json | Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
404 | CodedProblem application/problem+json | Not found. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
409 | CodedProblem application/problem+json | Upload in progress. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
410 | CodedProblem application/problem+json | Gone. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
413 | — | the request body exceeds the configured limit. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
429 | CodedProblem application/problem+json | Rate budget exceeded. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
500 | CodedProblem application/problem+json | Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
GET /v1/sync
Section titled “GET /v1/sync”Returns the changes in the caller’s library after cursor.
Read-only and idempotent: two calls with the same cursor return the same page, because the cursor names a position rather than consuming one. That is what makes a lost response harmless and a retry free.
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. |
album_id | query | string | null | One album’s page rather than the caller’s own feed (S-C51). For the album’s owner or any account on its current roster. Positions are the owner’s sequence numbers filtered to the album, and the cursor is bound to (caller, album), so it cannot be presented on the caller’s own feed or on another album. Absent: the caller’s own library, as before. |
cursor | query | string | null | The opaque cursor a previous page returned. Absent means “from the beginning”. |
page_size | query | integer | null | How many entries to return. Clamped into the range this server serves. u32 and not usize: Kynos refuses to describe a platform-width integer, and it is right to — a schema whose bounds depend on the server’s pointer size is a schema no client can rely on. |
| Status | Body | Description |
|---|---|---|
200 | SyncPageResponse application/json | OK. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
400 | CodedProblem application/problem+json | Bad Request. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
401 | CodedProblem application/problem+json | Unauthorized. Headers: WWW-Authenticate, X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
403 | CodedProblem application/problem+json | Forbidden. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
413 | — | the request body exceeds the configured limit. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
429 | CodedProblem application/problem+json | Rate budget exceeded. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
500 | CodedProblem application/problem+json | Internal server error. Headers: X-Capsule-Min-Client-Build, X-Capsule-Protocol-Max, X-Capsule-Protocol-Min. |
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. |
SyncBlobRef
Section titled “SyncBlobRef”One blob an asset holds.
| Field | Type | Description |
|---|---|---|
role | WireBlobRole | Required. The blob’s role in the bundle. |
hash | string | Required. Its ciphertext content address, lowercase hex. |
size | integer | Required. Its size in bytes, so a client can budget a fetch before issuing one. |
SyncEntry
Section titled “SyncEntry”One change in a library.
| Field | Type | Description |
|---|---|---|
asset_id | string | Required. The asset that changed. |
album_id | string | Required. The album it belongs to. The client keeps its anti-rewind high-water mark per album. |
protocol_version | string | Required. The album’s pinned protocol date. A client refuses an entry above its own maximum rather than applying it partially. |
sync_seq | integer | Required. The entry’s position. Strictly increasing within a page, and therefore within any album the page touches. |
change | WireChangeKind | Required. What this is to the client that asked. |
manifest_cbor | string | null | The signed manifest, base64 of the provenance blob’s exact bytes (S-C30). Absent on a tombstone, and absent — with a loud server-side log — when the index names a provenance blob the store cannot produce. |
metadata_blob | string | null | The encrypted metadata blob’s content address. |
blobs | SyncBlobRef[] | Required. The asset’s original and derivative blobs. |
original_held | boolean | Required. Whether the original has landed. false is the derived awaiting-original state. |
changed_at | string | Required. When the change happened, RFC 3339. |
SyncPageResponse
Section titled “SyncPageResponse”A page of the feed.
| Field | Type | Description |
|---|---|---|
entries | SyncEntry[] | Required. The changes, in sync_seq order. |
next_cursor | string | Required. The cursor that resumes after the last entry. Always present, including on an empty page, where it re-mints the position the client arrived with. A client therefore never has to decide whether to keep its old cursor. |
has_more | boolean | Required. Whether the server holds changes beyond this page. Answered from the owner’s high-water mark rather than by fetching one more entry, so a caught-up client is told so without paying for a page it will not receive. |
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.
WireChangeKind
Section titled “WireChangeKind”What an entry is, relative to the client that asked for it.
One of: created, updated, deleted.