- Your server only says which WhatsApp number is writing (
waId). Kravata finds the user with that phone in your company and sends an OTP to the user’s own phone (SMS) and email. Only the code the user types back opens a session. - The PIN never goes through your server. The user types it in a WhatsApp Flow whose data endpoint is Kravata.
- With the user’s token, your server calls the same endpoints as the Kravata widget, so the same rules apply: your company’s OTP and PIN settings, KYC, tiers and limits.
In production, the channel token and session calls go through the partners domain and need the same client certificate as the rest of your partner API: see Production access. The calls made with the user token (PIN, deposit, accounts, withdrawal) go to
api-kore, like the Kravata widget. The examples below use the test domain.
The channel is enabled per company. Ask your Kravata point of contact to enable it and to issue your channel credential.
Credentials and tokens
You work with two kinds of token:1. Open a session for the user
1
Request the OTP
When a number writes to you and you have no valid session for it, call Tell the user that a code was sent by SMS and email. Kravata never sends this code through WhatsApp.
POST /api/v1/channel/whatsapp/session/request with your channel token. waId is the number as WhatsApp sends it (country code, no +).2
Verify the code the user types
waId. A new session for a number ends the previous one.3
Keep the session alive
Before the access token expires, call
POST /api/v1/channel/whatsapp/session/refresh with {"waId", "refreshToken"}. A session can be refreshed for at most 7 days after it was opened; after that, repeat step 1.4
End the session
When the user leaves (for example, writes “salir”), call
POST /api/v1/channel/whatsapp/session/revoke with {"waId"}. It ends every channel session of that number.{"error": {"code": "...", "message": "..."}}:
2. Registration of new users
3. Terms and conditions
Users accept Kravata’s terms and data policy on Kravata’s terms page. Your integration gets the link withPOST /api/v1/client/terms-acceptance/generate-link ({"clientId", "userId"}, with your partner API token) and sends it to the user.
4. PIN setup
The PIN is created and recovered only in the Kravata widget, never in the chat. With the user token you can check whether the user already has one:pinSet is false, send the user to the widget to create it.
5. Deposit
1
Get the user's wallet
GET /api/v1/custodian/kravata-wallets returns the user’s wallets (items). Use items[0].walletId as accountId in the deposit; its balances show the user’s balance.2
(PSE) Get the banks
GET /api/v1/banks/get-banks-cashin returns [{"id", "name", "achcode", "status", ...}].3
Create the deposit
bankCode is the bank’s achcode. With executionMode: "NORMAL", amount is the COP amount the user pays; with "INVERSE", it is the amount of the wallet’s token the user wants to receive.The response is {"operation": {...}, "tierEscalation": null, ...}. For PSE, send the user operation.depositInstructions.pseLink. If tierEscalation is present and operation is null, the user must complete a tier upgrade first (tierEscalation.actionType / actionPayload).6. Register a bank account
1
Get the banks
GET /api/v1/banks/get-banks returns [{"id", "code", "name", "status"}].2
Confirm with the PIN (if your company requires it)
See PIN confirmation with
purpose: "account_creation".3
Create the account
Use the same user token within 120 seconds of the PIN confirmation.
type is SAVING or CHECKING. For a third party’s account use accountOwnerType: "PERSON" with holderIdentificationType, holderIdentificationNro, holderFirstName and holderFirstSurname (or "COMPANY" with holderBusinessName). For a Bre-B key: {"name", "type": "SAVING", "number": "<key>", "currency": "COP", "paymentMethod": "BREB"}.GET /api/v1/accounts lists the user’s accounts (items). Editing an account (PATCH /api/v1/accounts/{id}) also asks for the PIN, with purpose: "account_update".7. Withdrawal
1
Choose the destination account
GET /api/v1/accounts → the id of the account.2
Confirm with the PIN (if your company requires it)
See PIN confirmation with
purpose: "withdrawal". Each withdrawal needs its own confirmation.3
Create the withdrawal
executionMode: "NORMAL", amount is the amount of the wallet’s token (for example USDC) the user sells; with "INVERSE", it is the COP amount the user wants to receive. Use paymentMethod: "BREB" for a Bre-B account.The response has the same shape as the deposit; operation.prefix + operation.numberCode identify the withdrawal for the user.Operation OTP in the channel
If your company requires an OTP for deposits or withdrawals, the OTP the user typed to open the channel session covers it while the user is active: their last OTP or PIN in that session must be at most 30 minutes old. Your server’s own calls (refresh, reads) don’t count as activity. After 30 minutes without activity, deposits and withdrawals are rejected with403: open a new session (section 1) and retry.
PIN confirmation
When your company requires the PIN for an operation, the user confirms it in a WhatsApp Flow whose data endpoint is Kravata. Your server never receives the PIN.1
Create the PIN challenge
With the user token, call If the user has no PIN, the answer is
POST /api/v1/pin/challenge. summary is the text the user sees in the Flow (up to 160 characters). purpose is withdrawal, account_creation or account_update.404: send them to the widget to create it.2
Send the WhatsApp Flow
Send your PIN Flow with
flow_token = flowToken. Its data endpoint is POST /api/v1/channel/whatsapp/flows/pin/{clientId} (your clientId), on https://api-kore.kravata.co in production: Meta calls it, so it doesn’t use mTLS.3
Wait for the Flow to finish
When the PIN is right, the Flow ends with
pin_validated: true. Then send the operation with the same user token within 120 seconds. A confirmation authorizes one operation only.- One screen with id
PIN. Kravata sends itdata.summaryand, after a wrong PIN,data.error_message(for example “PIN incorrecto. Te quedan 4 intento(s).”). - A
pinfield submitted withdata_exchange. - Completion on
SUCCESSwithparams:flow_token,pin_validatedandpurpose.
432 to a bad signature, 421 when it can’t decrypt (Meta then re-fetches the public key) and 427 when the flow_token is unknown, used or expired.
When an operation is rejected
Deposits, withdrawals and account changes rejected by the gateway answer403 without a reason. Check, in this order:
- The PIN confirmation was done with this same user token, less than 120 seconds ago, and was not already used.
- The user has a PIN (
GET /api/v1/pin/status). - The user was active in the last 30 minutes (operation OTP); otherwise open a new session.

