Providers & coverage
Coverage is a resource, not a claim on a marketing page. GET /v1/capabilities?product=… answers "can this account do X" — read it instead of hard-coding an assumption about a corridor, a country or a payment method. A second endpoint, GET /v1/eligibility, is specified for "could an account in this country generally do X", but it is closed in production (see Eligibility below).
Capabilities — what this account can do right now
GET /v1/capabilities?product=payment_links|payouts|payroll|buy_sell|wallet_bank returns, per product, the corridors or rails this specific authenticated account is actually eligible for — not a static list of everything Swaps theoretically supports.
Every corridor row states its own status honestly rather than a blanket "supported":
| Field | Meaning |
|---|---|
lifecycle | public (advertised), preview (soft-launched), or blocked |
public_claim_status | live, unverified, or planned — the honest gap between what's claimed and what's been probed |
executable | whether this account can execute today — a capability read is availability, not a green light to skip re-checking at the money boundary |
blocked_reason | present whenever executable is false, so an agent has something to act on instead of a bare no |
blocked_reason is an open enum: a client that meets a value it does not know treats the corridor as not executable and shows the reason as text. Two values name an environment or account fact rather than a missing provider:
blocked_reason | Where | What it says |
|---|---|---|
relay_requires_tempo_mainnet | product=payment_links, the crypto_relay corridor | The deployment settles on a Tempo test network (or the network cannot be resolved), and the payer page admits Relay only on Tempo mainnet. The corridor reads not_enabled with source_chains: [] whatever the Relay switch says. max_amount is still published while the per-invoice cap is set. |
collection_account_uses_currency | product=wallet_bank, the wallet_bank_virtual_account corridor | A Payment links collection account already receives this currency into the same wallet, so a new wallet bank account would only hand that one back. The corridor reads not_enabled with action: none. POST /v1/wallet/virtual_accounts for that currency answers 409 conflict. |
For product=payment_links the answer also carries fee, the Swaps fee the payer is charged on top of the invoice (you receive the full invoice), read from the same constant the charge uses: kind: "percentage", bps: 100, applies_to: "payer", rails: ["crypto_tempo", "crypto_relay"], rounding (floor) and rounding_decimals (6). A rail that is not in rails carries no fee claim from this object. The fee is a price, so it is published even while those corridors read not_enabled. See Payment links for what the payer is asked for.
There is also an unauthenticated public projection of capabilities (product-wide fee and corridor claims with no entitlement or per-account detail) for anyone building a comparison surface before a user signs up.
Availability is not permission
A capability answering executable: true is not authorization to move money. The server re-checks eligibility at create time and again at the money boundary (funding, activation, execution) — routing output is never chained straight into execution. See Agents & MCP → what a tool can never do.
Eligibility — what a country and account type could generally expect
GET /v1/eligibility is dark-flag and closed in production: it answers 503 temporarily_unavailable, and it stays closed until the public claims it makes are signed off. Do not build on it; for an authenticated account, read GET /v1/capabilities?product=… instead. What follows is the contract it will carry once it opens.
GET /v1/eligibility (public: country + customer type) answers a coarser, pre-signup question — "if someone in this country opened this kind of account, what would likely work" — using the same eligibility engine the dashboard's own onboarding reads, with its own four honest states:
likely_availableconditionalunavailableunknown
likely_available and conditional are never collapsed into one "available" bucket — an agent told a flat "available" for something the engine only called likely would tell an end user something the engine itself won't promise.
Providers behind a corridor
A capability row can name the provider handling a corridor (display_label, logo_url where relevant) — the point of the resource is honesty about whether a corridor works, not brand attribution. Swaps fans a request out across multiple connected providers per product (banking rails, on/off-ramp providers, DEX and CEX liquidity) and returns the best executable route; which provider actually serviced a given order is visible on that order's own record, not guessed from the corridor list.
Keeping this honest
Coverage claims drift when a provider's own availability changes faster than a document does. The KPI page tracks K12 — provider truth: capability rows whose claimed status disagrees with the last live probe, target zero stale claims older than 24 hours. If a corridor this page or the /v1/capabilities response describes turns out wrong, that is a defect against K12, not a documentation nuance.
Next: Products for what each product actually does with a resolved capability · Agents & MCP for how a tool reads this same resource.