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/ordersThe 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 formt=<timestamp>,v1=<hex>, where the HMAC is computed over"${timestamp}.${body}". It is sent alongsidex-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.