Fixed
- AML screening person shapes (guide): the screening
engine requires
date_of_birthas a{year, month, day}object (the plain"YYYY-MM-DD"string returns422),nationalityas an array of ISO-3166 codes andpersonal_identification[]as{ "issuing_country", "number" }without atypefield. Guide and spec examples updated with the live-verified shapes.
Added
- QR Crypto POS — amount-bearing crypto QR charges for processors (guide):
company accounts operating physical POS terminals register their
merchants as verified merchants (approved third-party KYB/KYC) and
generate crypto charges (USDT, USDC, BTC) with an exclusive address and
QR per sale. Early payment detection for the POS (
confirmingwithin seconds), credit with automatic conversion to the settlement asset, per-merchant attribution on charges/webhooks, a reconciliation summary (GET /v1/pos/summary) with the informative per-merchant commission and the net to distribute, and refunds over the crypto withdrawal rail with a hard cap (never more than received). New routes under/v1/pos/*(QR Crypto POS tag in the API Reference); partial payments accumulate and late payments into an expired charge are still credited.
Fixed
- Bitcoin crypto QR: the checkout QR now carries the raw bech32
address (same as TRON/ETH). Exchange apps like Binance rejected the
BIP-21 URI (
bitcoin:…?amount=…) as “invalid QR”; the exact amount remains shown next to it with a copy button. - Checkout page: white-label favicon (org symbol) and panel copy no
longer splits Spanish words mid-word (“momento” → “moment”/“o”) — the
aggressive
word-breaknow applies only to monospace addresses.
Added
- Dedicated CLABE per checkout link (Mexico): materializing
bank_transferMX on a universal checkout link now issues (or takes from a recyclable pool) a CLABE exclusive to that link. The payer transfers the exact amount with no reference: the deposit is detected and routed to the link automatically by destination account. The materialization payload carriesdestinationwithdedicated: true; if the dedicated account cannot be issued, it degrades to the classic path (merchant account + mandatoryreferencein the transfer description). CLABEs are recycled with a cooldown once the link resolves (paid or expired).
Added
- Pull collections on the universal checkout link (Venezuela): the
checkout page now offers methods that charge the payer’s account
directly (
c2panddebito_inmediatoin VE). The payer fills in bank, document, phone or account and the OTP on the same page; the amount is always the one frozen at quote time. New public endpoints:POST /pay/{token}/collect/otp(requests the key when the rail sends it on demand) andPOST /pay/{token}/collect(runs the charge; if the rail confirms synchronously the link is settled in the same call). These methods arrive withcollect: truein theGET /pay/{token}/quotecatalog. - Multi-currency fiat per country: each country in the quote lists
its corridors in
options[]— one row per method+currency (e.g. Bolivia with QR in BOB and USD) with itslocal_amountincountry_quote. Materializing a method offered in several currencies requires¤cy=YYY(the400 currency_requirederror now applies to any method, not just cards). - Destination account on bank transfers: when the corridor uses a
dedicated deposit account (the CLABE in Mexico), the
bank_transfermaterialization includesdestination(type, account number and beneficiary) besides the reference — the payer knows where to send the transfer without leaving the page.
- SVG flags on the payment page: country and currency flags are now SVG images (consistent across Windows, macOS and mobile; some systems used to render the country code as plain text). On the Card tab the flag is derived from the charge currency (USD → United States flag, even when the acquirer sits in another country).
- The checkout page no longer replies
429 too_many_attemptsjust for being open: the read, materialization, OTP and collect traffic limits are now independent from each other.
Added
- Card tab on the universal payment link: card payments move out of
the Fiat tab into their own tab, listed by charge currency (today
BOB and USD; currencies from future acquirers show up on their own).
GET /pay/{token}/quotereturns the newcards[]catalog (country, currency andlocal_amountper option) andcountries[]no longer listscardamong the methods. Materializing a card requires the currency:POST /pay/{token}/methods/card?country=XX¤cy=YYY— without it the new400 currency_requirederror is returned. Each currency is an independent materialization with its own hosted payment page.
- Payment page with a stronger visual identity: asset logos (USDT, USDC, BTC, GOLD) next to the amount and on the crypto groups, country flags on the Fiat selector and the card rows, per-method icons, and a prominent expiry timer (clock pill; under 1 hour it shows a countdown and under 10 minutes it turns red).
- The checkout page no longer scrolls by itself to the active panel every few seconds: the automatic refresh re-renders only when the data changed and never moves the scroll (only manually selecting a method brings the detail into view).
Changed
- Universal checkout payment page redesigned: the options are now
organized into three tabs — CBPay (merchant QR + alias, with a copy
button), Crypto (coins grouped by network; new networks show up on
their own once enabled) and Fiat (country selector + methods with
the quoted local amount). Copy buttons on the alias, addresses, amounts
and references. No API changes: the URL, the creation contract and the
public endpoints (
/state,/quote,/methods/{method}) are the same.
Fixed
- QR payout — validation before the payout is created: a
POST /v1/payouts/qr/scanwith an unreadable or dynamic QR now answers400 invalid_qr_payloadwith the concrete reason (it used to return a generic502). On the Brazilian confirm, an amount that does not match a fixed-amount PIX QR answers422with the payoutfailedand the refund already applied — and the QR stays intact so you can retry with the right amount and a new key. - Static PIX QR is reusable: the “one QR = one payment” guard no longer
applies to Brazilian static PIX QRs (they are paid many times by
design); the per-payment protection is your
idempotency_key, which is mandatory on every Brazilian confirm.
Added
- PIX QR payout in Brazil (BR/BRL): the two-step flow
POST /v1/payouts/qr/scan→POST /v1/payouts/qr/confirmnow accepts static Brazilian PIX QRs (including the “copia e cola” code) — sendcountry: "BR"andcurrency: "BRL". The scan decodes the BR Code locally (free of charge) and returns the merchant name, PIX key and amount; the confirm pays through PIX with the same pricing as a regular payout.amountis always required: fixed-amount QRs demand an exact match (a mismatch answers422with the payoutfailedand an automatic refund — the QR is not burned). A static PIX QR is reusable: each payment carries its ownidempotency_key. Dynamic or corrupt QRs answer400 invalid_qr_payload— use thepixmethod with the beneficiary’s key. Available in the test environment with sample QRs and magic values (.99amounts fail) — see Environment & testing. Details in the payouts guide.
Changed
- Universal checkout link v2 — multi-country + settlement in the asset
you choose (Breaking over yesterday’s v1 shape): the charge is now
denominated in any of your 4 virtual balances via
settlement_asset(USDTdefault,USDC,BTC,GOLD) withamountIN that asset (“50” USDT, “0.001” BTC, “2” g of gold); sendingcurrencyreturns400(existing v1 links keep working). The payer sees every country with a live pay-in corridor (pick a country → its methods with the local amount quoted and frozen at materialization), the 4 crypto options with a scannable QR (qr_payload+qr_png_base64; BIP-21 for BTC, raw address for TRON/ETH tokens — readable by Trust Wallet, MetaMask, Binance and external wallets), and the merchant’s CBPay QR + alias to pay instantly from the app (deeplinkcbpay:pay?to=…&checkout=…;POST /v1/transfersacceptscheckout_tokenand validates the due server-side). Every payment auto-converts into thesettlement_asseton credit (same asset skips conversion);conversion_statusis visible on/state. New public endpointGET {checkout_url}/quotewith the country catalog, crypto dues and CBPay dues. New errorscountry_required,country_unavailable,settlement_asset_disabledandcheckout_amount_mismatch. Details in the payins guide.
Added
- Rejection detail on failed active collections: when an active
collection (
collect, C2P or immediate debit) ends upfailed, the payin now includes afailureobject with where the rejection originated (provider= the payer’s bank,core= pre-charge validation), plus the concrete code and message — visible in the synchronousPOSTresponse, inGET /v1/payins/{id}and in the webhook. Previously only the genericfailedstatus was exposed. See the payins guide.
Added
- Universal checkout link (
checkout):POST /v1/payinsacceptsmethod: "checkout"and returnscheckout_url— a branded public page where the payer picks how to pay: QR, card, bank transfer or crypto (USDT on TRON, USDT/USDC on Ethereum and BTC) with a deposit address exclusive to that charge and accumulation of partial payments. One link = one charge: the first method that completes the payment wins. State queryable without auth atGET {checkout_url}/state; thepayin_creditedof a crypto payment addssettled_viaandcrypto_amount. Supportssuccess_url,failure_url,expires_in(10 minutes to 7 days) and idempotency (a retry returns the same link). New errorsalready_paid,checkout_expiredandmethod_unavailable. Details in the payins guide.
Changed
- Pre-capture authentication filter on card payments: card charges are
only sent to the processor when the 3-D Secure verification ended with a
successful or attempted authentication and complete authentication data;
an attempt without real authentication is rejected before any funds move
and the payer can retry. The payment page also extended device data
collection (~11 s) to improve issuer approval rates. In the test
environment, an amount ending in
.44simulates an attempt rejected by this filter (full table in Test environment).
Added
- Card payments (
card) on payins:POST /v1/payinsacceptsmethod: "card"(Bolivia, BOB or USD) and returnspayment_url— a hosted payment page with your organization’s branding where the payer enters their card in secure fields and completes their bank’s 3-D Secure verification. Optional fieldscustomer,success_url,failure_urlandexpires_at. A confirmed payment arrives via thepayin_receivedwebhook and credits the balance like any payin; if nobody pays,payin_expiredcloses the charge. Details in the payins guide.
Added
account_idon swaps and address screenings: the responses ofPOST/GET /v1/swapsandPOST/GET /v1/screenings/addressesnow includeaccount_id(the account that owns the operation). Informational for single-account integrations; admin views use it to attribute each record.
Added
- Bitcoin on-chain (
btc/btc): fourth supported network of the crypto product. Every account is now born with four deposit wallets (Bitcoin joins, bech32 addressbc1q…); BTC deposits credit the BTC balance (~30 min confirmation, 3 blocks) and on-chain withdrawals acceptchain: "btc"(bech32, taproot and legacy destinations; the network fee is covered by the operation — the recipient receives the exact amount). Segregated wallets also support thebtc/btcpair (no gas: the fee comes out of the wallet’s balance). Travel Rule applies as on the other networks, valuing the amount in USD. Details in the crypto guide.
Changed
- Two-step login also honors the phone binding cooldown: with login
2FA over SMS/WhatsApp and a recently linked, unverified number, the
login code is issued over a stronger factor (authenticator app, then
login email) instead of the phone — the effective
channelcomes back in the login response. Without an alternative factor the login responds403 phone_binding_cooldownuntil the cooldown expires. The code is never sent to a number linked from the session itself. Details in the security and 2FA guide.
Changed
- OTP challenges with the phone in cooldown fall back to a stronger
factor: with a recently linked number (24 h cooldown),
POST /v1/otp/challengesno longer blocks if you have the authenticator app enrolled or a verified email — the challenge is issued automatically over that channel (hierarchy totp > email) and the response reports the effective channel. The403 phone_binding_cooldownremains only for accounts with no alternative factor. Previously the cooldown blocked every 2FA relaxation (even disabling the email channel) even when stronger factors were available. Details in the security and 2FA guide.
Added
- Verified identity as the profile’s source of truth: when your
KYC/KYB onboarding is approved,
display_name(person = first + last name; company = legal name),tax_idandcountryare backfilled automatically from the verified identity. Documented in the KYC guide and the profile guide.
PATCH /v1/melocks identity fields once verified: withkyc_status: approved, changingdisplay_name,tax_idorcountryanswers409 identity_locked(new code on the errors page).phonestays editable with its own verification flow.
Added
- AML screening PDF report:
GET /v1/aml/screenings/{screeningID}/reportdownloads any screening in your history as an executive PDF report with your branding — a cover page with the decision and its risk traffic light, indicators (sanctions, watchlists, PEP, adverse media…), consolidated matches, aliases, a glossary and a final backing section with the international data sources consulted. Trilingual vialang=en|es|zh(default English). Pure read, no fee. New section in the AML guide. - New error code
invalid_language(HTTP 400): the PDF reportlangis noten,esorzh. Documented on the errors page.
- Company fields in the AML screening: examples and the spec documented
tax_id/registration_number/country_of_incorporationas flat fields ofcustomer.company, but the screening engine rejects them with422. The identifier goes inregistration_authority_identification, the country inplace_of_registrationandincorporation_dateis a{year, month, day}object. Guide and spec corrected (verified in production).
Added
- New corridor: Ecuador (USD) with four payout methods —
bank_transfer,deuna(DeUna wallet),cash_pickup(over-the-counter withdrawal, no account needed) andcnb(non-bank correspondent). The beneficiary accepts structured names (given_name/first_surname/…) or automatic splitting fromname, plus an optional sender block (sender_nameor its structured fields). Per-method examples in the payouts guide and the spec. - New error code
channel_unavailable(HTTP 503): the corridor’s payment channel is temporarily unavailable. Retry later with the sameidempotency_key. Documented on the errors page.
Added
- Test accounts are born populated: every new account in the test environment starts with ~6 months of realistic demo history across all products (payouts, payins, transfers, crypto, swaps, cards, banking, contacts…), with play balances, a reconciled statement and analytics ready to explore. Applies to every creation path (registration, social login, admin creation and the dashboard’s test/live switch).
- Fully independent environments: test data is no longer refreshed from a production snapshot — nothing is copied between environments. Updated environments and testing guide.
Added
- Official MCP server at
https://mcp.cbpayapp.com: connect your AI editor or assistant (Cursor, VS Code, Claude, ChatGPT and any MCP client) to this documentation — search, endpoints with real examples and the error catalog, without leaving your editor. Read-only, no authentication. New MCP Server page with one-click install and per-client setup.
Changed
- Test environment: new accounts are now born with
kyc_status: approved— you can exercise every product immediately, with no onboarding gate. This applies to every creation path (register, social login, admin creation and the dashboard test/live switch); existing test accounts were approved retroactively. Live is unchanged: accounts are born unverified and KYC/KYB remains mandatory before money can leave. To test the verification flow in test mode, use third-party KYC/KYB verifications.
Changed
PUT /v1/otp/preferences: enabling 2FA for theloginaction over a phone channel (sms/whatsapp) now requires the account phone number already verified (complete any SMS/WhatsApp OTP challenge first). If the number is not verified the API responds409 phone_verification_required. This safeguard prevents a mistyped number from locking you out of your account when enabling login 2FA.
Fixed
POST /v1/me/passkeys/register/beginandDELETE /v1/me/passkeys/{passkeyID}now accept a request without a body, as the spec documents (optional body). They previously returned400 invalid_json. The current password is still required for accounts that have one (403 invalid_passwordif missing or wrong); social-login-only accounts pass with their session.
Fixed
POST /v1/me/totp/enrollnow accepts a request without a body, as the spec documents (optional body). It previously returned400 invalid_json. The current password is still required for accounts that have one (403 invalid_passwordif missing or wrong); social-login-only accounts pass with their session.PUT /v1/otp/preferenceswith channelemailortotpreturned a 500 error; fixed — all four channels (sms,whatsapp,email,totp) now save correctly.
- PDF statement: operation statuses are now color-coded (green completed, amber pending, red failed) for quick scanning.
Added — CSV / Excel export on listings
- The
movements,payouts,payinsandtransferslistings now accept theformat=csvorformat=xlsxparameter to download the rows as an accounting-ready file (up to 10,000 rows per download; thefrom/to,statusand other filters apply the same).
- Without
formatthe response is still the usual paginated JSON — no compatibility changes.
Breaking — Segregated wallets move to
/v1/segregated-wallets- Every segregated-wallet route is renamed from
/v1/wallets*to/v1/segregated-wallets*. Same methods, parameters, response shapes, fees and webhooks — only the path prefix changes. There is no compatibility alias: the old/v1/wallets*routes now respond404. - Mapping (the 15 routes follow the same pattern):
- The
receipt_urlin responses, webhooks and receipt emails of wallet sends/deposits now points to the new path. - Why: the generic
/v1/walletsprefix was constantly confused with the deposit wallets of the crypto product. Those are untouched and keep living under/v1/crypto/wallets.
type discriminator on every wallet response- Deposit wallets (
/v1/crypto/wallets) now includetype: "deposit"andreceive_only: true. - Segregated wallets include
type: "segregated". - Use it to tell the two products apart defensively — never by route alone.
Added —
payin_expired webhook: automatic closure of unpaid collections- When an active charge (QR or hosted checkout) expires or fails without
receiving the payment, the payin now moves automatically from
pendingtoexpired(orfailed) — previously it could stay pending forever. - New
payin_expiredwebhook event carrying thepayin_id, the final status, the corridor and the reference, so you can close the collection on your side without polling. Subscribable viaPOST /v1/webhooks/subscriptions. - No funds move in any case: to retry the collection, create a new payin.
Changed — Redesigned receipts, statement and emails
- Every PDF receipt (
GET .../receipt) ships a banking-grade redesign: header with logo and receipt number, product icon, hero amount, two-column details, a “Verifiable document” strip with the QR code and an institutional footer. The brand symbol appears as a subtle watermark; non-final operations keep the status watermark. - The statement PDF (
GET /v1/reports/statement?format=pdf) adds summary cards with icons, a verified-reconciliation badge and per-section icons; the Excel export keeps its structure. - Emails (receipts, verification codes and security notices) now share a branded template with your organization’s institutional header and footer.
- On fiat payout receipts the beneficiary bank is ALWAYS shown by name: if
the operation was created with the catalog
bank_code, it is resolved to the bank’s display name automatically. - No API changes: same routes, same shapes. Only the documents and emails look different.
Added — Refresh tokens for user sessions
- Every login (password, OTP, social, passkey, handoff and register) now
returns, alongside the 24-hour
access_token, a single-userefresh_token(rt_…) to renew the session without re-login:POST /v1/auth/refreshissues a fresh pair and rotates the token (30 days per rotation, absolute cap of 90 days from the original login). Details and security rules in Authentication → Session renewal. - Strict rotation and theft detection: exchanging revokes the device’s
previous access token; presenting an already-exchanged refresh token
revokes the entire chain and records a
refresh_token_reuseevent inGET /v1/me/security/events. Signing out, revoking sessions or changing the password also invalidates refresh tokens. - New error code:
401 invalid_refresh_token. API keyspk_are unchanged: they never expire and don’t use refresh.
Added — Test environment (sandbox) with simulated money
- New test environment at
https://cryptobank.qbank.cl/platform: the same API, with every corridor served by a deterministic internal simulator — always available, no third-party dependency. Operations complete on their own within seconds and magic values (.99/.77amounts,REJECTbeneficiary, OTP000000, etc.) force every other outcome. Full guide in Environments and testing. - Per-environment API keys: test issues and accepts only
pk_test_keys; live onlypk_. A key from the other environment returns401— impossible to cross environments by mistake. - Every response carries the
CBPay-Environmentheader (test|live) andGET /healthzexposeslivemode. - One-click test/live switch:
POST /v1/auth/environment-handoff(live) issues a single-use 60-second token exchanged atPOST /v1/auth/handoff(test) for a test-environment session, with automatic mirror-account provisioning.
Added — AML screening audit history
GET /v1/aml/screeningsandGET /v1/aml/screenings/{screeningID}list and retrieve every AML screening (person, company and rescreen) stored locally for audit — subject, risk, fee and full result.POST /v1/aml/screeningsandPOST /v1/aml/rescreennow requireidempotency_key(the operations charge a fee). Replaying with the same key returns the original record withidempotency_hit: trueand never double-charges.PATCH /v1/aml/monitoringstores each enable/disable toggle in the same history (kind: monitoring);idempotency_keyis required when the state changes (enable charges a fee).
Added — Travel Rule on on-chain withdrawals (FATF R.16)
- Crypto withdrawals above the configured threshold (default 1,000 USD)
now require declaring the beneficiary before moving funds:
wallet_type: "self_hosted"+beneficiary_namefor own wallets, ortravel_address+beneficiary_namefor destinations at another institution (the data exchange happens inline and the payment address is provided by the receiving institution). Below the threshold nothing changes. - The withdrawal response includes
travel_rule_status(not_required/self_hosted_attested/approved). - New error codes:
travel_rule_required,travel_rule_beneficiary_required,travel_rule_address_mismatch,travel_rule_rejected,travel_rule_pending,travel_rule_incomplete_approval,travel_rule_unavailable. Details in the crypto guide and the errors page.
Added — Banking series in the balance history
GET /v1/balances/historynow includes inassetsthe daily series of the banking accounts (BANK_USD,BANK_EUR), each in its own currency (2 decimals), ready to chart as one more filter next to USDT/USDC/BTC/GOLD. They remain outside thetotal_usdaggregate, which only covers the operational balances. Analytics guide updated.
Added — Country filter on payouts and payins
GET /v1/payoutsandGET /v1/payinsaccept thecountryfilter (ISO 3166-1 alpha-2, e.g.?country=MX), combinable withstatus,from/toand pagination. Payouts and payins guides updated.- The
feesblock ofGET /v1/ratesnow returns the effective fee configuration (organization defaults resolved against your account’s overrides). Accounts without overrides used to seefees: []even when operations had a cost; use this block to quote the exact fee before creating an operation.
Changed — Wallet limits per account type
- Deposit wallets: every account — person and company — holds exactly
one deposit wallet per supported pair (
tron/usdt,eth/usdt,eth/usdc), provisioned free of charge on registration.POST /v1/crypto/walletsnow exists only to restore a missing pair; with the pair already provisioned it responds422 wallet_limit_reachedfor every account type (previously companies could create more). - Segregated wallets: now also available to person accounts, capped at
1 per network/asset pair (the second attempt responds
422 wallet_limit_reached). Company accounts remain unlimited. The403 company_requirederror no longer applies to segregated wallets. - Crypto and segregated wallets guides, the persons and companies page and errors updated.
Added — Continuous transaction monitoring (compliance controls)
- The platform now monitors every operation in real time with bank-grade compliance controls. For the vast majority of clients this is invisible: no flow changes and no perceptible latency.
- New error codes documented in errors:
403 compliance_hold(operation held by compliance),403 geo_restricted(unsupported jurisdiction) and503 compliance_check_unavailable(check temporarily unavailable — the operation did not go out; retry with the same idempotency key).
Added — Documentation in 3 languages (English by default)
- This documentation is now fully available in English (default language), Spanish and Simplified Chinese. Switch languages with the selector at the top of the site.
- The API Reference is also available in all three languages (same endpoints and examples; only the descriptions change).
- The Postman collection and the compiled Markdown guide stay up to date from any language of the site.
Added — Wallet screening (AML risk for blockchain addresses)
- New product:
POST /v1/screenings/addressesevaluates any blockchain address against global on-chain intelligence — sanctions, exposure to illicit funds — and returns aLow/Medium/High/Severerisk level with the full evidence. Fixed fee per scan (address_screening, with automatic refund on failure) and mandatory idempotency. History viaGET /v1/screenings/addresses(+/{id}). - Free automatic protection: on-chain withdrawals evaluate the destination before signing (severe risk ⇒ rejected with a full refund) and incoming deposits evaluate the sender before crediting (severe ⇒ held for compliance review; high ⇒ credited with an alert).
- New webhooks:
crypto_deposit_heldandcrypto_deposit_alert. - New guide: Wallet screening.
Added — Public assets over CDN (avatars, branding, charge QR codes)
- Avatars over CDN:
avatar_url(inPUT /v1/me/avatar,GET /v1/resolveand contacts) is now an absolute public URL that loads without authentication once the image is published to the CDN;GET /v1/avatars/{accountID}answers with a302redirect to that URL (legacy avatars are still served directly). - Branding URLs:
GET /v1/brandingaddslogo_urlandsymbol_url— public CDN URLs for the logos, so the front end can theme itself without decoding base64 (the*_png_base64fields remain). - Payin QR codes: QR charges (
POST /v1/payins, methodqr) exposeqr_image_url, the QR PNG published to the CDN, alongside the usual base64qr_image. Perfect for a direct<img>tag.
Added — Compliance catalogs
- New
GET /v1/aml/catalogs: every catalog you need to build compliance and verification forms (genders, legal entity forms per country, income/wealth sources, industry standards, ISO-3166 countries and subdivisions). This data was previously unavailable through the API.
- The
asset_pricesblock ofGET /v1/ratesandGET /v1/rates/historyno longer includes the internalsourcefield; usesettlement_gradeandupdated_atto know whether a price is executable and how fresh it is.
Added — Every account is born with its deposit wallets
- When an account is created (person or company), its three crypto deposit
wallets are provisioned automatically and free of charge:
tron/usdt,eth/usdtandeth/usdc. Right after registration,GET /v1/crypto/walletsalready returns the three addresses (provisioning runs in the background; querying at the very second of registration may take a few moments). POST /v1/crypto/walletsis now for additional wallets (companies); persons already hold each combination’s slot since registration. Accounts created before this change were backfilled with any missing wallets.
- Public account registration is now rate limited per IP
(
429 too_many_attempts).
Added — Full traceability: banking in the statement, itemized fees and wallet custody
- Richer statement: new
card_transactions(card purchases),swaps(balance conversions) andbanking_operationssections. If you use Banking, your bank accounts reconcile asBANK_USD/BANK_EURmirror balances inside theassetssection. - Itemized fees: payouts, payins and crypto withdrawals now split the
fee into
fee_percentandfee_fixed(they add up exactly tofee); standalone charges carryfee_model: "fixed"and are labeled Fixed Com in the PDF/Excel. - New receipts:
GET /v1/banking/operations/{id}/receipt,GET /v1/wallets/{walletID}/sends/{sendID}/receiptandGET /v1/wallets/{walletID}/deposits/{depositID}/receipt. Thebanking_operation_status_changedwebhook now includesreceipt_url. - Segregated wallet custody:
custodyfield (cbpay|client) on every wallet; the platform syncs the complete on-chain activity and emits thewallet_external_movementwebhook (movement signed outside, expected underclientcustody) andwallet_key_compromise_suspected(critical alarm). - Analytics:
sections.banking.volume(money moved through your bank accounts, which also adds togross_volume),sections.verifications.fees_by_kind(KYC vs KYB spending, separately),sections.adjustmentsanddeposits.wallet_fees_usd. - Guaranteed per-wallet accounting (
cbpaycustody): lifetime reconciliation in the statement andfunding_sources(deposit→send FIFO attribution) on each send’s detail.BANK_*mirror balances also show up inGET /v1/balanceswithcustody: "banking".
Added — Historical series for your dashboard
GET /v1/rates/history: the evolution of your account’s FX rates (payout and payin side per point), withdayorhourgranularity and a signedchange_pctper currency — ready for the rate chart with its “+3.4% / −3.0%” badge. Includes the USD reference series for BTC and GOLD.GET /v1/balances/history: the daily evolution of your balances — one series per asset with each day’s closing balance (no gaps), the aggregated USD series valued at each day’s historical price, the period’s inflows/outflows and the current snapshot — everything needed for the balance card with a chart.- Rate history starts with a ~90-day backfill of daily rates and is recorded continuously going forward.
Added — PDF receipts with authenticity verification
- Every transactional product has its branded PDF receipt:
GET .../receipton payouts, payins, transfers, crypto withdrawals and deposits (newdeposit_idinGET /v1/crypto/transactions), swaps and card purchases. Languages?lang=es|en. receipt_urlon every response of those products and on final-state webhooks: the front end never builds the URL by hand.- Public authenticity verification: every PDF carries a signed code with
a QR that opens
GET /verify/receipts/{code}(no credentials) — JSON for APIs and a branded web page for browsers, always showing the real, current status and amount, never the beneficiary’s personal data. - Receipts of non-completed operations carry a diagonal watermark (“PROCESSING” / “FAILED”): an in-flight PDF can never pass as proof of payment.
- Automatic email with the PDF attached when the operation reaches a
final state, with per-account opt-out (
PATCH /v1/mewithreceipt_emails: false).
GET /v1/branding: the platform’s effective branding (logo, colors, name) so a white-label front end can theme itself from the API.
- The PDF statement now renders with the brand’s real logo and the Inter typeface (previously a typographic wordmark), and the Excel includes the logo on the summary sheet.
Added — Segregated wallets (company accounts only)
- On-chain wallets with their own balance (outside the ledger): create
(
POST /v1/wallets), list and get, import an external wallet with its key (POST /v1/wallets/import), export the private key (POST /v1/wallets/{id}/export, shared custody) and send crypto directly from the wallet (POST /v1/wallets/{id}/sends). - Live on-chain queries:
GET .../balance(includes gas),.../depositsand.../transactions; configurable auto-forward (GET/POST .../auto-forward). - Send gas is on the client: without gas the send returns
422 insufficient_gas. Import and export require a signed-in user session with 2FA. - New fees:
wallet_import,wallet_export,wallet_send. - New webhooks:
wallet_deposit_received,wallet_send_status_changed,wallet_key_exported. New service flag:wallets. - The statement and dashboard include a segregated wallets section.
Added — Account profile, credentials and security
- Password: self-service change (
POST /v1/me/password, revokes all other sessions) and code-based recovery (POST /v1/auth/password/forgot→POST /v1/auth/password/reset) via email or verified phone. Forgot always returns 200 (never reveals whether the account exists). - Login email: verified change (
POST /v1/me/email/change→confirmwith the code sent to the new email) and verification of the current one (POST /v1/me/email/verify). - Permanent alias (
PUT /v1/me/alias) and profile QR (GET /v1/me/qr): identify your account to receive transfers. Transfers acceptto_aliasandto_qr_token;GET /v1/resolvepreviews the recipient before sending. - Profile photo:
PUT/DELETE /v1/me/avatarandGET /v1/avatars/{id}. - Self-service 2FA (
GET/PUT /v1/otp/preferences): enable and pick the channel per action — now also email and authenticator app (TOTP) in addition to SMS/WhatsApp. Harden freely; weakening requires verification. - Authenticator app (TOTP):
POST /v1/me/totp/enroll(QR) →confirm(returns 10 one-time backup codes),DELETE, andPOST /v1/me/totp/recovery-codesto regenerate them. - Passkeys (WebAuthn): passwordless sign-in with the device’s biometrics
(Face ID, Touch ID, Windows Hello, security keys). Registration
(
/v1/me/passkeys/register/begin|finish), management (GET,DELETE) and login (/v1/auth/passkey/login/begin|finish). - Sessions and activity:
GET /v1/me/sessions+ revoke one or all, andGET /v1/me/security/events(account security history). - Email alerts on sensitive events (password or email change, factor added/removed).
Added — Reusable verified identity (unified KYC/KYB)
- A customer’s approved KYC/KYB verification becomes their single identity inside CBPay: their data and documents are reused across the other products without re-typing or re-uploading. Guide: reusable identity.
- Cards: your account’s first issuance auto-fills the cardholder’s
identity and documents from your approved verification — you only
send
occupationandsalary_usd. Explicit fields still win. - Compliance report (KYB):
GET /v1/kyb/submissions/{id}/reportdownloads the verification’s signed compliance report (PDF).
POST /v1/banking/third-partiesnow requires theverification_idof an approved verification of the third party. Thetypecomes from the kind (KYC ⇒ INDIVIDUAL, KYB ⇒ COMPANY), identity auto-fills and the already-validated documents are re-delivered to the banking provider (documents_synced). Existing third parties keep operating.POST /v1/cardsfor designated persons (company accounts) now requirescardholder.verification_idof that person’s approved KYC; their identity and documents come from the verification.- New errors:
422 verification_required,422 verification_not_approved,422 verification_kind_mismatch,422 verification_invalid.
Added — Account summary (analytics) + third-party banking users
GET /v1/analytics/summary: in a single call, every series and statistic of your account to build your dashboard — gross volume (in/out), transactions and new users per period (day/week/month, with comparison vs the previous period), global per-country view, and a section for EVERY service (payouts, payins, deposits, withdrawals, transfers, swaps, cards, banking, KYC/KYB, AML, contacts) with their dimensions (country, currency, method, status, chain, merchant). Plusspending(what you consumed in fees per service) and USD-valuedbalances. New guide: Your account summary.- Third-party banking users (companies only):
POST/GET /v1/banking/third-parties(+documents, submit, accounts, balance) to register your end clients as separate banking users, with their own identity/KYC and accounts in their name. Isolated per account. - New limit: person accounts can hold at most 1 bank account
(
409 banking_account_limit).
Changed — Bolivia and Venezuela rates
- The USD→BOB and USD→VES rates in
GET /v1/ratesnow reflect the market we actually operate your payments with (previously a reference rate was published that did not match the applied value). - If one of those rates is temporarily unavailable, the country is omitted
from
GET /v1/ratesand operations in that currency return422 currency_not_supporteduntil it is back — we never quote with an incorrect rate. We recommend checkingGET /v1/rates(or subscribing to the rates webhook) before quoting payments inBOBorVES.
Added — Swaps: convert between your balances
- New
swapsproduct: convert betweenUSDT,USDC,BTCandGOLDinstantly, without the money leaving your account — any pair, including directBTC↔GOLD.POST /v1/swaps(synchronous, withidempotency_key),GET /v1/swaps/quote(free indicative quote) andGET /v1/swaps(+/{id}) for history. - The quoted rate is your account’s execution rate: quoted = received, no
separate fees. Live BTC/GOLD prices (if the price is not fresh the swap
is rejected with
503 pricing_unavailable). - Conversions touching BTC/GOLD share the per-operation and 24h volume
limits with payouts and card purchases (
GET /v1/settlement). New guide: Swaps.
Added — Contacts and sending by phone number
- Contact book (
/v1/contacts): full CRUD with search and favorites. Every send (transfer, payout, crypto withdrawal) saves its destination as a contact automatically — deduplicated; opt out with"save_contact": false. - Phone address book import (
POST /v1/contacts/import, up to 1,000 per request): normalizes phones to E.164 and tells you which contacts already have CBPay (has_cbpay, matching only within your operator). - Transfer by phone:
POST /v1/transfersacceptsto_phone(only accounts with an OTP-verified phone; ambiguity answers422 recipient_ambiguous) andto_contact_id. - Quick send to contacts:
beneficiary_contact_idon payouts (uses the contact’s saved beneficiary) andto_contact_idon crypto withdrawals (uses its saved address). New guide: Contacts.
Added — KYC/KYB identity verification (hosted wizard, OCR documents and video liveness)
- Mandatory onboarding: every new account must approve its identity
verification (person ⇒ KYC, company ⇒ KYB) before operating. Until then
it can only fund (payins, crypto deposits, incoming transfers) and
read; everything else answers
403 verification_required. Request your link withPOST /v1/me/verification/linkand check your state withGET /v1/me/verification— approval updates yourkyc_statusautomatically. Existing accounts were grandfathered as approved. - Third-party verification (company accounts only): generate hosted
links (
POST /v1/kyc/links,POST /v1/kyb/links) or send data through the API (POST /v1/{kyc,kyb}/submissions), upload documents with presign + OCR and close the liveness check with liveness links. New fixed feeskyc_verification/kyb_verificationbilled at creation (mandatoryidempotency_key, automatic refund on failure). - 7 new webhooks:
kyc/kyb_verification_status_changed,kyc/kyb_link_completed,kyc/kyb_document_validated,kyc_liveness_completed. Full guide at KYC and KYB verification.
POST /v1/kyc,POST /v1/kyc/rescreenandPATCH /v1/kyc/monitoringwere removed: list screening now lives atPOST /v1/aml/screenings,POST /v1/aml/rescreenandPATCH /v1/aml/monitoring(same semantics, samecompliance_*fees). Theno_kycerror becomesno_screeningand screening no longer touches yourkyc_status. Newaml_screening_updatedwebhook and newamlservice flag (thekycflag now gates identity verification). Guide: AML screening.
Fixed — Banks catalog without
method in countries with several methodsGET /v1/payouts/banks?country=VEanswered400asking formethod, and?country=BOanswered400 payout_corridor_unsupported. The catalog withoutmethodnow returns the union of every payout method’s banks for the country (deduplicated by code), as this documentation promises; passingmethodscopes it to a single channel (parameter now documented in the reference).
Added — Card purchases from BTC and GOLD (at-the-moment conversion)
spending_assetnow also accepts BTC and GOLD: purchases convert at the effective price of the moment of each event (the same one in thesettlementblock ofGET /v1/rates).- Authorization: the equivalent is reserved plus a small cushion (not a
charge; returned at settlement). If the execution price is unavailable,
the purchase is declined with
pricing_unavailable— your balance is never converted with an untrustworthy price. - Settlement: the final amount is re-quoted at the capture moment’s price and the cushion’s excess returns automatically. Reversal of an authorization: exact amount returned, no conversion. Refunds/adjustments after capture: re-converted at the price of the event’s moment (your balance takes the price variation).
- BTC/GOLD purchases share the account’s volatile-asset limits with
payouts: per operation (
settlement_limit_exceeded) and 24h volume (settlement_daily_limit_exceeded).
Added — Choose which balance your cards spend from (USDT or USDC)
- Each card now has a spending asset (
spending_asset): its purchases debit the account’s USDT or USDC balance, 1:1 with the USD and with no conversion fee. USDT by default (identical to the historical behavior). - Set it when creating the card (
spending_assetinPOST /v1/cards) or change it any time withPATCH /v1/cards/{cardID}. The change only applies to future purchases: in-flight authorizations keep (and refund to) the asset they debited. - Card transactions now expose
spend_assetandspend_amount(the balance and amount actually debited);amount_usd/amount_usdtremain the USD reference value. Per-card limits are still measured in USD. - New errors:
400 spending_asset_unavailable(BTC/GOLD are not available for card purchases) andspending_asset_disabledauthorization declines if your operator disables the asset.
Changed — Multi-asset settlement hardening
- Payments from BTC/GOLD now have, on top of the per-operation limit, a
rolling 24h per-account volume cap (
422 settlement_daily_limit_exceeded). It shows inGET /v1/settlementasvolatile_daily_limit_usdt. - Card fees (issuance, cancellation and the monthly fee) are now also debited from your default settlement balance, like every other service. Card purchases still settle in USDT.
Added — Pay payouts and services from any balance (multi-asset settlement)
- Payouts and service fees (KYC, wallet creation, banking) can now be debited from any of your four balances (USDT, USDC, BTC, GOLD). Pricing is still quoted in USDT; the total translates to the chosen asset at the effective settlement price of the moment. Details in the money model.
- New
GET/PUT /v1/settlement: set your account’s default balance (default_settlement_asset). Per-operation override withsettlement_assetinPOST /v1/payoutsand in the QR confirm. - The payout response now records
settlement_asset,settlement_amount(the exact amount debited — also the amount refunded on failure, never re-quoted) andsettlement_rate. GET /v1/ratesadds asettlementblock with the effective price per enabled asset, andasset_pricesnow carriessource,updated_atandsettlement_grade(whether the price is fit to execute).- New errors:
503 pricing_unavailable(BTC/GOLD execution price unavailable),400 settlement_asset_disabled,400 invalid_settlement_assetand422 settlement_limit_exceeded(per-operation limit for volatile assets).
Changed — Short reference for announced bank transfers
POST /v1/payinswithmethod: "bank_transfer"now returns a short 12-character alphanumericreference(e.g.CBW4N8R2T6P9) instead of the UUID: bank concept fields have hard limits (Paraguay/SIPAP caps them at 20 characters with no special characters) and the UUID never fit.- Automatic matching accepts the new reference and keeps accepting the
UUID from old announcements — existing
pendingpayins are unaffected. The amount+currency fallback is unchanged. GET /v1/payinsand the detail expose the announce reference inreferencewhile the payin ispending.
Added — Payins in Paraguay (announced bank transfer)
- New collection corridor
PY/PYG/bank_transfer: announce the deposit withPOST /v1/payins, your payer transfers (SIPAP or an internal transfer at the receiving bank) with thereferencein the concept, and the credit arrives automatically in USDT at yourpayin_rate, like in every country. Guide in payins. - Guaraníes use no decimals: announce the exact integer amount
(e.g.
"596000"). The amount+currency fallback match applies as usual. - The corridor shows up in
GET /v1/payins/methodswithdelivery: polling.
Added — Multi-currency virtual balances (USDT, USDC, BTC, GOLD)
- Every account now holds four independent virtual balances:
USDT(the operating currency),USDC,BTC(8 decimals, satoshis) andGOLD(grams of fine gold, 6 decimals, custodian-backed). They never mix and are never converted automatically. Details in money model. GET /v1/balancesalways returns all four balances (zeros if you have not used that currency) andGET /v1/movementsfilters by currency with?asset=.- Multi-currency internal transfers:
POST /v1/transfersacceptsasset(USDTdefault,USDC,BTC,GOLD) — always between balances of the same currency, with no conversion and no fee. - On-chain USDC: create
eth/usdcwallets, deposit and withdraw USDC over Ethereum. Every deposit credits its own asset’s balance. Guide in crypto. - Reference prices:
GET /v1/ratesincludesasset_priceswith each currency’s USD reference price (BTC per unit, GOLD per gram) — for valuation only, no conversion and no spread. - Multi-currency statement: new
assetssection with each non-USDT balance reconciled independently (opening/inflows/outflows/closing and its ownbalancedflag), also in the PDF and Excel exports. - Payouts, payins, cards and service fees keep operating exclusively against the USDT balance.
Added — Social login (Google, Apple, Microsoft, Meta)
- Passwordless sign up and sign in with Google, Apple, Microsoft and
Facebook via token exchange: your front end gets the credential with the
provider SDK and exchanges it at
POST /v1/auth/oauthfor the CBPay session. Full guide in social login. - New endpoints:
POST /v1/auth/oauth(unified login + registration),GET /v1/auth/oauth/providers(enabled providers, public),GET/POST /v1/me/identitiesandDELETE /v1/me/identities/{provider}(link/unlink providers from the session). - Integrates 2FA: if the account enforces OTP on login, social login
also returns
otp_required+pending_token. - Multi-method: one account can have a password and several providers; auto-linking by email only happens if the provider returns it verified.
- New error codes in the catalog:
invalid_provider,provider_not_configured,invalid_credential,email_conflict,identity_taken,last_login_method.
- The “Collection updated” stamp on the Postman page now correctly shows how long ago it was updated (it previously left an empty indicator).
Added — OTP/2FA over SMS and WhatsApp
- Two-step verification for sensitive actions: your operator can require a one-time code (over SMS or WhatsApp) before login, payouts, crypto withdrawals, transfers, banking operations, revealing a card, issuing API keys, adding members or changing the phone. Full guide in security and 2FA.
- New endpoints:
POST /v1/otp/challenges(sends the code),POST /v1/otp/challenges/{id}/verify(returns the single-useotp_tokenfor theX-OTP-Tokenheader),GET /v1/otp/challenges(+ detail) andGET /v1/otp/settings(your effective policy). - Two-step login: with OTP active on
login,POST /v1/auth/loginreturnsotp_required: true+pending_token, and the session is issued atPOST /v1/auth/login/otp. - User sessions only:
pk_API keys are exempt — your server-to-server integrations do not change. - New error codes in the catalog:
otp_required,otp_invalid,phone_required,phone_binding_cooldown,too_many_attemptsand more.
Documentation — person vs company and unified guides
- New persons and companies page: ALL the differences between the two account types (wallets, cards, members, KYC/KYB) in a single table, with the errors each limit produces.
- Cards guide reorganized by account type: “Person account” and “Company account” tabs, each with its complete flow (first card, subsequent ones, and for companies both corporate and employee issuance) — no more assembling the flow from scattered notes.
- Country examples back in their guides: the per-corridor requests/responses for payouts and payins live INSIDE each product’s guide again (one page per product, no jumping to a separate reference). Old URLs redirect.
- Postman with live freshness: the Postman page now shows how long ago the collection was updated (seconds/minutes/days), on top of the date and version.
- The compiled MD now includes the full endpoint reference and the documentation version.
Documentation — full site redesign
- New navigation: Getting started → Concepts → Integration flows → Products → Integration → Resources, with per-page icons and breadcrumbs.
- New pages: environment and testing
(webhook tunnel for local dev + go-live checklist),
enabled services,
statuses and lifecycle (including the failed
payout
status_codecatalog), movements and reconciliation and integration flows with end-to-end diagrams. - Payouts and payins split: general guide + country reference with the real request and response of every corridor.
- Expanded guides: quickstart closes the loop with webhooks; profile
(
PATCH /v1/me) and members with roles; complete idempotency endpoint table; webhook retry schedule; on-chain confirmation times; EUR banking accounts; banking errors in the catalog; FAQ with limits, cancellations and reconciliation. - Cards: when to send
cardholder, clarified. The guide and spec now explain that an account’s first issuance creates and verifies the holder (full data + mandatory documents) and that subsequent cards reuse it with no data — the minimal example previously implied data was never required.
Added
payin_rateinGET /v1/rates: each country now carries your two rates —ratefor payouts (dispersals) andpayin_ratefor payins (fiat collections/deposits). Quoted = credited, always.
- Payin pricing now works like payouts: a payin’s FX pricing lives in
your
payin_rate(the credit converts at exactly that rate) and the payin fee becomes a fixed amount per operation — no separate percentages. Each payin’sfx_ratefield records the rate applied. See fees and the payins guide. - Credit conversions round down to the micro-USDT (debits keep rounding up), with at most 1 micro-USDT of difference.
- KYC/KYB: full identity field reference. The
customerobject has always accepted many more optional fields than the examples showed (date of birth, nationalities, documents with issuing country, aliases, residences, company registry data…) and sending them makes the screening more precise. The KYC guide now documents every field, with full-identity examples and the deduplication rule.
Added
- Card catalogs:
GET /v1/cards/catalog/occupationsandGET /v1/cards/catalog/business-activities(searchable with?q=) to populate pickers. When designating a person,occupationmust be a catalog code; for a company, so mustkind_of_business. An out-of-catalog value is rejected with400 invalid_occupation/400 invalid_kind_of_businessbefore reaching the issuer. See the cards guide.
Added
GET /v1/services: effective map of the services enabled for your account (payouts,payins,transfers,crypto,banking,kyc,cards) — use it to decide what to show in your UI. Services are enabled per account according to your commercial agreement; when one is off, its actions answer the new403 service_disablederror (reads and money in flight are never blocked).
Added
- Virtual and physical cards that spend straight from the account’s
USDT balance, with no prefunding: every purchase is authorized in real
time against the available balance and the card’s limits. Persons: 1
virtual + 1 physical; companies: unlimited, for the company or for
designated persons (e.g. employees). New endpoints
POST/GET /v1/cards,GET/PATCH /v1/cards/{id}(limits and freeze/unfreeze),POST /v1/cards/{id}/activate|cancel|revealandGET /v1/cards/{id}/transactions. See the cards guide. - New billable services (fixed, configurable, can be 0):
card_creation_virtual,card_creation_physical,card_monthly(with no balance the card is frozen — no debt) andcard_cancellation. - New webhooks
card_transaction(authorized/annulled/adjusted) andcard_status_changed(state changes, including automatic freezes). - New ledger movement types:
card_debit,card_refund,card_fee,card_fee_refund.
Added
- Chile: hosted payment page (
method: "fintoc") onPOST /v1/payins. The response carries apayment_urlthe payer opens to transfer from any Chilean bank or wallet (Banco Estado, Santander, Mach, Tenpo, Mercado Pago, among others); the deposit is detected, validated and credited automatically in USDT with the usualpayin_creditedwebhook. Supports an optionalidempotency_key: a retry returns the same payin and the same URL without opening a second payment session. See the payins guide.
Added
-
from/todate filters on every list endpoint:/v1/movements,/v1/payouts,/v1/payinsand/v1/crypto/transactionsnow acceptfrom/to(YYYY-MM-DD, UTC, inclusive), on top of the usual pagination (page,page_sizeup to 200). Invalid dates return400 invalid_range. -
Query transfers:
GET /v1/transfers(list with pagination and date filters) andGET /v1/transfers/{id}— previously they could only be created. -
List webhook subscriptions:
GET /v1/webhooks/subscriptions. -
Idempotency on active collections:
POST /v1/payins/collectnow requiresidempotency_key(it executes a real charge; a retry never re-charges the payer). Same hardening for wallet creation (no double fee on retries) and admin adjustments. -
Uniform pagination added to
members,crypto/wallets,deposit-accountsand (admin)orgs. -
Account statement (
GET /v1/reports/statement): consolidates every movement of the period — payouts, payins, crypto, transfers and fees — into one auditable document with an exact accounting reconciliation (opening + inflows − outflows = closing, verified against the ledger). Three formats from the same endpoint: JSON for your web, PDF with CBPay branding and a multi-sheet Excel with numeric cells, filters and a movements sheet for auditors (format=json|pdf|xlsx,lang=es|en). The org admin can generate any of its accounts’ statements. See the guide.
Improved
- Visual flow diagrams across the documentation: the money map in the introduction (everything entering and leaving the USDT balance), the payout lifecycle with debit/hold/refund, the two-step QR flow, the four payin modes converging into the credit, crypto deposit and withdrawal, the full banking lifecycle, KYC states, webhook delivery and retries, and the idempotency decision rule (“which key do I retry with?”).
Changed
- New base URL:
https://api.qbank.cl/platform(previouslyexchange.qbank.cl/platform). The old domain keeps working as an alias, so no existing integration breaks — but useapi.qbank.clfor everything new. All documentation, the spec and the Postman collection already point to the new URL.
Added
- Banking: real bank accounts for your account — receive, hold and
send money over international banking rails (SEPA, SWIFT, ACH depending
on the currency). 14 new endpoints under
/v1/banking/*:- Banking profile: create, fetch, upload documents and submit for verification.
- Accounts: open per currency, list and check live balances.
- Beneficiaries: register, list and attach destination accounts.
- Payments: quote (
prepare, free) and executeTRANSFER/WITHDRAWwith idempotency.
- New webhooks:
banking_customer_status_changedandbanking_operation_status_changed. - New fees (fixed, configurable, refunded if the operation fails):
banking_customer,banking_account,banking_operation— thebanking_feefield on each response shows what was charged. - Full Banking guide with the end-to-end flow and examples for every operation.
Improved
- Fully localized API Reference: titles, descriptions, fields and sidebar groups are now translated when browsing the documentation in Spanish (previously only the UI chrome switched languages).
- Payouts guide reorganized: Brazil PIX now lives only under “Examples by country” (the duplicated section was removed); QR stays as the single separate flow section since it is a distinct flow (scan + confirm).
- Webhooks: sample payload for each of the 5 events.
- Quickstart: registration examples for both person and company.
- Postman collection expanded to 53 requests: endpoints with several use cases now ship one request per case (a payout per country and method, payins per mode, person/company KYC, etc.), each with a ready-to-send body.
- Payins guide restructured by country, matching payouts: a corridor matrix with each country’s mode plus Chile / Peru / Mexico / Venezuela / Bolivia / Brazil tabs with their complete examples.
- New FAQ page: sandbox, initial funding, pre-payout cost estimation, rate guarantees, arrival times, safe retries, deposits without a reference and more — day-one questions answered inside the docs.
- Quickstart opens with the key facts table (base URL, auth header,
slug, amount format, environment) and the
GET /v1/ratesresponse example with the cost-estimation formula. - Payouts: response examples for the methods and banks catalogs, plus a
status table with the effect on your balance. Payins: catalog response
example with the meaning of
delivery.
Improved
- Complete per-use-case examples across the documentation:
- Payouts: an example for every country and method with its real
beneficiaryand response (Chile, Peru CCI + Yape, Mexico CLABE + debit card, Venezuela Pago Móvil + bank transfer, Bolivia ACH, Brazil PIX, Paraguay). - Payins: Bolivia and Brazil QR side by side, active collection
c2panddebito_inmediatowith the OTP response, dedicated deposit account. - KYC/KYB: person, company and minimal autofilled requests, with the screening, rescreening and monitoring (enable/disable) responses.
- Transfers: by email, by
account_id, company→person (payroll) and idempotent replay. - Crypto: person vs company wallet creation, and the
wallet_limit_reachederror. - API Reference: selectable named examples on every endpoint (10 payout corridors, 3 payin modes, person/company KYC…).
- Payouts: an example for every country and method with its real
Added
- Brazil (BRL) with PIX documented for payouts and payins:
pixpayout by key (CPF/CNPJ, phone, email orevprandom key) viaPOST /v1/payouts.- Payout to a PIX QR (static or “copia e cola”) via the
qr/scan+qr/confirmflow withcountry: "BR". - Payin with a dynamic PIX QR via
POST /v1/payins(method: "qr",country: "BR"), carrying the QR image and the “copia e cola” code. - Payin by announced bank transfer (
method: "bank_transfer").
GET /v1/payouts/methods,
GET /v1/payins/methods) reflects availability at any given time.Added
- Every collection (payin) method now available through the API:
POST /v1/payinsnow acceptsmethod:qr(QR charge, as before) orbank_transfer(announce an incoming deposit and get the reference the transfer must include to be credited automatically).POST /v1/payins/collect— active pull collection in corridors that support it (e.g. Venezuelac2p/debito_inmediato), with synchronous crediting;POST /v1/payins/collect/otpfor the prior OTP when the method requires it.POST /v1/payins/deposit-accounts— fixed dedicated deposit account (e.g. a Mexican CLABE) bound to your account: everything arriving to it is credited automatically.GET /v1/payins/deposit-accountsto list them.
- Full corridor and method matrix for payouts in the guide (Chile, Peru
with
yape, Mexico SPEI, Venezuela withpago_movil, Bolivia withqr, Paraguay). - Venezuela (VES) joined the
GET /v1/ratesquotes.
Added
- Bolivia QR payout: pay any Bolivian collection QR in two steps —
POST /v1/payouts/qr/scan(free, returns the recipient’s data) andPOST /v1/payouts/qr/confirm(charged like a regular payout: your rate + fixed fee, with a synchronous final result and automatic refund on failure). - Bolivia (BOB) joined the
GET /v1/ratesquotes.
Added
- New Postman page: official downloadable collection with all 25 endpoints, example bodies and pre-configured authentication. Regenerated with every API version.
- The Fees page and payout examples now reflect the current pricing model: payouts are charged at your rate + a fixed fee per operation (no separate percentage). Dispersing the equivalent of 100 USDT debits 100 USDT plus your configured fixed fee.
Improved
GET /v1/ratesnow returns your account’s own exchange rate per country: the same rate your operations execute at (local_amount / rate = USDT), with no difference between what is quoted and what is charged.
Removed (Breaking)
GET /v1/crypto/deposit-address(the alias deprecated in v1.4) was removed for good. UsePOST /v1/crypto/walletsto create wallets andGET /v1/crypto/walletsto list them.
Added
- Multiple wallets for companies: company accounts can now create unlimited wallets per network (persons keep 1 per network).
- New endpoints:
POST /v1/crypto/wallets(create a wallet, with an optionallabelto tell them apart) andGET /v1/crypto/wallets(list my wallets). Every creation bills the fixedwallet_creationfee when configured. - New
422 wallet_limit_reachederror when a person tries to create a second wallet on the same network. - Wallet responses now include
wallet_idandlabel.
- The Crypto guide was reorganized into: create wallet, view my wallets, deposit, transfer and movements.
GET /v1/crypto/deposit-addressremains as a deprecated legacy alias: use the wallet endpoints instead.
- Copy and translation polish in both languages; the movements table now
includes the
wallet_creation_feeandwallet_creation_refundentry types.
Improved
- Professional-grade API Reference: all 25 endpoints now include request and response examples for every case (success, idempotency replay, and each possible error with its real body), ready to try from the docs playground.
- The 5 webhooks are now documented inside the API Reference itself (standard OpenAPI Webhooks section), with schema and example payload for each event.
- Methods and banks catalogs documented with the system’s real response shapes.
GET /healthzendpoint documented (service status).- The Crypto guide adds “Wallet balance and activity”: how to check your
balance, on-chain activity with
tx_id, and the accounting history. - Brand-voice copy: the whole documentation now speaks as CBPay (it previously used generic wording like “your operator” or “the organization”).
- Identity verification is now named KYC/KYB across the documentation (KYC for persons, KYB for companies).
- Internal transfers: explicitly documented that they work between any combination of accounts (person↔person, person↔company, company↔company) and are always free.
Added
- New
wallet_creationfee service: the first creation of a deposit address on each chain may carry a fixed charge configured by CBPay (0 = free, the default). TheGET /v1/crypto/deposit-addressresponse now includescreation_fee, and the movements history adds thewallet_creation_feeandwallet_creation_refundentry types. Fetching an existing address remains always free; if creation fails, the charge is refunded automatically. - New Changelog page (this page) with the version history of the API and documentation.
- The Crypto guide now has an explicit “Create your wallet” section
explaining per-network creation (201 on first call with
creation_fee, free 200 afterwards), and the API Reference renames the endpoint to “Create or get my wallet (deposit address)”.
Added
- Per-operation compliance fees:
compliance_person,compliance_company,compliance_rescreenandcompliance_monitoring(fixed per-call charge; 0 = free). KYC responses now includecompliance_serviceandcompliance_fee. POST /v1/kyc/rescreenandPATCH /v1/kyc/monitoringendpoints (disabling monitoring is free). Both require a prior KYC (409 no_kyc).
- Official CBPay brand identity applied across the documentation.
- Administration documentation moved to CBPay’s internal portal; this site now covers the account API only.
Initial release
- Public CBPay API documentation, bilingual (Spanish and English):
authentication (JWT sessions and
pk_API keys), USDT money model, fees, idempotency, multi-country fiat payouts, payins, internal transfers, crypto (on-chain funding and withdrawals), KYC, signed webhooks and the full error catalog. - Interactive API Reference generated from OpenAPI 3.1.