Documentation
OverviewQuickstartConceptsDecisions and errorsApprovalsVersioningSecurityExtensionsFAQPartner integration profileVersioning
Status: Draft 0.4, pre-release. Sources: Draft 0.4 sections 4.5 and 16, binding section 10,
SECURITY.md.
RCTP has three kinds of version number. The release says which code you have. The capability version says which protocol a gateway speaks. The UCP release says which version of the Universal Commerce Protocol RCTP builds on. They move for different reasons.
At a glance
| What | Current value | Where you see it |
|---|---|---|
| Specification | Draft 0.4 (adopted for v0.2, 27 October 2026) | spec/rctp-draft-0.4.md |
| Release tag | v0.2.0-draft.4 (the Starter profile of Draft 0.4) |
Git tags, CHANGELOG.md |
| TypeScript SDK | @rctp/sdk 0.2.0-draft.4, npm dist-tag draft (dry run: not yet published) |
npm install @rctp/sdk@draft once published |
| Python SDK | rctp 0.2.0a4, the PEP 440 form of the same release (dry run: not yet published) |
pip install --pre rctp once published |
| Go module | tag packages/gateway-go/v0.2.0-draft.4 (created at release) |
go get github.com/carousell/rctp/packages/gateway-go |
| Conformance runner | @rctp/conformance 0.2.0-draft.4 |
pnpm conformance |
| Capability version | 2026-11-draft5 (Draft 0.5; v0.2.0-draft.4 speaks 2026-11-draft4) |
RCTP-Version header, /.well-known/ucp, every file in registries/ |
| UCP release | v2026-08-25 (UCP Ask at commit f2626c2 until it is released) |
ucp.version (2026-08-25) in every UCP profile |
| Term sets | goods.small/1, vehicles/1 |
config.term_sets of dev.rctp.listing; the listing's term_set |
Release numbers
Releases follow semantic versioning 0.x, tagged with the draft number: v0.MINOR.PATCH-draft.N.
0.xmeans anything may change between minor releases. There is no stability promise before 1.0.-draft.Nnames the specification draft the release implements.v0.2.0-draft.4implements Draft 0.4;v0.1.0-draft.3implemented Draft 0.3.- Each new specification draft gets its own release tag.
- The SDKs, the gateway module and the conformance runner share one release number.
Capability version and capabilities
2026-11-draft5 names the protocol a gateway speaks: the year and month of the draft, and its number [4.5(3)]. It is
the version field of every registry file and of every RCTP capability entry in a UCP profile.
RCTP defines two capabilities of its own, both standalone UCP capabilities under the dev.rctp.* namespace:
| Capability | Covers | config in a gateway profile |
|---|---|---|
dev.rctp.listing |
Listing Terms and the listing.* verbs |
term_sets: the term sets the gateway enforces |
dev.rctp.deal |
Offers, acceptance, checkout and the deal record: offer.* and deal.* |
offer_expiry (default_seconds, max_seconds), offer_budget (per_agent, per_operator, window_hours) |
Each seller verb's scope sits under one of them, such as dev.rctp.listing:create or dev.rctp.deal:offer_accept.
Operators also use dev.rctp.operator (who they are) and dev.rctp.deal with config.webhook_url (where webhooks go)
in their own profiles.
UCP profile discovery
A gateway publishes its UCP profile at /.well-known/ucp (binding 10):
curl -s http://localhost:8080/.well-known/ucp
{
"ucp": {
"version": "2026-08-25",
"capabilities": {
"dev.ucp.common.identity_linking": [
{
"version": "2026-08-25",
"config": {
"scopes": { "dev.rctp.deal:offer_accept": { "default_tier": "ask", "allowed_tiers": ["ask", "auto"] } }
}
}
],
"dev.rctp.listing": [{ "version": "2026-11-draft5", "config": { "term_sets": ["goods.small/1"] } }],
"dev.rctp.deal": [
{
"version": "2026-11-draft5",
"config": {
"offer_expiry": { "default_seconds": 172800, "max_seconds": 604800 },
"offer_budget": { "per_agent": 3, "per_operator": 10, "window_hours": 24 }
}
}
]
}
},
"keys": [{ "kty": "EC", "crv": "P-256", "kid": "…", "x": "…", "y": "…" }]
}
(Abridged: the real profile lists every scope, and each RCTP entry also names its spec and schema.)
dev.ucp.common.identity_linking is a UCP capability, so its version is the UCP release, not the RCTP capability
version. Read the
scopes and tiers, the term sets and the limits from here rather than hard-coding them; the conformance runner does.
GET /.well-known/oauth-protected-resource (RFC 9728) names the marketplace authorization server.
The RCTP-Version header
Clients MAY send the version they speak as an RFC 9651 sf-string (binding 10):
RCTP-Version: "2026-11-draft5"
- The SDKs send it on every request.
- A gateway that does not serve the version answers
400with{"error": "unsupported_version", "message": "supported: …"}and noRCTP-Decisionheader. This check runs before anything else. - The header is optional. Without it, the gateway does not check the version.
The reference gateway on this branch serves 2026-11-draft5 only (versions in its configuration).
Support window and overlap
Draft 0.4 lets a deployment keep serving the previous capability version for at most 90 days after it starts
serving the new one [4.5(3)]. The v0.2 gateway does not speak 2026-10-draft3: a deployment that must keep it runs a
v0.1 gateway beside the v0.2 one for that window, then retires it. Security fixes land in every supported version
during the window (SECURITY.md).
| Version | Supported |
|---|---|
v0.2.0-draft.4 (Draft 0.4, 2026-11-draft4) |
Yes |
v0.1.0-draft.3 (Draft 0.3, 2026-10-draft3) |
For at most 90 days after a deployment moves to 2026-11-draft4, then no |
| Earlier drafts | No |
Deprecation policy
- Announce every deprecation in
CHANGELOG.md, with the date support ends. - Overlap. Keep the deprecated version working for the full window: at most 90 days.
- Registries only grow within a major version. Adding a registry value needs editor review. Removing one needs a
new major version [16] (
GOVERNANCE.md). - Experiments expire on their own. An
x-extension has an end date of at most two drafts or six months, and is removed or promoted by then. See Extensions. - Security fixes are not held back by the policy. They land in every supported version.
What counts as breaking
| Change | Breaking? |
|---|---|
| A new registry value (verb, reason, checkpoint, level, term set) | No, but agents must handle an unknown value safely: an unknown verb is never allowed, and an unknown reason is a refusal |
| A registry value removed | Yes: needs a new major version |
| A new required field in an object | Yes |
| A new optional field in an object | Treat it as breaking: schemas are closed (additionalProperties: false), so an older validator rejects the new field |
| A changed term set | Yes: a new term set version (such as goods.small/2). A listing records the version it was approved under [6.2] |
| A wire-format change in the binding (headers, signature profile, challenge) | Yes: new capability version |
Source: docs/versioning.md