Skip to content
Last updated

v2.2.0 — September 2026

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.

Changed — Cash-Out contract

⚠️ Breaking for Cash-Out consumers. Review your status handling before this release reaches production.

  • status is now one of five values: PROCESSING, PENDING, COMPLETED, CANCELLED, REFUNDED — the same on GET /cash-out/{id}, GET /cash-out and every CASHOUT_* webhook. PAID became COMPLETED, and FAILED became CANCELLED. The rule: if the money never left, it is CANCELLED; if it left and came back, it is REFUNDED.
  • paidAt is now completedAt on the Cash-Out. failedAt no longer exists; a cancelled Cash-Out carries cancelledAt — spelled with two L, like the CANCELLED status, on Cash-Out and Cash-In, in GET by id, listings and webhooks.
  • failure only on CANCELLED, always with a code from a fixed catalog of 18 codes and a fixed English message per code. See the failure.code table.
  • reason on REFUNDED: PAYEE_REQUESTED, FRAUD, OPERATIONAL_ERROR, REVERSED_BY_INSTITUTION or OTHER.
  • CASHOUT_REQUESTED keeps its name and now carries status: "PROCESSING" (it was "REQUESTED"), the same status as POST /cash-out and GET /cash-out/{id} for a Cash-Out that was just accepted.
  • CASHOUT_FAILED keeps its name and now carries status: "CANCELLED", failure and cancelledAt. CASHOUT_REFUNDED carries status: "REFUNDED", reason and refundedAt.
  • GET /cash-out/summary buckets are the Cash-Out statuses in lowercase: processing, pending, completed, cancelled, refunded. paid became completed, and failed no longer exists (it is counted under cancelled). settlement counts completed only.
  • pixKeyType is always one of CPF, CNPJ, EMAIL, PHONE or EVP in responses and webhooks.
  • Processing is asynchronous. Balance and withdrawal limits are checked after 202 Accepted; an insufficient balance arrives as CASHOUT_FAILED with failure.code: "INSUFFICIENT_FUNDS", never as a 422 on POST /cash-out.

Changed — Cash-In

  • reason on REFUNDED (GET /cash-in/{id}, GET /cash-in and CASHIN_REFUNDED): FRAUD, DUPLICATED_PAYMENT, CUSTOMER_REQUEST, MERCHANT_ERROR, PAYER_NOT_ALLOWED or OTHER.
  • CANCELLED is documented on GET /cash-in/{id}, with cancelledAt.
  • settlement is now also in the data of CASHIN_PAID and CASHIN_REFUNDED: webhook data mirrors the GET body.
  • CASHIN_REQUESTED keeps its name and now carries status: "AWAITING_PAYMENT" (it was "REQUESTED"), the same status as POST /cash-in and GET /cash-in/{id} for an open Cash-In.
  • CASHIN_EXPIRED arrives 5 to 7 minutes after the expiration time. expiredAt is the charge's expiration date and time (the end of the payment window), the same value on GET /cash-in/{id}, GET /cash-in and CASHIN_EXPIRED; the envelope eventAt is the send time, not the expiration.
  • 409 DUPLICATED_EXTERNAL_REFERENCE on POST /cash-in, as on POST /cash-out.

Changed — Both

  • GET /cash-in/{id} and GET /cash-out/{id} accept your externalReference, besides internalCode, transactionId and the payment or refund endToEndId, with a fixed precedence when a value matches more than one transaction.
  • X-Idempotency-Key is optional (still recommended). Without it the request is processed normally, and externalReference still blocks duplicates. With it: Idempotent-Replayed: true on a replay within 24 hours, 422 IDEMPOTENCY_KEY_REUSED, 409 IDEMPOTENCY_KEY_IN_PROGRESS, 400 IDEMPOTENCY_KEY_INVALID. POST /cash-in/{id}/refund does 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 the DigitalSignature codes DIGITAL_SIGNATURE_REQUIRED, DIGITAL_SIGNATURE_INVALID (401) and CRYPTO_TOKEN_NOT_CONFIGURED (403). The authentication 401s have no code — see below.

Fixed — Documentation of authentication errors

  • The documentation listed INVALID_CREDENTIALS, TOKEN_EXPIRED and INVALID_APPLICATION_TOKEN. The API never returned those codes. It now describes what the API returns:
    • POST /auth/token with wrong credentials: 401 with { "message": "..." }, no code.
    • JWT missing, invalid or expired: 401 with no body and a WWW-Authenticate header (error_description="The token expired at '...'" when expired). Request a new token.
    • ApplicationToken missing or invalid: 401 Problem Details without code. See Authentication Errors.
  • externalReference accepts up to 50 characters (the documentation said 100).

v2.1.1 — September 2026

Changed

  • Available period on GET /account/{number}/statement. Statement data is available from a start date set for each client. A from earlier than that date returns 422 LIST_FROM_BEFORE_CUTOFF, and the detail states the first available date.

v2.1.0 — September 2026

New Endpoint

EndpointDescription
GET /account/{number}/statementBank 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.

Changed

  • limit now goes up to 1000 (was 200) on GET /cash-in, GET /cash-out and the new statement endpoint. The default is still 50.
  • New order parameter on the same three endpoints: asc or desc.
  • New previousCursor on all three list responses. Send it in the same cursor parameter 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 the order you asked for, and cost the same.

⚠️ order defaults to asc, which is the behaviour these endpoints always had. Existing integrations are unaffected — you only see a change if you ask for one.

⚠️ order cannot change mid-walk. The direction is baked into the cursor. Sending a different order alongside a cursor returns 422 LIST_ORDER_MISMATCH. Cursors issued before this release remain valid and are read as asc.

v2.0.0 — March 2026

Initial release of the ConnectPSP API V2.

New Endpoints

EndpointDescription
POST /auth/tokenJWT-based authentication
POST /cash-inCreate PIX Cash-In (QR Code or OpenFinance)
GET /cash-in/{id}Poll Cash-In status
POST /cash-in/{id}/refundRequest full devolution of a paid Cash-In
POST /cash-outSend PIX payment (by key or bank account)
GET /cash-out/{id}Poll Cash-Out status
GET /account/balanceGet consolidated wallet balances
POST /account/rebalanceRebalance transactional vs proprietary accounts

Key Features

  • Standardized error responses (RFC 7807 Problem Details) on all 4xx/5xx errors
  • Idempotency support via X-Idempotency-Key header on write operations
  • V2 Webhooks — events contain full transaction data matching GET endpoint responses
  • OpenFinance support on Cash-In via the openFinance object
  • Dual destination on Cash-Out: PIX key or direct bank account data