What Caratuva does on this surface
- Accepts a payment intent from your server.
- Returns a hosted payment URL you forward to your buyer.
- Onboards the buyer through KYC (mandatory — no skip path).
- Collects payment from the buyer, runs cross-border transfer + FX, and pays out BRL via PIX to the seller’s registered destination.
- Notifies your ERP through signed outbound webhooks at every state change.
Step 1 — Issue an API key
Log in to the dashboard and create apk_test_ key for development, plus a pk_live_ key for production. Store both in your secret manager. The plaintext secret is surfaced exactly once at creation time.
See API keys for the full CRUD surface.
Step 2 — Register a webhook subscription
Before you create your first intent, subscribe to thepayment_intent.* events you care about. The signing secret is also returned exactly once.
Step 3 — Create a payment intent
Each intent is a request to collect a specific amount from a specific buyer.externalId is your primary key — re-POSTing the same value is safe.
Step 4 — Forward the payment link
Email, SMS, or render thehostedPaymentUrl in your own UI — whichever channel you already use to engage your buyer. Caratuva does not auto-email the buyer on the payment-intent surface, because you own the customer relationship.
The hosted page handles email magic-link sign-in, KYC, FX quoting, and payment collection. Your buyer never leaves pay.caratuva.com until the redirect to returnUrl after settlement.
Step 5 — Reconcile through webhooks
Every state change fires apayment_intent.* event. The two events that matter for most ERPs:
payment_intent.settled— funds are in the seller’s BRL account. Mark the order paid in your system. The payload carriespaymentIntentId,externalId, and the originalmetadata(plussourceandexternalEventId). For settlement amounts (amount,currency,brlSettledAmount,fxRateAtSettlement), fetchGET /v1/payment-intents/{id}on receipt — they are not on the webhook body.payment_intent.failed— terminal failure. The payload carries the reason. Refund the order or surface an error to your buyer.
X-Caratuva-Delivery-Id as an idempotency key — Caratuva retries up to seven times with exponential backoff (immediate, 30s, 2m, 10m, 1h, 6h, 24h) and your endpoint will see the same delivery id on every attempt.
Test mode
pk_test_ keys run the entire flow end-to-end against a sandbox payment instance. The same intent transitions, the same webhooks, the same response shapes — but KYB and buyer KYC auto-approve and no real money moves. Use it for CI and staging. See Environments.
Common pitfalls
- Missing buyer email. It’s required and must be a real address — that’s where the magic-link goes.
- Sending floats. Pass
amountas a string ("12500.00") to avoid float drift. - Re-serializing the webhook body before verifying. The signature is computed over the raw bytes. Always verify against
req.rawBody, notJSON.stringify(req.body). - Reusing
Idempotency-Keyacross distinct logical operations. It’s scoped per organization and collapses retries; don’t share it across unrelated intents.
Where to next
- Payment intents — full schema, error codes, state machine.
- Webhooks — signature verification, retry policy,
payment_intent.*event reference. - API keys — issuance, rotation, revocation.