v2.61
v2.61
Added- Account locale
en/es/zh.GET /v1/menow returnslocale.PATCH /v1/mewith{ "locale": "en" | "es" | "zh" }persists it; an empty string stores English; any other non-empty value returns400 invalid_locale("locale must be en, es or zh"). New accounts pick locale at birth (body, thenAccept-Language, then the orgdefault_locale, then English). Guide: Locale and language.
- Human surfaces default to English. Hosted pages (checkout, public tracker, receipts, status, Qscore seal, verification report), PDF receipts/statements and CSV headers resolve
enunless a valid?lang=/?locale=, the account profile, the org default orAccept-Languagesays otherwise. Invalid query locale is ignored (never400). API JSON bodies and webhooks stay in English. - Payer cookie
cbpay_pay_locale(30 days,Secure,SameSite=Lax) on public pages; it does not translate JSON. - Existing accounts keep Spanish. A one-shot deploy step stamps
locale=eson accounts that had no locale so live Hispanic clients do not flip to English. New accounts still default to English.
v2.60
v2.60
Changed- US ACH, wire and SWIFT return
bank_referenceimmediately. The create response staysprocessingand already carries the CBF reference the beneficiary (and you) can match with the bank. The payout completes when the bank confirms — listen topayout_status_changed. Other corridors still leavebank_referenceempty until the rail reports it.
v2.59
v2.59
Changed- USD bank-rail payouts: the beneficiary may live in any country
(payouts guide): for
ach,wireandswifttransfers the beneficiary’scountry_codeis no longer fixed toUS— for example, an ACH to a US bank account for someone living in Germany. The receiving bank stays in the US forach/wire(bank_country: "US"— domestic rails do not pay banks abroad); forswiftthe bank may be in any country.stateis required only when the beneficiary lives in the US. Annex-B jurisdictions (CU/IR/KP/SY) stay blocked for both the beneficiary and the bank country. - Supporting document required on every USD bank-rail transfer: USD
payouts via
ach,wireandswiftalways require a supporting document (invoice/receipt) uploaded first viaPOST /v1/payouts/documents, regardless of the beneficiary’s country — previously the requirement depended on the country. A missing document returns400 supporting_document_required.
v2.58 · 3 releases
v2.58
Changed- Card payins with a settlement delay confirm as
creditedright away (fees): withsettlement_hours > 0, a paid card payin now flips tostatus: creditedat payment time — thepayin_creditedwebhook fires immediately and a card-paid checkout link closes as paid. What waits is only the balance: it lands in your ledger atsettle_at(the settlement worker runs every minute) or earlier if your org admin releases it manually. Previously the payin stayedpendingandpayin_creditedonly fired at settlement. - New payin fields: while the balance is scheduled, the create/GET/list
responses carry
settle_at(RFC 3339) andsettlement_pending: true; once the balance lands they carrysettled_atinstead. payin_settlement_scheduledpayload: the webhook now reportsstatus: "credited"(waspending), matching the immediate confirmation.
- New error
settlement_pending(422): refunding a card payin whose balance is still scheduled for settlement is declined until the funds are released (atsettle_at, or earlier by an org-admin release). Details in refunds.
v2.57
Added- New webhook event
payin_settlement_scheduled: when your organization has a settlement delay configured for card payins (settlement_hours > 0), a paid card payin stayspendingwith a futuresettle_atuntil the settlement worker releases the funds. From today, the moment the payment is confirmed you receivepayin_settlement_scheduledexactly once (idempotent — a retry never re-emits it) with the full quote:usdt_gross,fee,usdt_net(the amount that will be credited at maturity),settle_atandreceipt_url. Previously the only signal was the payin sitting inpendingwith no confirmation. At maturity the worker credits the balance and emitspayin_creditedas usual. Subscribe withevent_type: "payin_settlement_scheduled"like any account event.
v2.56
Changed- Neutral balance summary on banking balances:
GET /v1/banking/accounts/{bankAccountID}/balanceandGET /v1/banking/third-parties/{thirdPartyID}/accounts/{bankAccountID}/balancenow return three optional top-level fields next to the (unchanged)balanceobject:availableandheldas flat decimal strings (e.g."1250.00","0.00") andcurrency(ISO 4217, e.g."USD"). They are the recommended way to read the amount — previously the amount only existed nested inside the rail-nativebalanceobject, whose shape varies per rail. Thebalanceobject keeps the full account detail (display name, requisites to receive money).
v2.55 · 6 releases
v2.55
Added- Configurable card payin settlement (fees):
the
payin_cardfee configuration now acceptssettlement_hours(integer ≥ 0, default0= immediate credit, exactly as before). With a delay configured, an approved card charge leaves the payinpendingwith a newsettle_attimestamp (RFC 3339) in the create, detail and list responses — the balance credit, thepayin_creditedwebhook, the checkout link closing and the auto-conversion all happen atsettle_at(a worker settles due payins every minute). A payin whose deadline already passed when it gets approved or assigned credits immediately. Sendingsettlement_hoursfor any other service (or a negative value) answers400 invalid_settlement_hours. - Banking rail fees (fees): five
new transactional fee services —
banking_deposit,banking_transfer_ach,banking_transfer_swift,banking_transfer_wireandbanking_transfer_sepa— percent + fixed, charged in the operation currency (BANK_USD/BANK_EUR). Deposits are charged when credited (capped at the deposit amount, so a small deposit never goes negative); outbound transfers are charged at dispatch with a fail-closedbalance >= amount + feecheck and the fee is refunded if the transfer is definitively rejected. A rail with no specific configuration falls back to the legacybanking_operationservice; a rail configured at 0% + 0 fixed is explicitly free and never falls back.
v2.54
Changed- Date filters now use your organization’s timezone: every
from/todate filter (YYYY-MM-DD) on platform listings (payouts, payins, crypto withdrawals, banking transfers, expenses, statement, analytics, revenue) now interprets the day in your organization’s timezone instead of UTC.fromis midnight of that day in your zone (inclusive) andtois midnight of the next day in your zone (exclusive). The timezone is an organization setting (timezone, IANA name) managed by the platform — the default isAmerica/New_York— and the current value is exposed inGET /v1/brandingastimezone. Daily buckets of analytics and revenue also group by your organization’s civil day. No request shape changed: only the calendar day aYYYY-MM-DDfilter covers.
v2.53
Added- Verifiable public Qscore seal (seal guide):
company accounts with band A or B and a fresh evaluation (no older than 90
days) can activate a public, verifiable seal —
POST /v1/qscore/my-seal(idempotent by design: a replay answers 200 with the current seal), check it withGET /v1/qscore/my-seal, then share the public page or embed the live SVG badge (badge_url). The page and the badge re-evaluate eligibility on every view: if the score drops below band B or the evaluation ages past 90 days, the seal switches to “not current” — it never reveals the reason or the numeric score (anti-oracle). The holder can revoke at any time withDELETE /v1/qscore/my-seal; revocation is permanent for that seal and a new one can be activated right away. New public endpoints:GET /platform/verify/qscore/seal/{code}(JSON, or a branded HTML page for browsers) andGET /platform/verify/qscore/seal/{code}/badge.svg(embeddable live badge). New error codes:seal_companies_only,seal_not_eligibleandno_active_seal. No new webhooks.
v2.52
Added- Qscore consent links (holder authorization) (consent links guide):
ask a subject to authorize read access to their banking data with a shareable
link —
POST /v1/qscore/consents(idempotent, optionally emailed to the holder with your branding), then track withGET /v1/qscore/consentsandGET /v1/qscore/consents/{id}, or cancel withPOST /v1/qscore/consents/{id}/revoke. The holder decides on a public page (no login): they connect their bank through the secure widget and the verified holder identity must match the subject’s document exactly (an account under a different document never grants consent). Once granted, CBPay derives positive banking facts (accounts, balances, 90-day income/expense activity) into the subject’s credit file — Qscore reports re-derive them on every generation so the data stays fresh. New webhooks:risk_consent_grantedandrisk_consent_revoked. New error codes:purpose_required,invalid_purpose,invalid_doc_id,invalid_subject_type,invalid_email,already_decided,link_inactiveandholder_mismatch.
v2.51
Added- Qscore batch scoring (portfolio scoring) (Batch scoring guide):
upload a batch of subjects with
POST /v1/qscore/batches— a JSON array or a CSV string, up to 5,000 subjects per batch — and the platform issues one full Qscore report per subject asynchronously. Rows are validated upfront (invalid document ids, unsupported subject types and in-batch duplicates are reported inrejected_itemsand never processed); each item is billed the standalone report fee when processed and automatically refunded if it fails terminally. When the batch finishes you receive onerisk_batch_completedwebhook and one email with the counters — the individual reports do not emit their own webhook or email. Read the per-item results withGET /v1/qscore/batches/{batchID}/itemsor download them withGET /v1/qscore/batches/{batchID}/results.csv. New error codes:no_valid_itemsandtoo_many_items.
v2.50
Added- Qscore company reports may now include a
peer_benchmarkblock: the score’s position within its industry segment (same country, same ISIC industry). It reports the segment code and label (segment_code/segment_label), the number of comparable companies (peers), thepercentile(share of peers with a lower score) and the segment’smedian_score. The block is published only when at least 5 comparable companies exist, and only for company reports.
v2.49 · 9 releases
v2.49
Added- Qscore — your own credit report, free (Qscore guide):
the holder of a verified account can now pull THEIR OWN Qscore credit
report — the ARCO / data-protection right of access — with
POST /v1/qscore/my-report(optionally{"lang":"es"|"en"|"zh"}), read the latest one withGET /v1/qscore/my-reportand download the branded PDF withGET /v1/qscore/my-report/pdf. Unlike a purchased report, the self report is free (no fee), the subject identity comes from the verifiedtax_idof the account (the request never accepts adoc_id— pulling a third party’s report through these endpoints is impossible by design), one NEW report can be generated every 30 days (within the window the existing one is returned withidempotency_hit: true), and self reports are excluded from the subject’s query count, so checking your own report never penalizes your score. Therisk_report_readywebhook of a self report carriespurpose: "self_access". The commercial endpointPOST /v1/qscore/reportsnow rejectspurpose: "self_access"with400 invalid_purpose. New error codes:kyc_required,no_tax_id,invalid_tax_id(errors).
v2.48
Changed- Banking and card applications can now be held for review (banking guide, cards guide, transaction reviews): if your organization enabled application review,
POST /v1/banking/customer,POST /v1/banking/third-partiesandPOST /v1/cardscan answer202 Acceptedwith{"status":"in_review","kind":"...","review_id":"..."}instead of creating the resource right away — nothing is sent for processing until compliance approves the review. The opening/issuance fee is charged when the application is held and refunded automatically if it is rejected. A retry with the sameidempotency_keyreturns the same review (idempotency_hit: true) and never double-charges. Track the outcome with thetxn_review_status_changedwebhook or in Transaction reviews (kindsbanking_application/card_application).
v2.47
Added- Qscore — continuous subject monitoring (Qscore guide):
once you own a
readyreport for a subject, subscribe withPUT /v1/qscore/subjects/{docID}/monitoringand the platform re-evaluates the subject every ~5 minutes, emitting the new webhookrisk_monitoring_alertwhen the score drops below yourmonitor_since_scorethreshold (score_drop_below), when new bureau records appear (new_records) or when records are removed (records_removed) — withonly_material: trueonly the material triggers fire. Manage subscriptions withGET /v1/qscore/subjects/{docID}/monitoring,GET /v1/qscore/monitoring(every monitored subject of the account) andDELETE /v1/qscore/subjects/{docID}/monitoring(deactivates withactive: false— the history is never deleted). Monitoring is free but requires a purchased report for the subject: without one the API answers403 report_required, the same response a non-existent subject gets (by design, so subject existence cannot be probed). New error code:report_required(errors).
v2.46
Added- Bank reference of a payout, now visible on every surface
(payouts guide): every payout exposes
bank_reference— the transaction id assigned by the destination bank/rail — in the responses ofPOST /v1/payouts,GET /v1/payoutsandGET /v1/payouts/{payoutID}, in thepayout_status_changedwebhook payload, on the PDF receipt, in the payouts CSV export and in the statement (JSON and Excel). The field is empty ("") while the payout is in flight and populated once it iscompleted— it is the reference the beneficiary can use to cross-check the payment with their bank.
v2.45
Added- Qscore — API-first credit bureau (Qscore guide): buy
credit reports on people and companies (
POST /v1/qscore/reports), Chile first. Each report aggregates negative records, labor and pension background, unpaid leaves and official gazette publications into a 0–1000 score with bands A–E (SCwhen there is no data), reason codes, a branded PDF and a public verification code.GET /v1/qscore/subjects/{docID}/scorereads the current score of a subject you already reported on,GET /v1/qscore/reports/{reportID}/pdfdownloads the PDF, and the ARCO rectification flow runs throughPOST /v1/qscore/subjects/{docID}/disputes+GET /v1/qscore/disputes/{disputeID}. Reports are billed per document type (risk_report_person/risk_report_company) and require the declaredpurposeunder data protection law. New webhooks:risk_report_readyandrisk_score_changed. Requires theriskservice flag. - Public report verification:
GET /v1/verify/qscore/{code}validates the code printed on a Qscore report and returns the non-sensitive facts (subject class, band, issue date) — no PII. - New error codes:
purpose_required,invalid_purpose,invalid_doc_id,invalid_subject_type,no_score,pdf_not_ready(errors).
v2.44
Fixedpayin_receivedevents are no longer generated for internal bank reversals of the operator’s treasury account (the reversal of an own outbound transfer was never a customer payment).
v2.43
Changed- Cities catalog quality pass (AML catalogs guide): the
cities served by
GET /v1/aml/catalogs/cities?country=<CC>were regenerated for correctness and coverage. Names keep their local spelling (accents,ñ,ü— “Alhué”, “Coyoacán”, “São Paulo”), local names replace English exonyms (“Ciudad de México”, not “Mexico City”), and urban divisions are now complete — every comuna of Santiago, the districts of Lima, the alcaldías of Mexico City, municipalities across the region. Source noise was removed (US census suffixes like “Abanda CDP”, residual administrative prefixes, duplicate spellings). Same response shape and error codes — no integration change.
v2.42
Added- Tracking link from the API (tracking guide): the new authenticated
GET /v1/track-link?kind=<kind>&id=<id>returns the shareable public tracking link of any transaction in your read scope —{ "track_url", "code" }— without downloading the receipt PDF. It is the building block for a “Share link” button in your UI. Thecodeis the same deterministic HMAC code printed on every receipt, so the link is always the same for a given transaction. Available to the account itself, to org admins and to platform admins; a transaction outside your scope answers a uniform404 not_found.
v2.41
Added- Public tracking link for every transaction (tracking guide): every
receipt (payout, payin, refund, internal transfer, swap, crypto withdrawal or deposit, banking
operation, card purchase) now carries a shareable public link —
https://business.cbpayapp.com/t/{code}, with the same signed code printed on the receipt — that opens a Wise-style tracking page with the live timeline, the receipt PDF download and language selection (EN/ES/ZH). The page isnoindex, never cached, and shows review-type states asprocessing(no tipping-off). - Public tracking endpoints:
GET /v1/public/track/{code}?lang=returns the public JSON state of a transaction andGET /v1/public/track/{code}/receipt.pdf?lang=regenerates the receipt PDF on the fly. Both are unauthenticated, rate-limited per IP and answer a uniform404 not_foundto invalid or tampered codes. - Receipts in Chinese: receipt PDFs and the tracking page now fully support
lang=zh.
- Receipt
verify_urls open the tracker: theverify_urlof new receipts and of receipt emails now points to the tracking page. The legacyGET /v1/verify/receipts/{code}stays live — browsers are redirected (302) to the tracker while API clients keep receiving the same JSON verdict as before.
v2.40 · 4 releases
v2.40
Added- Bank directory lookup (payouts guide): the new
GET /v1/payouts/bank-directory/lookupautocompletes the beneficiary bank from an embedded public bank directory — pass exactly one ofrouting_number(9 digits, US only) orswift(8 or 11 characters; anXXXsuffix is normalized to the head office) and it resolves the bank name, city, state and address block, so payout and counterparty forms can prefillbank_nameand the optionalbank_*fields while the sender types. A404 bank_not_foundsimply means the code is not in the directory: keep the form manual. Static data withCache-Control: public, max-age=86400. - Postal code lookup (AML guide): the new
GET /v1/aml/catalogs/postal-code?country=US&code=33130resolves a US ZIP code to itscityandstate, so address forms can autofill both fields while the user types the ZIP. Only US has a dataset today; a404 postal_code_not_foundmeans the ZIP is unknown (or the country has no dataset) and the fields stay manual.
- Cities catalog quality cleanup:
GET /v1/aml/catalogs/citiesnow dedupes cities by their folded form (diacritic-free, case-insensitive), unifies the Hawaiian ʻokina, drops two corrupted glued entries, collapses internal whitespace, and servesContent-Type: application/json; charset=utf-8.
v2.39
Added- Cities catalog per country (AML guide): the new
GET /v1/aml/catalogs/cities?country=USreturns the cities of one ISO 3166-1 alpha-2 country grouped by subdivision —stateskeys are the same ISO 3166-2 codes ascountry_subdivisionsin the main catalog, andcountry_citieslists the cities whose region could not be mapped (neither field is evernull). A country without coverage answers200with empty lists (fall back to a free-text city field); a malformed code gets400 invalid_countryand an unknown one404 country_not_found. Static data withCache-Control: public, max-age=86400— one call per country, then filter by state on the client. - US/USD payins now publish two deposit rails (payins
guide): the announced
bank_transfercorridor serves a domestic wire instruction (ABArouting_number) and an international SWIFT instruction (BIC + correspondent bank) side by side — the announcement, the payin reads and theGET /v1/payins/deposit-instructionspreview all exposedeposit_instructions(domestic) anddeposit_instructions_swift(international), each with its own copy-paste QR, so the payer picks the rail their bank supports. Both blocks carry the newholder_addressandnotesfields when configured (the QR prints them as “Holder address” and “Note” lines). Fail-closed: a US/USD corridor missing its SWIFT variant answers422 deposit_instructions_unavailableat announcement time.
v2.38
Added- Automatic rejection by review deadline (transaction reviews guide) —
if your organization configured a review deadline for the transactional
firewall, a review nobody decides within that window (counted from its
last status change — uploading evidence resets the clock) is
automatically rejected by an hourly sweep: the operation is cancelled,
any held funds return to your balance, and you receive the same email and
txn_review_status_changedwebhook (status: "rejected") as with a manual rejection. The review detail carries the standard deadline notice indecision_note.
v2.37
Added- New payin corridor: United States (USD) via announced bank transfer
(ACH / wire). The account announces the deposit with
POST /v1/payins{method: "bank_transfer", country: "US", currency: "USD", amount, idempotency_key, payer_name?}and the response carries the uniqueCB…reference,status: "pending"and the completedeposit_instructionsblock — which now supports the US banking fieldsrouting_number(ABA),swift(BIC),bank_address,intermediary_bank_nameandintermediary_bank_swift. The client transfers from their bank with theCB…reference in the transfer memo; when the deposit reaches the collection account it is matched by reference and credited in USDT (status: "credited"withusdt_creditedandfx_rate). A bank credit with no announcement or reference staysunassigned— fail-closed, it is never auto-credited. You can preview the destination account without announcing viaGET /v1/payins/deposit-instructions?country=US¤cy= USD&method=bank_transfer. The United States joins the corridors that require the organization to have deposit instructions configured: announcing without them fails with422 deposit_instructions_unavailable. US tab with full request/response examples, status table, errors and FAQ in the Payins guide; thedeposit_instructionsblock and the preview endpoint are updated in the API reference.
v2.36 · 3 releases
v2.36
Added- Transactional firewall: when your organization has the transactional
firewall enabled, money operations (payouts, crypto withdrawals, payins
and banking transfers) can be held
in_reviewawaiting a human decision — the API answers202 Acceptedwith areview_id. New account endpointsGET /v1/me/txn-reviews(list and detail),POST /v1/me/txn-reviews/{reviewID}/files(upload the requested documents) andGET .../files/{fileID}/download(download your own files), plus the newtxn_review_status_changedwebhook (neutral payload — internal reasons never travel). New guide: Transaction reviews.
v2.35
Added- New payout corridor: United States (USD) with three methods —
ach(next-day ACH to checking or savings accounts),wire(domestic wire) andswift(international USD wire via SWIFT). The rail requires the beneficiary’s complete identity and postal address on every transfer (name,email,account_number,country_code,address,city,postal_code,bank_nameandbank_code— ABA routing number forach/wire, SWIFT BIC forswift;account_typeCHECKING/SAVINGforach), with the receiving bank’s address block andbank_phoneas recommended optionals.wireandswifthave a USD 25.00 minimum. The first payout to a brand-new beneficiary may stayprocessingwithstatus_code: "pending_aml"while the rail reviews the beneficiary, and executes automatically on approval; a rail rejection ends the payoutfailedwithstatus_code: "counterparty_rejected"and an automatic refund. Per operation you can override the rail’s payment-purpose declarations inoptions(purpose,crypto_activity,payment_gateway). Corridor table, per-method field table, real examples and FAQ in Payouts; named request examplesus_ach,us_wireandus_swiftin the API reference.
v2.34
Added- The MCP Server page now mentions the dedicated MCP server for
the organization administration documentation
(
mcp-admin.cbpayapp.com, being deployed), so organization administrators know there is an equivalent assistant feed for the org-admin API — this public server keeps covering the account-level API.
v2.33 · 2 releases
v2.33
Added- More transparency in document validations: the document list of a
submission (
GET /v1/{kyc,kyb}/submissions/{id}/documents) now exposes on each validation itsid, theeffective_outcome(the verdict currently in force, which may come from a manual review by the operator) and themanual_reviewblock withoutcomeandreviewed_atwhen a validation was reviewed by hand. The submission detail also carriesdocuments_gate, a summary of the validation status (ok,matched,totaland the categories still unresolved). No flow changes: these are additive, read-only fields.
v2.32
Added- Automatic KYC/KYB decisions: verification submissions are now decided
by an automatic engine before reaching a human reviewer. A 100% clean
file (documents verified, liveness passed, no sanctions or PEP hits,
low-risk geography) is approved in minutes with no manual queue.
Grey areas (homonym AML matches, PEP signals, partial document reads,
medium risk, high-risk countries) always go to a human reviewer,
and clearly invalid files (confirmed severe sanctions, false or expired
documents) are automatically rejected. Final decisions now carry
decision_source(autooradmin) in thekyc_verification_status_changedandkyb_verification_status_changedwebhooks so you can tell how each file was decided. Details in KYC and KYB. - New
HOLDREVIEWmagic value in the testing environment: a KYC/KYB submission whose subject name containsHOLDREVIEWstays in human review instead of being auto-decided, so you can exercise the manual queue end to end. The companion magicMANUALREVIEWkeeps every signal clean but never settles the submission on its own, so the automatic approve/reject paths of the decision engine can be tested deterministically. See testing environment.
v2.31 · 4 releases
v2.31
Added- Enriched banking operation fields:
GET /v1/banking/operationsandGET /v1/banking/operations/{id}now expose optionaldirection(in/out), netamount,currency,counterpartyandreferencefields whenever the bank reports them — including inbound deposits and bank fees discovered automatically in the operations list. Thebanking_operation_status_changedwebhook is unchanged by design (lightweight + fetch detail). Details in banking.
v2.30
Changed- Sanitized error messages across the API. An error
messagenever exposes provider names, infrastructure details, URLs, raw upstream bodies (JSON/HTML), or internal configuration — not in API responses, webhooks, or stored status fields. Business rejections from the payment processor keep their actionable reason (for example, why a document or account was rejected); infrastructure failures are replaced by the fixed generic message"the payment provider could not process the request"— retry those operations with the sameidempotency_key. No shape changes: only message contents changed.
v2.29
Added- Per-purchase card fees: card transactions can now carry a
transactional fee (percent + fixed) configured per account through two
new services —
card_purchase_virtualandcard_purchase_physical. The fee is estimated at authorization (included in the balance hold), recalculated at settlement with the configuration in force at that moment, and refunded pro-rata on partial or total reversals and adjustments. Card transactions now exposefee_asset,fee_amountandfee_refunded_amount(omitted when no fee is configured — accounts without configuration see no change), the purchase receipt shows the fee line, and the ledger records the movements ascard_fee/card_fee_refund. Details in cards.
v2.28
Added- Saved cards with payer verification on the payment page: every card
payment page (the
payment_urlof acardpayin and the card option of the universal checkout) now asks for the payer’s email as the first field and, when that email has saved cards with you, emails a verification code before showing them — the list is never revealed without verification. With “Remember this device” (checked by default) the payer skips the code for 30 days on that browser. Picking a card pays with 3-D Secure without re-typing it. Details in stored cards.
- The universal checkout no longer asks for the payer’s email: the card
option materializes and redirects straight to the payment page, where the
saved-cards discovery now lives. The public endpoint
GET /pay/{token}/saved-cardswas removed (it answers 404) — the card list no longer leaves any surface without verification. No contract changes:POST /v1/payins(cardandcheckout) is unchanged, and server-to-serverstored_card_idneeds no code (you already know your customer).
v2.27 · 2 releases
v2.27
Added- Disable and reactivate webhook subscriptions: new
PATCH /v1/webhooks/subscriptions/{subscriptionID}with{ "status": "active" | "disabled" }— adisabledsubscription stops receiving new events without being deleted (deliveries already queued are still sent) and you can reactivate it at any time. Idempotent: repeating the current status is a no-op200. See the webhooks guide.
v2.26
Fixed- Verification status protected against late events from older attempts: when an account retries identity verification (for example, after a rejection), a late status event from an earlier attempt can no longer change the account’s verification status or trigger the decision email — only the most recent attempt decides it. Every attempt keeps its full history in the admin panel.
v2.25 · 3 releases
v2.25
Changed- Administration error codes documented: added the
global_treasury_access_disabledandinvalid_valueerror codes to the error catalog. These come from organization administration surfaces (the CBPay Admin panel), not from the account-level API — see the new “Organization admin panel” section.
v2.24
Added- Deposit instructions for announced bank transfers
(payins guide): creating a payin with
method: "bank_transfer"on supported corridors now returns adeposit_instructionsblock with the exact destination account —bank_name,account_number,account_type,holder_name,holder_tax_id,holder_email,reference_required, a copy-pasteqr_payload(multi-line text with the account, the holder and your reference/amount) and a brandedqr_png_base64. The same block is echoed back on the payin’s detail and list responses. The newGET /v1/payins/deposit-instructions?country=¤cy=&method=previews the destination account before you create the payin. See the guide’s FAQ for why the bank QR is scan-to-copy, not auto-fill.
v2.23
Added- Automatic KYC/KYB decision emails (self onboarding): when your
verification lands on approved, rejected, or changes requested, you get a
branded email with the organization letting you know the outcome. Does not
apply to third-party verifications (for example, your company verifying a
customer or vendor) — that flow keeps using the
kyc_status_changed/kyb_status_changedwebhook you already integrated. The email never includes the detailed reason for a rejection, for security and privacy reasons.
v2.22 · 1 release
v2.22
Changed- Liveness now supports multiple sessions per subject
(identity verification): the verification report’s
liveness[]array can carry more than one entry per person — the onboardinggatecheck plus one or more later evidencemedia_recaptures. Each session now carries its ownsession_idandpurpose(gateormedia_recapture). In a KYB,parties[].liveness(singular) is kept for compatibility and always points to that party’sgatesession, while the newparties[].liveness_sessions[]carries every session for that party. Media metadata stays URL-free (has_selfie,has_video,frame_gestures, hashes) — no contract change there.
v2.21 · 1 release
v2.21
Changed- Verification report with a navigable cover (identity verification): the PDF opens with an index of clickable cards (icon, title and page number) that jump to their section. Every section carries its icon and accent bar, matching the visual language of the AML report.
- Clickable links: adverse media entries in the AML annex carry a “view
source” chip and the public verification URL in the closing block is
clickable. For safety, only
httpandhttpslinks are embedded — any other scheme is dropped and the text stays unlinked. - Photos keep their real aspect ratio: identity document and liveness photos are rendered without stretching, with their caption underneath.
- No blank pages, no orphan headings: each section header reserves the height of its first block, so it never sits alone at the bottom of a page.
- The aggregated adverse media status now reads “Review” (was “In review”).
v2.20 · 2 releases
v2.20
Added- Visual evidence in the verification report
(identity verification): when the provider publishes
liveness media (selfie / frames) or identity document photos, the PDF
embeds the photos best-effort. If media is missing or the link expired,
the photo section is omitted. The report JSON only declares metadata
(
has_selfie, gestures,has_video, hashes) — never signed URLs. - Full AML annex at the PDF closing: when a screening exists, the report reuses the same closing as the standalone AML report (attribution, coverage stats, source blocks and legal notice). Without a screening it keeps the generic disclaimer.
v2.19
Added- Complete verification report, nothing discarded (identity verification): the KYC/KYB report went from summary to full file. On top of what it already carried, the JSON and the PDF now include the declared economic profile (source of funds, purpose of the relationship, expected volumes and income, expected chains), the risk attestations (money services, third-party funds, high-risk activities, prohibited countries), the bank account masked at the source (the full number never enters the report), the extended company identity (incorporation, jurisdiction, ISIC industry, website, countries of operation, registered address) and the remainder of the file: every verified field that does not fit a structured section is still emitted in the fields block.
- Related parties with their own AML screening (KYB): every UBO,
control person and signer in the file is emitted as a
parties[]entry with its identity, its ownership, the documents and liveness proof that belong to it, and its own AML screening with continuous monitoring enabled. No charge: this is diligence, not a billable product. The(source, index)pair is the stable identity of the party, so its screening is always the same no matter how many times you download the report. If a party has no screening yet at download time, the report comes back with"partial": ["party_aml_unavailable"]and the missing one runs in the background. - AML screening with per-match detail: the AML section of the full
report (third parties and admin reads) now carries indicators, aliases,
sanctions lists with source and validity, PEP positions, RCA links and
adverse media — the same level of detail as the AML report. On your own
onboarding report the section stays aggregated (
clear/under_review, no matches), and the same applies to the screening of your related parties. - Document validation in the document detail: every document in the
report exposes
validated_atand, when applicable, the rejection reason, alongside category, filename, status, outcome and score.
v2.18 · 3 releases
v2.18
Fixed- Amounts always as plain decimals (payins): the
local_amountfield on payins (and theamounton charge events) is always returned as decimal text — for example"5000000"— never in scientific notation. On large deposits in zero-decimal currencies (CLP, PYG, COP) a credit could be recorded as"5e+06": the amount was unreadable for your integration and the deposit failed to match its announced transfer, so it was never credited. The fix also covers historical records: reading them through the API now returns them normalized, without altering any accounting data.
v2.17
Added- Downloadable KYC/KYB verification report
(identity verification): every KYC/KYB submission now
has a platform-generated verification report, with
?format=pdf|jsonand?lang=en|es|zh. Third parties:GET /v1/kyc/submissions/{submissionID}/verification-reportandGET /v1/kyb/submissions/{submissionID}/verification-report(company account, full report: verified identity, lifecycle, documents + OCR, liveness and AML screening with matches). Own onboarding:GET /v1/me/verification/report(same structure with an aggregated AML section). Free of charge — it reads the verification already paid for. - Public report verification code: the PDF prints an HMAC code + QR
and anyone can validate the document at
GET /verify/reports/{code}(JSON or HTML page, no personal data: only kind, current decision status, issue date and issuing organization). - New error codes:
invalid_format(400,formatother thanpdf/json) andverification_not_found(404, the account has not submitted any verification yet);invalid_languagealso applies to this report.
v2.16
Fixed- QR collections now always credit on their own
(payins): a paid QR could stay
pendingwhile the money arrived as an unassigned deposit, because the bank transfer does not carry the collection’s reference and amount-based reconciliation is reserved for announced transfers. The deposit that settles a collection (QR, checkout link or card) now travels with the link to the paid charge and is routed one-to-one to its payin — no heuristics. The credited payin declares it withmatch_method: charge_link, the strongest reconciliation signal of all. match_methoddocumented enum: the reference listedsingle_candidateanddedicated_instrument, which do not exist in the API. The real values areamount_single_candidateanddedicated_clabe;charge_linkandmanual_assign(an admin routed the deposit by hand) were added to the spec.
v2.15 · 1 release
v2.15
Fixed- Announced transfers now honour idempotency (payins):
POST /v1/payinswithmethod: "bank_transfer"acceptedidempotency_keyand ignored it, so a retry (timeout, double click) opened a second announcement. Two live announcements with the same amount are exactly the case matching refuses to resolve, so the real deposit landedunassigned. A retry with the same key — body field orIdempotency-Keyheader — now replays the original announcement (samereference, HTTP200withidempotency_hit: true). A POST without a key reuses a live identical announcement (same account, currency, amount and payer) instead of duplicating it. To collect two real payments of the same amount from the same payer, send a different key for each announcement. Reusing a key that was already used with ANOTHER payin method (QR, checkout, card) now replies409 idempotency_conflictinstead of returning an object that does not match the request.
v2.14 · 6 releases
v2.14
Added- Payer identification on announced transfers (payins):
POST /v1/payinswithmethod: "bank_transfer"accepts the optionalpayer_name,payer_documentandpayer_account. If you do not sendpayer_documentand the account is a verified individual, the holder’s document is used by default, so a deposit that arrives without a reference is still matched by the payer the bank reports. The response says which identity is in play withpayer_source(declared,account_identityornone). - Matching audit on the payin:
GET /v1/payins/{id}exposesmatch_method(reference,payer_document,payer_account,payer_name,single_candidate…) and thepayerblock the rail reported, so you can see exactly why a deposit landed in that account.
- Announced transfers no longer match “the oldest one” by amount: if two or
more pending announcements share amount and currency and nothing identifies
the payer, the deposit stays
unassignedinstead of crediting the wrong account (fail-closed). The amount-only match survives only when there is exactly ONE candidate. Documented in the new How an announced transfer is matched section.
v2.13
Added- Handshake quota on the event stream (errors): opening
GET /v1/eventstoo many times in a row now answers429 rate_limited. It is a different limit fromtoo_many_streams:rate_limitedcounts connection attempts per IP (600 per hour, plenty for reconnects), whiletoo_many_streamscaps how many streams you keep open at the same time (5 per account). Both retry the same way: wait and reconnect with yourLast-Event-ID, nothing is lost.
v2.12
Added- Real-time event stream (guide):
GET /v1/eventsopens a Server-Sent Events connection with everything that happens in your account — the same events as the webhooks, delivered to the browser without waiting for a poll. Reconnect with theLast-Event-IDheader and the server replays what you missed, filter with?types=and ask for the absolute current state with?snapshot=true. - Queryable event history:
GET /v1/events/history(withfrom/to, pagination and filters by type) andGET /v1/events/{eventID}read the same log that feeds the stream, kept for 90 days. - Three new events (webhooks):
balance_adjusted(an admin credited or debited your balance),account_status_changed(your account was suspended or reactivated) andmember_security_event(logins, password or 2FA changes, revoked sessions). They arrive both by webhook and through the stream. - New error codes (errors):
too_many_streams,stream_unavailableandstreaming_unsupported.
v2.11
Added- Card payin refunds (guide):
POST /v1/payins/{payinID}/refundsrefunds a card payin in full or in part and debits the amount from your balance right away. Refunds require an idempotency key (retrying with the same key never refunds twice) and an OTP code when requested with your session.GET /v1/payin-refundslists your refunds with filters by account, status, kind and date range,GET /v1/payin-refunds/{id}returns the detail andGET /v1/payin-refunds/{id}/receiptgenerates the PDF receipt with a verifiable code. - Refund state on the payin: refunded payins expose
refund_status(partialorfull),refunded_amount(accumulated USDT debited) andrefunded_local(accumulated amount returned to the cardholder). payin_refundedwebhook (webhooks): notifies every refund, void and chargeback with its kind, status, amounts and the resulting balance.
- Fees and FX margin are not refunded: refunding a payin debits the gross amount credited; what we charged to process the payment stays. A chargeback notified by the issuer is applied automatically and may leave your balance negative until you fund it.
- New error codes (errors):
payin_not_refundable,refund_not_supported,refund_exceeds_payinandinvalid_amount.
v2.10
Changed- Public service status page redesigned
(guide): the page returned by
status_page_urlnow shows a country flag, a payment-method icon, a day-by-day availability bar for the last 90 days, a summary card with the overall state and average uptime, and an incident timeline with reasons written in plain language. It picks up your organization’s logo, colors and website, still ships with no JavaScript and no external resources (so you can embed it or share it with your customers), and the JSON at/v1/status/{token}is unchanged.
v2.09
Added- International cards in US dollars (guide):
POST /v1/payinswithcountry: "US",currency: "USD"andmethod: "card"returns a hosted checkoutpayment_urlwith 3-D Secure branded with your organization, to charge Visa, Mastercard, American Express, Discover and Diners cards issued anywhere. The contract is the same as the Bolivian card page (optionalcustomer,success_url/failure_url,expires_at, limited attempts and an idempotent retry returning the same URL), and so is card storage:save_cardpluspayer_referencestore the card with the payer’s consent for later charges and subscriptions. 3-D Secure runs inside the page (if the issuer asks for a challenge the payer completes it right there) and card data is typed into the processor’s secure fields: it never touches your integration. The corridor is enabled per account —GET /v1/payins/methodsis the source of truth for what you can collect today.
v2.08 · 6 releases
v2.08
Added- Real-time service status (guide): every method
in
GET /v1/payouts/methodsandGET /v1/payins/methodsnow carries an additiveavailabilityfield (operational/degraded/down), a new broadcast webhookcorridor_status_changednotifies every availability transition, and each organization gets a public, brand-themed status page (HTML + JSON at/status/{orgToken}and/v1/status/{orgToken}) with 90-day uptime and incident history. The status page URL is exposed inGET /v1/brandingasstatus_page_url.
v2.07
Added- Docs Knowledge Pack for AI/MCP: this documentation is now also
published as a structured, versioned pack at
/mcp-pack/manifest.json(OpenAPI specs in 3 languages, per-page guides in pure Markdown, error and webhook catalogs, testing guide with the simulator magic values, end-to-end recipes and RAG-ready chunks). It is the official source feeding the documentation MCP server.
- Compiled Markdown
CBPAY_DOCUMENTACION.mdretired: the single Spanish-only document is obsolete — its replacement is the Docs Knowledge Pack (trilingual, with complete specs) and the MCP server.
v2.06
Added- Anchor FAQ on every product guide: payouts, payins, checkout,
transfers, crypto, banking, cards, statement, QR payout and stored cards
- subscriptions now close with frequently asked questions and a direct link to the error catalog.
- Error and webhook catalogs completed: error codes and webhook event types that existed in the API but were missing from the reference pages are now documented. No contract changes.
v2.05
Changed- Docs overhaul, phase 5 (API reference only, no code change): the API
reference now groups operations under three new tags — Checkout
(public
/pay/{token}pages and quotes), Stored cards (/v1/stored-cardsand saved-card lookups) and Subscriptions (/v1/subscriptions). These operations were previously stacked under the generic Payins tag; every path and contract is unchanged.
v2.04
Added- Dedicated product guides, extracted from the payins/payouts monoliths: Checkout, Stored cards & subscriptions and QR payout. The original sections keep their headings and link to the new guides, so historical anchors still resolve.
- New end-to-end flows in Integration flows: checkout, saved cards and subscriptions, QR POS charges and balance swaps, each with its sequence diagram.
- Products navigation reorganized by product family: Money in, Money out, Balances & account, Identity & compliance, and Experience — instead of a flat 17-page list.
- Profile & security and Security and 2FA (OTP) now cross-link and state their roles: the profile guide owns the user’s 2FA factors; the OTP page owns the per-action challenge flow.
v2.03
Added- Test environment surfaced across the whole site: every product guide
now opens with the test and live base URLs (shared snippet), and the
FAQ, quickstart and
introduction correctly describe the test environment
(
https://cryptobank.qbank.cl/platform,pk_test_keys) — earlier copies incorrectly said no sandbox existed. Full details in Environments and testing.
- Introduction product catalog completed: checkout, cards and subscriptions, QR POS, swaps, segregated wallets, Bitcoin and analytics are now listed with their guides.
- Spec descriptions that predated multi-asset balances: tag descriptions
realigned (Swaps, AML screening, Cards) and legacy wording like
“credited to the USDT balance” corrected to the settlement-asset
semantics (
default_payin_asset,settlement_asset).
v2.02 · 6 releases
v2.02
Changed- Auto-conversion into
default_payin_assetnow executes at the real price, with no swap spread (money model): the payin already paid its fee and rate when it credited, so the automatic conversion into your configured balance adds no extra cost — there is no double conversion. The per-operation/24h limits of volatile assets (BTC/GOLD) still apply. Manual swaps (POST /v1/swaps) keep their regular spread.
v2.01
Added- New error code
reserved_idempotency_key(400) onPOST /v1/swaps(errors): idempotency keys prefixedpayin-convert:orcheckout-swap:are reserved for system auto-conversions (payin default balance and checkout) and are rejected. Use any other key for your swaps.
v2.00
Added- Default balance for payins (
default_payin_asset) (money model): choose which balance your incoming payments end up in.PUT /v1/settlementnow acceptsdefault_payin_asset(USDT, USDC, BTC or GOLD) andGET /v1/settlementexposes it. The payin still credits in USDT (pricing and fees untouched) and the net amount auto-converts into your asset through the swap engine (same spread and limits as a swap). If the conversion fails it staysconversion_status: pending_retryand retries automatically.GET /v1/payins, the detail and thepayin_creditedwebhook exposesettlement_assetandconversion_statuswhen a conversion applies.
- A checkout link created without
settlement_assetnow uses the account’sdefault_payin_asset(previously always USDT).
v1.99
Added- Dedicated fee for card payments (
payin_card) (fees): payments credited via card (direct payin withmethod: card, checkout links paid with card, and recurring charges on stored cards) can carry their own percentage fee, configurable per currency (e.g. one rate for BOB and another for USD). If your account has nopayin_cardconfigured, the regularpayinfee keeps applying — nothing changes without explicit configuration. Check your effective fees inGET /v1/fees(rows now include thecurrencyfield).
v1.98
AddedGET /v1/banking/accounts/{bankAccountID}(banking guide): live details of one of your bank accounts — name, currency, status and the receiving requisites (wire and local rails) underdata. Use it to render the deposit instructions of a specific account without walking the list.
- Bank account listing: the API now exposes only the accounts enabled
for your operation per the corridor configuration. Accounts that are
not enabled no longer appear in
GET /v1/banking/accountsand their by-id lookups return404.
v1.97
Fixed- Checkout page — saved card by default: when the entered email has saved cards, the primary button now pays with the saved card (its label changes to “Pay with VISA ···· 1234”) instead of starting a new-card payment. Using a different card is now an explicit action (“Use another card”). Previously, pressing the primary button while a saved card was listed led to the payment page asking for all card details again.
v1.96 · 3 releases
v1.96
Added- New corridor: Argentina 🇦🇷 (payouts guide · payins guide):
- Payouts in ARS and USD via
bank_transferto any 22-digit CBU or CVU (bank accounts and virtual wallets; USD is CBU-to-CBU only). Beneficiary takesname,tax_id(CUIT/CUIL) andaccount_number— nobank_codeneeded. - Payins in ARS with a dedicated CVU account per account (
POST /v1/payins/deposit-accountswithcountry: "AR"): every incoming transfer is credited automatically, no references needed. CVUs are receive-only: direct debit attempts are rejected automatically. - Available now in the test environment (staging) with the simulator; production activation will be announced once bank certification completes — the catalog (
GET /v1/payouts/methodsandGET /v1/payins/methods) is always the source of truth.
- Payouts in ARS and USD via
v1.95
Added- Billing on file with the saved card (payins guide): the billing details the payer enters when saving their card (name, address, city, email, phone) are stored alongside the credential. When paying again with that card, the secure page applies them automatically — the payer retypes nothing — and shows only a masked summary (name, partial email and city) with a “use different details” link in case they want to change them. The full details never reach the browser: the server applies them at authorization time.
- Cardholder email required with a saved card: on the public checkout page, paying with a saved card now requires presenting the same cardholder email it was saved with — a mismatch responds
404(anti-enumeration protection for personal data).
v1.94
Fixed- Checkout page — 1-click card payment (payins guide): continuing with a card on the public page now redirects straight to the secure payment page — the intermediate button that required a second click was removed. Picking a saved card from the list starts the payment immediately.
- Saved card on checkout: picking a saved card now always reaches the secure page with the credential applied (it shows brand and last 4 digits and never asks for the number again). Previously, the email re-validation could silently drop the selection and the page asked for every field again. Also, switching the choice on the same link (saved ↔ new card) regenerates the right payment session instead of reusing the previous one.
v1.93 · 3 releases
v1.93
Fixed- Banking webhooks for third parties (webhooks, banking guide): the
banking_customer_status_changedwebhook now also fires when a third party registered by your account changes verification state (previously only your own profile’s events arrived). The payload addscustomer_kind(self|third_party) and, for third parties,third_party_id(the same id asGET /v1/banking/third-parties/{id}).
v1.92
Fixed- Checkout charge amounts in the payin history (payins guide):
GET /v1/payinsandGET /v1/payins/{payin_id}now always include the denomination of checkout and QR POS payins —settlement_asset+asset_amount(plusconversion_statuswhen applicable) — in every status, including pending and expired. Previously the amount only appeared once credited, so pending rows showed no amount. Additionally, a charge settled in crypto or via the CBPay app now exposes itsusdt_creditedeven without anfx_rate. CSV/XLSX exports add thesettlement_assetandasset_amountcolumns.
v1.91
Added- Subscriptions (scheduled recurring charges) (payins guide): the platform runs the schedule for charges on a saved card.
POST /v1/subscriptions(intervaldaily/weekly/monthly/yearly, optionalstart_atfor a trial, requiredidempotency_key) charges the first period on creation and fires the rest automatically. Full resourceGET /v1/subscriptions(+/{id}, filters status/stored_card_id/payer_reference) and lifecyclePOST .../pause·/resume·/cancel. Dunning on declines (daily retry ×3 ⇒past_due), no catch-up on resume, and automatic cancellation when the card is revoked. Each successful charge credits like a card payin (payin_creditedwithsubscription_id). New webhooksubscription_status_changed.
v1.90
Added
- Saved cards and recurring charges (payins guide): the
cardmethod now supports stored credentials (the card brands’ COF mandate).POST /v1/payinsacceptssave_card(consent checkbox on the hosted page),payer_reference(your customer ID) andstored_card_id(pay with a saved card without re-typing the number; 3-D Secure still runs). New resourceGET /v1/stored-cards(+/{id},DELETEto revoke) and merchant-initiated charges without the payer present:POST /v1/stored-cards/{id}/charges(recurringfor subscriptions;idempotency_keyrequired — a retry never charges twice). The card number never exists on the platform: display data only (brand, last 4, expiry). New webhookscard_storedandstored_card_revoked; new error422 stored_card_revoked(errors).
v1.89 · 2 releases
v1.89
Added- Compliance controls on outgoing payments (payouts guide, errors): payouts, crypto withdrawals with a beneficiary name and collect charges now go through additional compliance controls before money moves. Documented errors:
403 compliance_hold(the operation was held and NOT created — no debit; by policy the exact reason is not disclosed, contact support with the timestamp) and503 compliance_check_unavailable(the check could not be evaluated; the operation was NOT created — retry with the sameidempotency_key).
v1.88
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.
v1.87 · 4 releases
v1.87
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.
v1.86
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.
v1.85
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).
v1.84
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.
v1.83 · 10 releases
v1.83
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).
v1.82
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.
v1.81
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.
v1.80
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.
v1.79
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.
v1.78
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.
v1.77
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.
v1.76
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).
v1.75
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.
v1.74
Addedaccount_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.
v1.73 · 5 releases
v1.73
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.
v1.72
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.
v1.71
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.
v1.70
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.
v1.69
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).
v1.68 · 7 releases
v1.68
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.
v1.67
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.
v1.66
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.
v1.65
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.
v1.64
ChangedPUT /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.
v1.63
FixedPOST /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.
v1.62
FixedPOST /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.
v1.61 · 6 releases
v1.61
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.
v1.60
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.
v1.59
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.
v1.58
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.
v1.57
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.
v1.56
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.
v1.55 · 9 releases
v1.55
Added — AML screening audit historyGET /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).
v1.54
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.
v1.53
Added — Banking series in the balance historyGET /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.
v1.52
Added — Country filter on payouts and payinsGET /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.
v1.51
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.
v1.50
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).
v1.49
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.
v1.48
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.
v1.47
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.
v1.46 · 7 releases
v1.46
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.
v1.45
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).
v1.44
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".
v1.43
Added — Historical series for your dashboardGET /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.
v1.42
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.
v1.41
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.
v1.40
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).
v1.39 · 7 releases
v1.39
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.
v1.38
Added — Account summary (analytics) + third-party banking usersGET /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).
v1.37
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.
v1.36
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.
v1.35
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.
v1.34
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.
v1.33
Fixed — Banks catalog withoutmethod 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).
v1.32 · 7 releases
v1.32
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).
v1.31
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.
v1.30
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.
v1.29
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).
v1.28
Changed — Short reference for announced bank transfersPOST /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.
v1.27
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.
v1.26
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.
v1.25 · 8 releases
v1.25
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).
v1.24
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.
v1.23
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.
v1.22
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.
v1.21
Addedpayin_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.
v1.20
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.
v1.19
AddedGET /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).
v1.18
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.
v1.17 · 16 releases
v1.17
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.
v1.16
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.
v1.15
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?“).
v1.14
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.
v1.13
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.
v1.12
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.
v1.11
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
v1.10
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.v1.9
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.
v1.8
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.
v1.7
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.
v1.6
ImprovedGET /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.
v1.5
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.
v1.4
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.
v1.3
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.
v1.2
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)“.
v1.1 · 2 releases
v1.1
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.
v1.0
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.