Skip to main content

Compatibility and stability contract

What stays the same over time and what can change; for how to call the API today, see Conventions. The API is in beta and may still change. At general availability the contract becomes additive-only: existing fields and behavior are preserved, and changes arrive as new fields, new values, and new endpoints.

What clients must tolerate

  • Unknown fields. Responses may gain fields at any time without a version bump. Ignore the ones you do not recognize.
  • Unknown enum values. Fields such as joinMode and siteMode may gain values at any time. Do not assume a closed set.
  • Uninformative 404s. A resource the API will not serve returns the same 404 as one that does not exist, permanently; never read a 404 as evidence about existence. See Conventions § Errors and not-found.
  • A generated client ages. Types from the OpenAPI specification are a snapshot of a growing spec; exhaustive enum matching and closed response types break on additive changes.

Cursors

nextCursor and previousCursor are opaque. Store and pass them back unchanged; never parse, decode, or construct one. Their structure can change.

Identifiers

Entity ids (space_…, post_…) and protocol DIDs are canonical and stable for the entity's lifetime; a DID on the wire is did:dfos: followed by 31 characters and is opaque. Subdomains are mutable aliases — a space can change its domain, and a freed domain can later belong to a different space. Store ids or DIDs for durable references; use subdomains for display and links.

The authentication wire

  • The scheme token is DFOS, matched case-insensitively, followed by the request proof. It will not become Bearer.
  • The credential header is X-Credential.
  • The freshness window has a ceiling. A proof's acceptance window plus the clock-skew allowance never exceeds five minutes in total. Today's values are narrower and can move within that ceiling; do not hardcode them.
  • Growth is additive. Which routes are gated, and which actions a credential can carry, can grow; an anonymous route never quietly becomes a gated one. The signing rules are versioned by the DFOS API-AUTH specification.

Writing

A small set of routes write. Everything above applies to them; these are the additions. How to call them is Conventions § Writing.

  • Request bodies are closed. Responses tolerate unknown fields; requests do not. Naming a field this API does not serve is a 400, permanently. Send only the fields you mean, and add new ones only when they are documented.
  • 409 and 415 are permanent. A jti replayed inside its freshness window is always 409 Conflict. A body that is not uncompressed application/json is always 415 Unsupported Media Type. Neither becomes another status.
  • A read route never quietly starts writing. New write routes and new actions arrive as their own additions.

Media URLs

  • Public images (post covers, avatars, inline body images) — a permanent, unsigned CDN URL with no urlExpiresAt, valid while the media stays referenced by public content.
  • Private media (audio, video, file attachments) — a time-limited signed URL returned inline on the post response, carrying urlExpiresAt.

Never persist a signed URL. Re-fetch the post for fresh URLs; data responses are no-store (see Rate limits and caching), so a fresh fetch always returns fresh ones.

Errors

Error responses are machine-readable and documented in the OpenAPI specification. Read the body's error fields, not the status alone.