Get startedVersioning

Versioning

Path versioning

The API is versioned in the URL path. Every route lives under /v1:

https://api.ruo.pro/v1/tenants/{tenant}/catalog/products
https://api.ruo.pro/v1/my/credentials
https://api.ruo.pro/v1/merchant/orders

The major version in the path is the compatibility contract. Within /v1, changes are additive: new endpoints, new optional request fields, and new response fields may appear without a version bump, so your integration must tolerate unknown response fields rather than breaking on them. A change that would break an existing /v1 caller — removing a field, renaming one, tightening a validation — is not made in place; it lands under a new major path.

The OpenAPI spec

The full API surface is described by an OpenAPI 3.1.0 document. The typed SDK (@dscodotco/sdk) is generated from that same document and ships its types prebuilt — a wrong path, query field, or body field is a compile error rather than a runtime surprise. As an external consumer you never generate anything; updating the package brings the types that match its API surface.

The document’s info.version tracks the spec’s own revision independently of the /v1 path version. Treat the /v1 path as the compatibility promise and the spec version as a finer-grained marker of which revision of the document you are reading.

Deprecation stance

Deprecations are handled conservatively: an old behavior is kept working alongside its replacement through a migration window, clearly marked deprecated, and only removed after that window closes. New integrations should adopt the replacement from the start.

Worked example — webhook signature headers

Outbound webhook signing is the concrete example of this policy in practice. Every delivery is signed two ways at once:

  • x-webhook-signature — the legacy scheme: a bare hex HMAC-SHA256 of the raw request body. It has no notion of time, so a captured delivery could replay forever against a receiver that only checks this header. It is deprecated.
  • x-webhook-signature-v1 — the versioned replacement, in the form t=<timestamp>,v1=<hex>, where the HMAC is computed over "${timestamp}.${body}". It is sent alongside x-webhook-timestamp (unix seconds at delivery-attempt time, bound into the signature). A retry gets a fresh timestamp and therefore a fresh signature, so a receiver can reject stale deliveries and close the replay hole.

Both headers ride every delivery during the migration window, so receivers that verify the legacy x-webhook-signature keep working while they migrate. The legacy header will be removed after the deprecation window closes.

New integrations must verify x-webhook-signature-v1 only. Verify the timestamp is recent, recompute HMAC-SHA256(secret, "${timestamp}.${body}"), and compare it against the v1= value before trusting the payload. Do not build anything new on the deprecated bare-hex header.

This is the pattern to expect for every deprecation: both old and new shipped together, the old one marked and dated, and a window before removal — never a silent break in place.