Already integrated with v2? Follow the Migration guide: v2.1 → v2.2: every breaking change as a before → after table, a checklist for your code and a side-by-side webhook example.
⚠️ Breaking for Cash-Out consumers. Review your status handling before this release reaches production.
statusis now one of five values:PROCESSING,PENDING,COMPLETED,CANCELLED,REFUNDED— the same onGET /cash-out/{id},GET /cash-outand everyCASHOUT_*webhook.PAIDbecameCOMPLETED, andFAILEDbecameCANCELLED. The rule: if the money never left, it isCANCELLED; if it left and came back, it isREFUNDED.paidAtis nowcompletedAton the Cash-Out.failedAtno longer exists; a cancelled Cash-Out carriescancelledAt— spelled with two L, like theCANCELLEDstatus, on Cash-Out and Cash-In, inGETby id, listings and webhooks.failureonly onCANCELLED, always with a code from a fixed catalog of 18 codes and a fixed English message per code. See thefailure.codetable.reasononREFUNDED:PAYEE_REQUESTED,FRAUD,OPERATIONAL_ERROR,REVERSED_BY_INSTITUTIONorOTHER.CASHOUT_REQUESTEDkeeps its name and now carriesstatus: "PROCESSING"(it was"REQUESTED"), the same status asPOST /cash-outandGET /cash-out/{id}for a Cash-Out that was just accepted.CASHOUT_FAILEDkeeps its name and now carriesstatus: "CANCELLED",failureandcancelledAt.CASHOUT_REFUNDEDcarriesstatus: "REFUNDED",reasonandrefundedAt.GET /cash-out/summarybuckets are the Cash-Out statuses in lowercase:processing,pending,completed,cancelled,refunded.paidbecamecompleted, andfailedno longer exists (it is counted undercancelled).settlementcountscompletedonly.pixKeyTypeis always one ofCPF,CNPJ,EMAIL,PHONEorEVPin responses and webhooks.- Processing is asynchronous. Balance and withdrawal limits are checked after
202 Accepted; an insufficient balance arrives asCASHOUT_FAILEDwithfailure.code: "INSUFFICIENT_FUNDS", never as a422onPOST /cash-out.
reasononREFUNDED(GET /cash-in/{id},GET /cash-inandCASHIN_REFUNDED):FRAUD,DUPLICATED_PAYMENT,CUSTOMER_REQUEST,MERCHANT_ERROR,PAYER_NOT_ALLOWEDorOTHER.CANCELLEDis documented onGET /cash-in/{id}, withcancelledAt.settlementis now also in thedataofCASHIN_PAIDandCASHIN_REFUNDED: webhookdatamirrors theGETbody.CASHIN_REQUESTEDkeeps its name and now carriesstatus: "AWAITING_PAYMENT"(it was"REQUESTED"), the same status asPOST /cash-inandGET /cash-in/{id}for an open Cash-In.CASHIN_EXPIREDarrives 5 to 7 minutes after the expiration time.expiredAtis the charge's expiration date and time (the end of the payment window), the same value onGET /cash-in/{id},GET /cash-inandCASHIN_EXPIRED; the envelopeeventAtis the send time, not the expiration.409 DUPLICATED_EXTERNAL_REFERENCEonPOST /cash-in, as onPOST /cash-out.
GET /cash-in/{id}andGET /cash-out/{id}accept yourexternalReference, besidesinternalCode,transactionIdand the payment or refundendToEndId, with a fixed precedence when a value matches more than one transaction.X-Idempotency-Keyis optional (still recommended). Without it the request is processed normally, andexternalReferencestill blocks duplicates. With it:Idempotent-Replayed: trueon a replay within 24 hours,422 IDEMPOTENCY_KEY_REUSED,409 IDEMPOTENCY_KEY_IN_PROGRESS,400 IDEMPOTENCY_KEY_INVALID.POST /cash-in/{id}/refunddoes not take it.- Errors carry a
code:VALIDATION_ERROR(400),CASHIN_NOT_FOUND/CASHOUT_NOT_FOUND(404),REFUND_NOT_ALLOWED/MISSING_E2E(422 on refunds),INTERNAL_ERROR(500), and theDigitalSignaturecodesDIGITAL_SIGNATURE_REQUIRED,DIGITAL_SIGNATURE_INVALID(401) andCRYPTO_TOKEN_NOT_CONFIGURED(403). The authentication401s have nocode— see below.
- The documentation listed
INVALID_CREDENTIALS,TOKEN_EXPIREDandINVALID_APPLICATION_TOKEN. The API never returned those codes. It now describes what the API returns:POST /auth/tokenwith wrong credentials:401with{ "message": "..." }, nocode.- JWT missing, invalid or expired:
401with no body and aWWW-Authenticateheader (error_description="The token expired at '...'"when expired). Request a new token. ApplicationTokenmissing or invalid:401Problem Details withoutcode. See Authentication Errors.
externalReferenceaccepts up to 50 characters (the documentation said 100).
- Available period on
GET /account/{number}/statement. Statement data is available from a start date set for each client. Afromearlier than that date returns422 LIST_FROM_BEFORE_CUTOFF, and thedetailstates the first available date.
| Endpoint | Description |
|---|---|
GET /account/{number}/statement | Bank statement of one of your accounts, for a period, with cursor pagination |
The statement is the raw banking ledger: every credit and debit that hit the account at the settlement partner, including entries that did not come from a Cash-In or Cash-Out you created. Entry types are normalized across partners (PIX_IN, PIX_OUT, TRANSFER_IN, …) with the partner's own label preserved in typeRaw.
The account must belong to the client behind your credentials. An account owned by someone else returns the same 404 as an account that does not exist.
limitnow goes up to1000(was200) onGET /cash-in,GET /cash-outand the new statement endpoint. The default is still50.- New
orderparameter on the same three endpoints:ascordesc. - New
previousCursoron all three list responses. Send it in the samecursorparameter to walk backwards. It is absent on the first page, so its absence tells you that you are at the start. Both directions return the page in theorderyou asked for, and cost the same.
⚠️
orderdefaults toasc, which is the behaviour these endpoints always had. Existing integrations are unaffected — you only see a change if you ask for one.
⚠️
ordercannot change mid-walk. The direction is baked into the cursor. Sending a differentorderalongside acursorreturns422 LIST_ORDER_MISMATCH. Cursors issued before this release remain valid and are read asasc.
Initial release of the ConnectPSP API V2.
| Endpoint | Description |
|---|---|
POST /auth/token | JWT-based authentication |
POST /cash-in | Create PIX Cash-In (QR Code or OpenFinance) |
GET /cash-in/{id} | Poll Cash-In status |
POST /cash-in/{id}/refund | Request full devolution of a paid Cash-In |
POST /cash-out | Send PIX payment (by key or bank account) |
GET /cash-out/{id} | Poll Cash-Out status |
GET /account/balance | Get consolidated wallet balances |
POST /account/rebalance | Rebalance transactional vs proprietary accounts |
- Standardized error responses (RFC 7807 Problem Details) on all 4xx/5xx errors
- Idempotency support via
X-Idempotency-Keyheader on write operations - V2 Webhooks — events contain full transaction data matching GET endpoint responses
- OpenFinance support on Cash-In via the
openFinanceobject - Dual destination on Cash-Out: PIX key or direct bank account data