Skip to main content
The Rhinestone API is versioned. Pin a version via the x-api-version header and upgrade on your own schedule — new versions are additive and opt-in.

Why versioning

The API evolves as Rhinestone adds chains, settlement layers, and new intent patterns. Versioning lets us ship those changes without forcing every integrator to migrate in lockstep. We use dated versions (YYYY-MM.name) rather than semver-style major versions. Semver majors tend to hoard changes into rare, big-bang releases — each bump looks like a migration project, so teams avoid shipping them. Dated versions normalise small, frequent bumps, so each one carries a small diff. The .name suffix gives each release a human handle. We name versions after mountains, one per letter — alps, blanc, caucasus, and so on. It’s easier to say “switch to Caucasus” than “switch to 2026-09”.

Pinning a version

The direct HTTP guides use Caucasus. Pin it by sending x-api-version on every request, including submission and reads:
The format is YYYY-MM.name. Always send the header — requests without it fall back to the deprecated 2026-01.alps shape, and unknown or malformed values return 400 VALIDATION_ERROR.

Compatibility

What we can change without a new version

Within a version, we treat the response schema as open. These changes ship freely:
  • New optional request fields
  • New response fields
  • New enum variants in responses (e.g. a new settlementLayer)
  • New endpoints
  • Widened request validation
  • Changed default values

What your client must do

To consume those changes safely:
  • Ignore unknown fields. If you use a strict JSON parser (Go’s DisallowUnknownFields, Rust serde(deny_unknown_fields), Jackson’s FAIL_ON_UNKNOWN_PROPERTIES), disable it for our responses.
  • Handle unknown enum values gracefully. A switch on settlementLayer that throws on default will break the day we add a new one. Treat unknown values as “not supported by this client” and fall back.
  • Preserve native signing payloads. On Caucasus, dispatch on each signingRequests[].payload.kind and return proofs in the same order. For EIP-712, forward the supplied typedData to wallet.signTypedData() without reconstructing its types. See signing requests and proofs.
  • Treat quote 404s as normal. Quoted intents are stored server-side with a short TTL. If a quote expires or the quote store restarts, you’ll see 404 on submit. Re-quote — don’t retry the submit.
  • Take routes[0] unless you have your own criteria. The array is server-ranked by a cost/speed tradeoff. Re-sorting client-side usually degrades route quality.

What triggers a new version

  • Removing or renaming any field
  • Adding a required request field
  • Changing a field’s type
  • Restructuring request or response shape
  • Narrowing request validation
  • Making a required response field optional or nullable
  • Removing an endpoint

Deprecation lifecycle

Fields deprecated in version N remain present and documented as deprecated; they’re removed in N+1. Versions themselves are not routinely deprecated — each version is intended to stay live indefinitely so you never have to migrate on our clock. The one exception is 2026-01.alps, which will be sunset after integrators migrate to blanc. The shape difference between the two is large enough that maintaining both long-term isn’t practical. Future version transitions will follow the standard per-field deprecation rule.

Versions

2026-09.caucasus

Caucasus introduces per-VM accounts, explicit source and destination assets, native execution, and ordered signing requests and proofs. The endpoint paths stay the same:
  • POST /quotes
  • POST /quotes/estimate
  • POST /intents
  • GET /intents/{id}
  • GET /intents

Migrating from Blanc

This section covers direct HTTP integrations, not changes to the SDK’s methods or configuration. Pin Caucasus on every request, including submission and reads:
Keep API keys server-side. Your existing authentication method does not change. Changing the header alone is not enough: update request bodies, signing, and response parsing together. Requests without a version header still default to Alps. The examples below use application-defined postBlanc, postCaucasus, getBlanc, and getCaucasus HTTP helpers. Each sends the corresponding version header and rejects non-2xx responses.
Restructure quote requests
Caucasus names one funding pair in source and one delivery asset in destination. Replace source allowlists and destination token arrays with explicit chain and token fields.
This requests 10 USDC on Arbitrum, funded with Base USDC. It does not fix the input amount. If your Blanc integration relied on automatic or multi-source funding, choose the source chain/token pair before requesting a Caucasus quote. Do not translate an allowlist by silently taking its first entry. Amounts, caps, auxiliary funds, and EVM call values use decimal strings in their respective base units. For binding quotes:
  • source.maxAmount optionally caps the observed source balance available to the planner. It is not an exact-input amount.
  • destination.amount specifies the requested output. Omit it for max-out.
  • Omit destination.token only when there is no token delivery.
  • source.amount belongs to estimates, not binding quotes.
Preserve balance-credit semantics. For a self-send without destination execution, an existing destination balance can count toward the requested amount when it is also eligible as the funding source. The example selects Base USDC, so existing Arbitrum USDC does not reduce the requested delivery. Caps apply before auxiliary funds. Available funds are the capped observed balance plus the declared auxiliary amount—not the combined balance capped afterward. Source calls and auxiliary funds are currently EVM-only. Auxiliary funds remain an assertion that funds will be available by execution time, not a transfer performed by quoting. Source calls retain their pre-claim timing.
Configure accounts per VM
Replace the flat EVM account with account.evm. An address-only entry is a receiver, not a spending account: include type when the account must fund or execute the intent. signatureMode remains a numeric enum, not a string such as "ECDSA". Simulation stubs and setup operations belong to ERC-7579 accounts. Solana spending uses account.svm. For a standalone, already-created Swig:
address is the asset-holding wallet; swigAccount is the state account containing its roles. They are not interchangeable. P-256 authorities use kind: "secp256r1" with their compressed publicKey. You can supply EVM and SVM entries together, but this does not authorize arbitrary wallet pairings. The orchestrator checks the supported pairing, account identity, and signing authority.
Move destination execution
Group execution with its destination: For EVM calls:
Each EVM call still contains to, value, and data. Preserve call order. An explicit receiver is destination.recipient: { address }. Configured EVM recipients use the same lower-case account types and nested setup/delegation fields, but do not carry the spender’s signatureMode. Solana delivery requires a recipient. Solana execution instead runs from the configured Swig: omit recipient and encode any payee in the instructions. Tron and Stellar destinations are delivery-only. A request without source is restricted to no-delivery intents with effective sponsorship covering the applicable orchestrator costs. It cannot fall back to another account balance. Sponsorship does not fund arbitrary caller-authored EVM call value.
Read the quote plan and requirements
Blanc returns { routes }. Caucasus returns { status: "quoted", routes }.
Each route declares its purpose:
  • execution: token delivery or execution.
  • deployment: a separate account-creation intent.
Review plan.source, plan.destination, and plan.deployments before signing. Execution disclosures identify whether the account or a solver runs the caller’s calls. A plan describes intended behavior, not completed execution or every transaction-internal operation. requirements[] replaces the chain-keyed tokenRequirements map:
  • erc20Approval names the account, chain, token, amount, and spender.
  • wrapNative names the account, chain, token, and amount.
The array is always present. An empty array means no preflight requirement; status: "quoted" does not mean nonempty requirements are already fulfilled. Route ranking, expiry, and the existing cost.input, cost.output, and cost.fees structure remain. Caucasus presents same-chain routes as SAME_CHAIN, including smart-account routes that Blanc labelled INTENT_EXECUTOR. When present, bridgeFill.destinationChainId is a chain-reference string.
Sign requests and submit ordered proofs
Replace role-specific signature slots with one ordered array:
Every request includes its account, authority, scope, purpose, chain references, validity constraints, and native payload. Do not sort, deduplicate, or omit requests—even when two payloads are identical. Proof count, order, and kind must match the selected route’s requests. This example assumes preflight requirements are satisfied and every signing request uses the same EOA with EIP-712 signing, without EIP-7702 delegation:
For other signing paths, select the signer from the request’s authority and dispatch on payload.kind: For WebAuthn, send credentialId as base64url, authenticatorData as hex, the original UTF-8 clientDataJSON, and the P-256 signature as 64-byte hex r || s, not DER. Do not parse and serialize clientDataJSON again. For an account-verified origin request that needs two signature encodings, Blanc’s { preClaimSig, notarizedClaimSig } becomes:
This is one proof, not two. It is not accepted for every account-format request. Separate authorizations.sponsor and authorizations.recipient bags disappear. Answer the corresponding EIP-7702 requests in proofs[]. Caucasus requests concrete-chain authorizations; a configured delegation default is not an any-chain authorization proof. Honor every returned validity constraint as well as route expiry. A Solana slot deadline can expire before route.expiresAt. Never reconstruct or rewrite native signing payloads: their chain values retain native formats, including numeric EIP-712 and EIP-7702 chain IDs. Submission still returns { intentId }. That acknowledges submission, not completion. Poll the intent before starting a replacement when the submission outcome is uncertain.
Update sponsorship
Rename options.sponsorSettings to options.sponsorship:
The same rename applies to estimates. Fee flags retain their meanings; requesting sponsorship does not bypass authorization, policy, or available-budget checks. If you issue intent-bound sponsorship grants, update the approval binding too. The approved input is:
The digest is SHA-256 of the RFC 8785 canonical JSON representation, encoded as lowercase hex. Preserve supplied wire values, explicit false settings, and array order. Omit an absent source; use {} for absent options. Do not reuse a Blanc digest. The approval-contract identifier is distinct from the HTTP version header and must match exactly. See sponsorship for policy configuration.
Update intent reads
Continue polling GET /intents/{intentId}. Add ?full=true for extended details. Overall statuses remain PENDING, COMPLETED, and FAILED. For transaction links:
Dispatch transaction references by vm: Known chain references use strings such as eip155:8453 or solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp. Blanc quote requests already used chain-reference strings; its read/list projections used numeric chains. Historical records that cannot be mapped to a known chain can retain numeric chain IDs and vm: "unknown". Do not invent an EVM chain reference for them. Full details retain nonce in hex and add optional deployment summaries. Keep intentId as a string; it can exceed JavaScript’s safe integer range. Treat missing historical accounts, authorities, executions, or deployment data as unavailable—not as empty data or proof that nothing happened. Execution details describe intended execution, not per-call results. refunds: [] means no refund has been observed, not that a failed intent can never be refunded. A transaction reference alone is not proof of finality. Recorded cost amounts remain integer micro-USD. details.cost.sponsored describes recognized sponsorship coverage and can be true while billed amounts are zero or absent.
Update intent lists
GET /intents keeps its { data, pagination } envelope.
value.side distinguishes planned output from retained input. The summary is not a wallet balance change, realized swap result, or proof of delivery. value is omitted when no single amount truthfully represents the intent, including deployment-only and historical multi-token cases. Pass pagination.nextCursor back unchanged as cursor; it is not an intent ID. Caucasus lists can include non-EVM accounts that Blanc excludes, so identical pagination requests need not return identical records.
Migrate estimates
POST /quotes/estimate uses the same source/destination grouping, but its account descriptors are hypothetical. They contain account types, not wallet addresses or signing configuration.
Caucasus infers direction from exactly one amount: For exact-out, remove the source amount and set the destination amount:
Do not send direction, amountIn, or amountOut. Supplying both amount sides—or neither—is invalid. Estimate responses move financial fields into cost:
output likewise becomes cost.output[]. The response reports the account assumptions used. source.assumptions.deployed applies to the source ERC-7579 account. Omission assumes undeployed; the field is ignored for EOA and Swig accounts. Estimates do not accept quote-only caps, auxiliary funds, recipients, or execution. They do not apply actual destination-balance credit and return no executable intent ID or signing requests. Obtain a binding quote before signing or submitting.
Migrate HyperCore actions and outcomes
HyperCore is a native destination variant:
Use one ordered actions[] array. A former singular options.hyperCore.action becomes a one-element array. Keep caller-authored HyperEVM calls in execution.settlement, separate from Core actions. Preserve hypercore:spot versus hypercore:perp. Neither is interchangeable with HyperEVM’s eip155:999 settlement chain or a signing-domain chain ID. USDC delivery addressing and units remain unchanged. On reads, replace hyperCore.outcome with the aggregate venue operation:
HyperEVM transaction evidence remains separate. A list entry’s destinationChainId can name the HyperCore venue while value.chainId names HyperEVM. accepted means the exchange accepted the action, not that an order filled completely. Reconcile unknown and partial outcomes against HyperCore before retrying; blindly repeating a batch can duplicate successful orders.
Respect capability boundaries
A schema variant does not guarantee an available route. Chain/token support, account authority, settlement providers, sponsorship, and environment configuration still apply. A missing Swig needed for spending returns SOLANA_ACCOUNT_NOT_CREATED. Quoting does not silently create it. Separate sponsored Swig creation uses an ordinary status: "quoted" response with a purpose: "deployment" route. Rent is disclosed separately in deploymentCosts; signingRequests is empty and submission uses proofs: []. This is not automatic creation-plus-spend or a deploymentRequired/re-quote response. Creation trusts the supplied root authority: verify it before creating or funding the wallet. Do not assume it is safe to fund an undeployed Swig. Sponsored Swig authority changes are separate typed operations, not arbitrary caller instructions. Existing role permissions and lockout protections still apply.
Migration checklist
Before switching traffic:
  • Pin Caucasus on quote, estimate, submit, and read requests.
  • Select one funding pair and preserve the intended balance-credit behavior.
  • Review the route plan and fulfill preflight requirements.
  • Handle supported signing kinds without changing payloads or proof order.
  • Update intent-bound sponsorship bindings alongside request bodies.
  • Parse native transaction references and tolerate unavailable historical data.
  • Reconcile uncertain submissions and HyperCore outcomes before creating replacement intents.
Blanc remains a separate version. Do not reinterpret an existing quote’s signing data as a Caucasus response.

2026-04.blanc

The previous contract used by Blanc integrations. Keep this header when continuing to use Blanc request and response shapes; follow the Caucasus migration to upgrade. The endpoint reference documents Caucasus; Blanc’s schema is in the published 2026-04.blanc OpenAPI document. What changed:
  • Flat routes[] array. Each route carries its own intentId, cost, signData, and tokenRequirements (EOAs only — smart accounts handle approvals internally). Pre-ranked; routes[0] is recommended.
  • CAIP-2 chain ids. Every chain id on the wire is now an eip155:<chainId> string — 1 becomes "eip155:1". Affects scalar fields, arrays, and chain-keyed maps. Path parameters are unchanged.
  • EIP-712 typed data in the response. Forward signData.origin[] and signData.destination directly to wallet.signTypedData(). No more client-side type reconstruction.
  • Server-stored intents. POST /quotes returns an intentId; the full intent stays server-side. Submit via POST /intents with { intentId, signatures } — no more round-tripping intentOp.
  • Resource-style endpoints. POST /quotes (was /intents/route), POST /intents (was /intent-operations), GET /intents/:id (was /intent-operation/:id), POST /intents/splits (was /intents/split).
  • Flattened cost structure. One cost object per route with input, output, and fees: { total, breakdown }. Replaces scattered tokensSpent / tokensReceived / feeBreakdownUSD / gasCost / sponsorFee.
  • Submit response collapsed. POST /intents returns just { intentId } (was { result: { id, status } }). The synthesised status: "FAILED" is gone — simulation failures now surface as 4xx with the unified error envelope.
  • Field renames. Notable: destinationGasUnits → destinationGasLimit, sponsorSettings.{gas,bridgeFees,swapFees}Sponsored → {gas,bridgeFees,swapFees}, userAddress → accountAddress. Portfolio token shape uses symbol (was tokenName), chains (was tokenChainBalance), and per-chain address/decimals (were tokenAddress/tokenDecimals). Timestamps move from BigIntLike strings to integer Unix seconds.
  • Unified error envelope. All non-2xx responses share { code, message, traceId, details? }. Switch from message-pattern matching to code-based dispatch.
  • Schema trimming. Account.mockSignature is gone — use the per-chain Account.mockSignatures map. AccountType.SMART_ACCOUNT is gone — use ERC7579. The accountAccessList flat-array variant is gone — use the structured shape.
  • Compact / resource locks removed. No blanc equivalent for topupCompact, emissaryConfig, MultichainCompact origin signatures, or the /withdrawals endpoints.

Migrating from alps

Quote and submit
Signing
Submit response
Status polling
The status enum is narrower in blanc — legacy values that no longer apply are removed. PRECONFIRMED is gone; if your client branches on it, drop that case. Splits endpoint POST /intents/split → POST /intents/splits. Request and response shapes follow the same blanc-wide rules (CAIP-2 chain ids, unified error envelope). Chain ids CAIP-2 strings (eip155:<chainId>) replace numeric chain ids on every field that carries one — chainId, sourceChainId, destinationChainId, chainIds, allChainIds, and chain-keyed maps like auxiliaryFunds, preClaimExecutions, chainTokens, and tokenRequirements. Path parameters are unchanged.
The portfolio filter switches from comma-separated lists to repeated query parameters, with tokens keyed as chain:address:
Reading costs
Field renames Timestamps move from BigIntLike strings ("1700000000") to integer Unix seconds (1700000000). Sponsor settings
Account types and mock signatures AccountType.SMART_ACCOUNT is gone — use ERC7579. The flat accountAccessList array shape is gone — use the structured shape. Mock signatures move from a single Account.mockSignature to a per-chain Account.mockSignatures map.
Error handling
Honour Retry-After on 429 TOO_MANY_REQUESTS.

Error codes

The list is extensible — add unknown codes to a generic fallback path.

Things you can’t migrate

The Compact / resource-lock surface has no blanc equivalent. If your integration depends on topupCompact, emissaryConfig, the /withdrawals endpoints, or MultichainCompact origin signatures, stay on alps until a replacement ships.

2026-01.alps

The original release. Intents are round-tripped through the client, signed via client-reconstructed EIP-712, and submitted with the full intentOp attached to signedIntentOp. The Compact / resource-lock surface (topupCompact, emissaryConfig, /withdrawals, MultichainCompact signatures) is only available on this version — stay on alps if you depend on it.
Deprecated. Will be removed once existing integrations migrate to blanc. No new features will land on this version.