Changelog
Notable changes to the External API and to these docs. Most recent first. Subscribe to webhooks and watch this page to stay ahead of deprecations.
Versioning policy
The API is versioned in the path (/v1). Breaking changes ship under a new version — the current version keeps working. Deprecations are announced here and remain supported throughout a transition window before removal.
Within a version, changes are additive: we may introduce new fields and new enum values without a version bump. Build consumers to tolerate that.
To stay forward-compatible: branch your logic on the stable error type — never on message text — ignore unknown fields rather than rejecting them, and treat any unrecognised enum value as a safe default instead of failing.
Releases
A Brazilian real deposit method can now be a Pix collection account — depositType: "PIX" no action needed 2026-09-10
The account-level receive details of a Brazilian real (BRL) deposit method may now come back as depositType: "PIX". No other currency returns this shape.
- What changes — a Brazilian real (
BRL) deposit method can now returndepositType: "PIX"with two fields:qrCodeString, the copy-and-paste code the payer pastes into their bank app, andbase64QRCode, the same code rendered as a PNG. - Brazilian real deposit methods can now be created on demand —
POST /v1/deposits/methodswithmethodType: "fiat"acceptscurrency: "BRL", alongsideEUR,USD,GBP,MXNandARS. It previously answered a validation error namingcurrency. base64QRCodeis raw base64, with no data-URI prefix — prependdata:image/png;base64,yourself before using it as an image source.- It carries no
amountand noreferenceCode— the payer enters the amount in their bank app, and the code carries a reference dedicated to this collection account, so there is no separate reference field to show. Do not require either field on this variant. - Pass
qrCodeStringthrough unchanged — the code carries its own checksum over its exact characters, so re-encoding it, trimming it or inserting line breaks makes the payer’s bank app reject it as corrupt. Show it as copyable text and render the image frombase64QRCode. - What does not change — every other
depositTypeon the account view behaves exactly as before, and a deposit method whose details are not payable yet still reads asPENDING. - What to do — nothing, unless you switch exhaustively on
depositTypeand reject unknown values; then add aPIXarm, or fall through to a default instead of failing.
Brazilian real collections have a rail value of their own — PIX no action needed 2026-09-10
A Brazilian real (BRL) collection can now be quoted and reported on the rail PIX, alongside the PIX_BR spelling that already existed. Both are accepted; neither replaces the other.
- Where the new value appears —
originRailonPOST /v1/quotes, andrailon the deposit object returned with a deposit or an order. - What the two values mean —
PIXnames the instrument the collection is actually provisioned as, the copy-and-paste code and QR the payer pays (depositType: "PIX").PIX_BRnames the payment scheme. ABRLquote carrying either value is accepted, and quotes you already send keep working unchanged. - Discover the rails, do not hardcode them —
GET /v1/currencies/BRL/payin-schemalists every accepted spelling underacceptedOriginRailsand the canonical one to send underpayinMethods. Read it instead of pinning a literal, so a corridor that gains a rail does not turn into a validation error on your side. - The Brazilian Pix method now reports its own channel type —
payinMethods[].typeon that same endpoint readspixfor the Pix method, where it previously readbank. Label it as Pix: the payer pastes a code into their bank app and is never given an account number to transfer to. The Brazilian bank-transfer method still readsbank. - Treat rail values as an open set — corridors gain rails without a version bump. If you switch exhaustively on a rail and reject unknown values, add a
PIXarm, or fall through to a default instead of failing. - What to do — map
PIXto the Pix copy-and-paste instruction (depositType: "PIX", carryingqrCodeStringandbase64QRCode) exactly as you would forPIX_BR. Nothing else about the Brazilian corridor changes.
A pending payin instruction can now say that waiting will never produce details — pendingReason: "accountless_per_account_corridor" action required 2026-09-10
pendingReason on a depositType: "PENDING" payin instruction has a second value.
- New value —
accountless_per_account_corridor. It means this corridor collects only into a collection account dedicated to the paying account, the request named no account, and none can be created for it. - Waiting does not resolve it — unlike
collection_account_activating, payable details will never follow for this instruction and no activation webhook will arrive for it. Polling it is an endless loop. - What to do — create the deposit against an account and read the instruction from that response. Treat this value as terminal for the instruction you are holding, and surface it rather than showing the payer a spinner.
A Colombian peso deposit method can now return a payment page instead of bank coordinates action required 2026-09-10
On POST /v1/deposits/methods, GET /v1/deposits/methods and GET /v1/deposits/methods/{methodId}, the depositInfo of a COP method may now arrive as depositType: "PSE" carrying a single url, where it previously always carried bank coordinates.
- Handle
PSEondepositInfo— the object is{ "depositType": "PSE", "url": "..." }and nothing else: no account number, no bank name, no reference. Present theurlas a link the payer opens; there is nothing on it to copy into a bank transfer. - Existing methods are unaffected — a
COPmethod that returns bank coordinates today keeps returning them, with every field intact. The payment-page shape appears only on methods whose collection account is set up for it. - New optional field —
amountPrefilledon aPSEinstruction. Whentruethe page already carries the amount and the payer cannot change it; whenfalseor absent, the payer enters the amount themselves and you must tell them what to pay. - Read the type, not the currency — branch on
depositInfo.depositTyperather than assuming a shape fromcurrency. A currency can serve more than one instruction type, and which one you get can change without a version bump.
US dollar bank payouts — say whether the account is checking or savings no action needed 2026-09-10
An ACH_US destination now takes an optional bankAccountType, which says what kind of bank account receives the money. The US banking network carries it on the payout, and until now we could not tell it apart, so every US payout was sent as a checking account.
- Optional, and it defaults — omit
bankAccountTypeand the payout is sent asCHECKING, which is what happened before this field existed. Nothing you already send needs to change. - Accepted values —
CHECKINGorSAVINGS, in capitals. Any other value is rejected with a validation error rather than quietly treated as a checking account. - Not the same field as
accountType—accountType(PERSONAL/BUSINESS) says whether the recipient is a person or a business.bankAccountTypesays what kind of bank account the money lands in. Both can be sent on the same destination. - Confirm the field list at runtime —
GET /v1/currencies/USD/destination-schema?method=achUSreturns every field, whether it is required, and its accepted values.
US dollar bank payouts — state is now required action required 2026-09-09
An ACH_US destination now requires state, the two-letter code of the recipient’s US state. It was previously not part of the destination; a request that omits it, or sends anything other than a two-letter code, is rejected with a validation error.
- Now required —
state, on everyACH_USdestination you create. This rail also needscityandpostalCode. Each of those two is accepted on the destination, or on the recipient’s details — thedestinationUserDatayou send when the recipient is new, or the details we already hold for one you have used before. - Accepted values — exactly two uppercase letters, for example
NYorCA. A state name such asNew York, or an empty string, is not accepted. - What to do — add
statewherever you build anACH_USdestination, for example onPOST /v1/ordersandPOST /v1/withdrawals. US destinations you already stored keep working on read; an order to a stored recipient whose state we do not hold is rejected when you create it onPOST /v1/orders. For a recipient you have used before, sendingstateindestinationUserDatadoes not lift that — update the destination, or the recipient’s details, with the state. - That rejection is now a
400— an order to a stored recipient whose state we do not hold returnsinvalidParameters(id1008) with HTTP400, naming the field. It previously returnederrorCreatingOrder(id1021) with HTTP500. If you retry on5xx, stop retrying this case and supply the state instead. - Confirm the field list at runtime —
GET /v1/currencies/USD/destination-schema?method=achUSreturns the required fields and their formats. Read it instead of hardcoding this list, and it will stay correct through later changes.
Colombian peso payouts — BANK_DEPOSIT_COL now needs the bank code and the recipient’s ID action required 2026-09-08
A BANK_DEPOSIT_COL destination previously took a recipient name, a payout network id and an account number. The Colombian payout rail needs six fields, so that shape was accepted at creation and then refused at payout. Creating or updating one now requires all six, and each missing field is named in the validation error.
- Now required —
destinationBankCode(four digits, and one of the codes on the supported bank list, e.g.1007Bancolombia),destinationBankAccountType(CORRIENTEorAHORRO),destinationDocumentType(CC,CE,NIT,TIorPP) anddestinationTaxId, alongsidedestinationNameanddestinationBankAccount. - No longer required —
destinationNetworkId. It is now optional and is not used to route the payout. If you were sourcing it fromGET /v1/currencies/COP/networksjust to satisfy the schema, you can stop. - A bank code that is not on the list is refused at creation — a three-digit code, or a bank name where the code belongs, returns a
400naming the field. Previously such a value was accepted, the funds were collected, and only then did the payout fail. - Destinations you already stored keep working on read — an existing Colombian recipient still reads, still lists and still appears on past orders, with every field intact, and you can still rename it. Supply the four fields when you next create or update one; until then it cannot fund a new payout.
BANK_DEPOSIT_COLandACH_COPare equivalent — same payout rail, same six fields, same bank list. They differ only in the key that carries the account number (destinationBankAccounthere,destinationBankAccountNumberonACH_COP). UseACH_COPfor new integrations: the nameBANK_DEPOSIT_COLis also used for a Colombian collection rail, so the same string means two different things depending on where it appears.- Confirm the field list at runtime —
GET /v1/currencies/COP/destination-schema?method=bankDepositCOLreturns the required fields, their formats and the accepted bank codes. Read it instead of hardcoding this list, and it will stay correct through later changes.
A pending payin instruction can now tell you why it is pending no action needed 2026-09-03
A payin instruction with depositType: "PENDING" may now carry an optional pendingReason. It is additive: nothing that exists today changes shape, and the field is simply absent when we cannot classify the reason.
- New optional field —
pendingReasonon aPENDINGpayin instruction. Today the one value iscollection_account_activating, which means the collection account for this payer is being opened and payable details are expected shortly. - A missing value never tells you the wait is short or long — absence means only that no reason is classifiable. Do not infer timing from a missing field.
- It also appears on webhooks — the field rides the deposit instruction wherever it is returned, including webhook payloads. If you validate webhook bodies with a strict parser of your own, allow the new key.
- Only on the transaction-level instruction — an account-level deposit method never carries this field at all, whatever its status.
- Expect more values over time — treat
pendingReasonas an open set and ignore values you do not recognise rather than failing on them.
Peruvian sol bank payouts — destinationCCI is now required action required 2026-09-02
A BANK_DEPOSIT_PEN destination now requires destinationCCI. It was previously optional; a request that omits it, or sends it empty, is rejected with a validation error.
- Now required —
destinationCCI, alongside the fields you already send. Send it for every recipient, whichever bank they use. - Accepted values — digits only, 1 to 20 characters. An empty string is no longer accepted.
- What to do — add
destinationCCIwherever you build aBANK_DEPOSIT_PENdestination, for example onPOST /v1/ordersandPOST /v1/withdrawals. Peruvian destinations you already stored keep working on read; supply the CCI when you next create or update one. - Confirm the field list at runtime —
GET /v1/currencies/PEN/destination-schema?method=bankDepositPENreturns the required fields, their formats and their accepted values. Read it instead of hardcoding this list, and it will stay correct through later changes.
Colombian ACH payouts — the bank code is checked against the bank list action required 2026-09-01
On an ACH_COP destination, destinationBankCode must be one of the four-digit codes the Colombian ACH rail publishes. Any other value is now rejected with a validation error naming the field; previously any non-empty string was accepted.
- What changes — the code must be exactly four digits and a bank on the supported list (e.g.
1007Bancolombia,1001Banco de Bogotá). A three-digit code such as001, or a bank name where the code belongs, is refused. - Why — those values were accepted at creation and then refused by the payout rail, after the funds had been collected, leaving the payment in manual review. The check now happens at the boundary, so you get a
400instead of a stuck payment. - What does not change — Colombian
BRE_B_COPpayouts carry no bank code and are untouched, as are all other rails. AnACH_COPdestination you created before this date still reads, lists and appears on orders exactly as before, bank code included, even if its code is not on the list — only creating or updating one is held to the new rule. - What to do — send the four-digit code, not the bank name.
GET /v1/currencies/COP/destination-schema?method=achCOPreturns the accepted codes with their bank names; read it instead of hardcoding the list. If one of your stored destinations carries a code that is no longer accepted, replace it before your next payout — the rail would refuse it.
A rail that is not a collection method for the currency now returns 1008 instead of 1002 action required 2026-09-01
When you send a supported currency together with a rail that the currency is not collected on, the rejection now identifies the real problem — the currency/rail pairing — instead of reporting the currency as unsupported. Affects POST /v1/deposits and POST /v1/orders. The status stays 400.
- What changes — the response for this case carries
error: "ValidationError",errorId: 1008,errorName: "invalidParameters". It previously carriederrorId: 1002,errorName: "notSupportedCurrency"and a message listing currencies that were unrelated to your request. The new message names the currency and the rail you sent, and the collection methods the corridor does accept. - What does not change — the request is still rejected, and it was correctly rejected before: these pairings are not available. Nothing new is accepted. A currency that genuinely has no enabled corridor still returns
errorId: 1002/notSupportedCurrency, unchanged — the two rejections are now distinguishable, which they were not before. - What to do — if you branch on
errorId: 1002to mean “this currency is unsupported”, that branch will no longer be entered for a currency/rail mismatch; handle1008for it, and treat it as a request to fix rather than a currency to drop. CallGET /v1/currenciesand readpayinMethodsto discover the rails each currency is collected on.
Deposits take originNetworkId to choose the mobile-money collection network action required 2026-09-01
POST /v1/deposits accepts a new optional originNetworkId, and a mobile-money collection that needs the payer's network now answers 400.
- What changes — you may send
originNetworkId, one of theidvalues fromGET /v1/currencies/{currency}/networks?rail={rail}&rampType=deposit, passing the same rail you send on the deposit. An id that corridor does not publish is rejected with400, and so is anoriginNetworkIdsent on a rail that is not mobile money. - What changes — where a mobile-money collection offers more than one network and you send no
originNetworkId, the response is400naming the field. It used to be500: do not retry it, resend with a network. - What does not change — the field is optional. Omit it and every request you send today is accepted unchanged; a collection with one network still resolves it for you.
- What to do — nothing, unless you collect by mobile money; then read the networks for the currency and send the payer's choice as
originNetworkId.
Argentine peso (ARS) is now a supported fiat currency for POST /v1/deposits/methods no action needed 2026-08-31
- What changes —
POST /v1/deposits/methodswithmethodType: "fiat"now acceptscurrency: "ARS". - What does not change — every other supported fiat currency, and every existing request, behaves exactly as before.
- What to do — nothing, unless you want to provision a dedicated ARS receiving account on demand; then send
currency: "ARS"withmethodType: "fiat".
Argentine peso bank payouts — the recipient tax ID is now required action required 2026-08-29
A BANK_DEPOSIT_AR destination must carry destinationTaxId: the recipient's CUIT/CUIL. It was optional; a request that creates an AR destination without it is now rejected with a validation error naming the field.
- Now required —
destinationTaxId, format^\d{2}-?\d{8}-?\d$(e.g.20-30405060-7), alongsidedestinationName,destinationNetworkIdanddestinationBankAccount. - Where — wherever you send a
BANK_DEPOSIT_ARdestinationTransferDatainline:POST /v1/ordersandPOST /v1/withdrawals. Destinations saved through the app are held to the same rule. - Why — the payout is registered against the recipient's own tax ID. Previously an AR destination without one could be registered under the payer's tax ID; that fallback is gone, and an empty value is now refused at capture instead of failing later at payout.
- What does not change — AR destinations you created before this date keep reading, listing and appearing on orders unchanged. Editing one requires adding the CUIT/CUIL; paying out from one without it is refused by the rail and routed to manual review, never re-attributed.
- Confirm the field list at runtime —
GET /v1/currencies/ARS/destination-schemareturns the required fields and their formats. Read it instead of hardcoding this list.
Withdrawals can declare a third-party destination with beneficiary no action needed 2026-08-28
POST /v1/withdrawals accepts a new optional beneficiary object for payouts to a wallet that is not the account holder's own.
- What changes — you may send
beneficiarywithname,surnameandrelationship: "third_party". When present, bothnameandsurnameare required. - What does not change — omit
beneficiaryand the withdrawal behaves exactly as before. Every existing request is accepted unchanged. - What to do — nothing, unless you pay out to a third party's wallet; then send
beneficiarywith the recipient's real name and surname.
The withdrawal approval endpoint has been removed action required 2026-08-28
POST /v1/withdrawals/approve no longer exists.
- What changes —
POST /v1/withdrawals/approvenow returns404. Withdrawals created through the API were never held for this approval step. - What to do — if you call this endpoint, remove that call. A created withdrawal proceeds without it.
KYC profile: pep is replaced by pepDeclaration, and profession is a sector code action required 2026-08-20
Two fields on POST /v1/kyc/data change. Requests keep succeeding either way — no new error is returned — but a value we no longer recognise is not recorded.
- What changes —
pep(boolean) is removed. SendpepDeclarationinstead, with one ofno,yes,family(immediate family member of a politically exposed person) orrelated(known close associate of one). Omit the field when the holder has not answered; never sendnoto mean unanswered. - What changes —
professionis now an activity sector code, a short numeric code such as24. Free text such as"Nurse"is still accepted by the request but is not recorded: it counts as not declared, and the holder is asked to choose a sector while completing verification. - What to do — if you send
pep, switch topepDeclaration:pepis now ignored, so a declaration sent under the old key is not stored. If you send a free-textprofession, either send a sector code or omit the field. Both fields stay optional, andmissingFieldsin the response tells you what is still outstanding.
Orders now return externalReference under the name you send it no action needed 2026-08-18
You set externalReference when creating an order. Until now the order read back carried that value under a misspelled key, externalRefeference, with a doubled e.
- What changes —
GET /v1/ordersandGET /v1/orders/{orderId}now returnexternalReferencewith the value you supplied. Reconciling on the key you wrote with works. - What does not change — on
GET /v1/orders,externalRefeferenceis still returned with the same value. It is now marked deprecated in the spec and will be removed in a future major version. - Also —
POST /v1/ordersnow echoesexternalReferenceon the create response, so you can confirm what you sent without a second call. The correct spelling is returned onGET /v1/orders,GET /v1/orders/{orderId},POST /v1/ordersandPOST /v1/pending-payments/{transferId}/create-order; the deprecated key was never present on the create or single-order responses and is not being added there. - What to do — nothing today. When convenient, switch your reads to
externalReference; if you branch on the presence ofexternalRefeference, note that both keys are present. - What changes — when the lookup behind either endpoint is temporarily unavailable, you get
503witherror: "ExternalServiceError". Previously both returned200— an emptynetworksarray, orlimits: null. - What does not change — a successful response is identical. An empty array still means the corridor genuinely has no matching networks, and
limits: nullstill means no bounds are published for it. - What to do — handle
503on both endpoints by retrying. If you cache either result, only cache a200: an empty list is settled, a503is unknown.
Corridor discovery returns 503 when a lookup is unavailable action required 2026-08-18
GET /v1/currencies/{currency}/networks and GET /v1/currencies/{currency}/limits now tell an empty answer apart from an answer they could not obtain.
Collections in ARS, COP, CLP, BOB and TWD are no longer available action required 2026-08-07
These five currencies can no longer be used as the origin of a quote or an order — you cannot collect funds in them. Paying out to all five is unchanged and continues to work.
- What changes —
POST /v1/quotesandPOST /v1/ordersrejectoriginCurrencyofARS,COP,CLP,BOBorTWDwith a validation error naming the currency. - What does not change —
destinationCurrencystill accepts all five. Payouts, destination schemas and existing payout methods are untouched. - What to do — stop offering these five as collection currencies. Orders already created are unaffected.
- Check availability at runtime —
GET /v1/currenciesreturns what each currency can do today. Read it instead of hardcoding a list, and it will stay correct through later changes.
Chilean peso bank payouts — three fields are now required action required 2026-08-07
A BANK_DEPOSIT_CL destination now takes five fields. Three of them were previously optional and are enforced today — a request that omits any of them is rejected with a validation error.
- Now required —
destinationBankName,destinationBankAccountTypeanddestinationTaxId, alongside thedestinationNameanddestinationBankAccountyou already send. - Accepted values —
destinationBankAccountTypeisCORRIENTEorAHORRO.destinationTaxIdis the recipient's RUT. - What to do — add the three fields wherever you build a
BANK_DEPOSIT_CLdestination, for example onPOST /v1/ordersandPOST /v1/withdrawals. - Confirm the field list at runtime —
GET /v1/currencies/CLP/destination-schemareturns the required fields, their formats and their accepted values. Read it instead of hardcoding this list, and it will stay correct through later changes.
Unreleased 2026-08-13
- New: fetch a single conversation —
GET /v1/conversations/{conversationId}?endUserEmail=returns one conversation. Previously you had to list an end-user's conversations and pick it out.endUserEmailis required: a conversation is addressed by end-user and id. Additive — nothing you send today changes. - Unrecognised query parameters are now rejected on the list endpoints —
/v1/deposits,/v1/orders,/v1/withdrawals,/v1/pending-paymentsand their/countvariants. A misspelled filter such as?limitt=5previously returned200with the parameter ignored; it now returns400. If you send any parameter not listed for the endpoint, remove it. cityandpostalCodeare required when paying out toSEPA,ACH_USorGBP_BANK_TRANSFER. Send them in eitherdestinationTransferDataordestinationUserData— either location satisfies the requirement. Requests missing both are now rejected at submission with a400naming the field, instead of failing later during payout.- Clearer payout errors. A missing recipient address now returns a message naming the field and where to put it, rather than a generic "user data is not valid".
- New:
refundStatuson pending payments.GET /v1/pending-paymentsandGET /v1/pending-payments/{transferId}may now returnrefundStatus— one ofpending_approval,returning,returned,failed. The field is absent when no refund is in progress. Onlyreturnedmeans the payer has the money back: do not readreturningas complete. While the field is present the payment cannot be linked to an order or a deposit, so stop offering it for linking. Additive — nothing you send today changes.
v1.0.0 current 2026-07-06
Initial public API (quotes, orders, deposits, withdrawals, webhooks) on stable JSON contracts — and the launch of this documentation site.
| Area | Change |
|---|---|
quotes | Lock an exchange rate and fees for a currency pair. |
orders | Commit a quote to a payout destination and track it to completion. |
deposits | Collect funds locally into a workspace balance. |
withdrawals | Pay out locally from a workspace balance. |
KYC | Onboard and verify entities before they transact. |
webhooks | Signed event notifications for state changes. |
discovery | Per-currency capability discovery via /v1/currencies/*. |
banking accounts | Manage the banking accounts behind deposits and withdrawals. |
docs | Modern API documentation launched — this site. |
Deprecated — the generic LOCALBANK deposit type is deprecated in favour of corridor-specific types (e.g. SEPA, PIX, and country-specific bank types). Discover the exact type per currency with GET /v1/currencies/{currency}/payin-schema. It is still returned on historical records for backward compatibility.
Upcoming
A cleaner, more consistent contract is planned: prefixed resource ids, a unified error envelope, 429 rate limiting with Retry-After, and standardized timestamps. It will ship under the versioning policy above — existing /v1 contracts keep working, and every change lands on this page first.