kamiPay LogokamiPay Docs

Paying Pix

Send payments to Brazilian bank accounts via Pix

This endpoint allows you to make payments from USDT to any given Pix key, which will reflect the balance in seconds into any bank account in Brazil.

Payments are processed through our prepaid system with direct bank settlement for optimal speed and reliability.

Request Body

NameTypeDescription
pix_keystringRequired. The Pix key of the recipient. Can be a CPF/CNPJ, email, phone number, or random key.
currencystringRequired. Either 'BRL' or 'USDT'. Determines how the amount is interpreted.
amountfloatRequired. Amount to be sent. Minimum of 3 BRL is required for payments.
from_addressstringRequired. Specifies the sender wallet address.
external_idstringRequired. Your internal reference ID for this transaction. Must be unique for each payment attempt. Used to prevent duplicates and track transactions.

Currency Handling: If you set the currency as BRL, the amount will be paid exactly unless the payment hits after the rate changes significantly (tolerance is 50cts USDT). If you set the currency as USDT, it'll be converted into BRL at the time of arrival with the actual exchange rate.

The minimum payment amount is 3 BRL.

Important: Always use kamipay_id and external_id as primary identifiers for tracking transactions. The transaction_hash field may occasionally contain a value but should be ignored for integration purposes.

Example Request

const url = `${baseURL}/v1/payments/payToPixKey`;

const body = {
  "currency": "BRL",
  "amount": 4.10,
  "pix_key": "user@example.com", // CPF/CNPJ/email/Phone/pixkey
  "from_address": "0x1c0aCF853xxxxx9488fEdce1ab4",
  "external_id": "payment-unique-id-001" // Must be unique for each attempt
};

const response = await fetch(url, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${access_token}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify(body)
});
import requests
import json

url = f"{base_url}/v1/payToPixKey"

body = {
  "currency": "BRL",
  "amount": 4.10,
  "pix_key": "user@example.com", # CPF/CNPJ/email/Phone/pixkey
  "from_address": "0x1c0aCF853xxxxx9488fEdce1ab4",
  "external_id": "payment-unique-id-001" # Must be unique for each attempt
}

headers = {
    'Authorization': f'Bearer {access_token}',
    'Content-Type': 'application/json',
}

response = requests.post(url, json=body, headers=headers)
package main

import (
  "bytes"
  "encoding/json"
  "fmt"
  "net/http"
)

func main() {
  url := fmt.Sprintf("%s/v1/payments/payToPixKey", baseURL)
  
  // Create request body
  requestBody, _ := json.Marshal(map[string]interface{}{
    "currency": "BRL",
    "amount": 4.10,
    "pix_key": "user@example.com", // CPF/CNPJ/email/Phone/pixkey
    "from_address": "0x1c0aCF853xxxxx9488fEdce1ab4",
    "external_id": "payment-unique-id-001", // Must be unique for each attempt
  })
  
  // Create request
  req, _ := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
  req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", access_token))
  req.Header.Add("Content-Type", "application/json")
  
  // Make the request
  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error making request:", err)
    return
  }
  defer resp.Body.Close()
}

Response

Payment Successfully Processed

{
  "status": "ok",
  "kamipay_id": "txc_01jrazd7a9fqpp0bym8km1dbd6",
  "data": {
    "status": "broadcasted",
    "transaction_hash": "", // May be empty for prepaid flow
    "usdt_amount": 0.875934
  },
  "external_id": "testing123"
}

Note: The transaction_hash field may occasionally contain a value but should be ignored. Always use kamipay_id and external_id for transaction tracking.

Payment Created (Processing)

{
  "status": "created",
  "kamipay_id": "txc_01jkg5vktaer5abc123kjgrsn2",
  "data": null,
  "external_id": "idempotency-1"
}

Bad Request

{
  "detail": "detailed error will be provided here"
}

Unauthorized

{
  "detail": "Incorrect Credentials"
}

Conflict (Previous Transaction Cancelled)

{
  "status": "canceled",
  "kamipay_id": "txc_01jkg5vktaer5abc123kjgrsn2",
  "data": null,
  "external_id": "idemptency-1"
}

Payment Failed (Transaction Cancelled)

{
  "status": "canceled",
  "kamipay_id": "txc_01jrazd7a9fqpp0bym8km1dbd6",
  "external_id": "testing123"
}

Critical: This status indicates the transaction could NOT be processed and should be considered failed. If you want to retry the payment, you must use a new external_id.

Internal Server Error

{
  "detail": "an unexpected error occurred"
}

Service Unavailable

{
  "detail": "Service is temporarily unavailable due to maintenance"
}

Transaction Identifiers

IdentifierDescription
kamipay_idPrimary identifier provided by kamiPay to monitor a specific transaction until completion. Always use this for transaction tracking.
external_idYour transaction identifier. Must be unique for each payment attempt. Essential for preventing duplicates, tracking in webhooks, and status endpoints.
transaction_hashLegacy field that may occasionally contain a value. Should be ignored for integration purposes.

Important: Always use kamipay_id and external_id as your primary tracking mechanisms. Do not rely on the transaction_hash field.

Payment Processing

Payments are processed through our prepaid system, which provides:

  • Fast settlement: Direct bank transfers settled in batches
  • Reliable processing: No dependency on blockchain network conditions
  • Transparent billing: Charges calculated on confirmed payments minus any refunds received
  • Consistent identifiers: Same tracking system (kamipay_id and external_id) regardless of underlying processing method

Error Handling & Retries

Status Code 424 - Critical Failure: When receiving a 424 status code, the transaction has failed permanently. To retry the payment, you must generate a new external_id. Using the same external_id will result in duplicate prevention mechanisms blocking the request.

Retry Guidelines

  1. Successful payments (200): No retry needed
  2. Processing payments (201): Monitor status via webhooks or status endpoint
  3. Failed payments (424): Generate new external_id before retrying
  4. Conflicts (409): Previous transaction was cancelled, can retry with same external_id
  5. Server errors (500/503): Safe to retry with same external_id after delay

Handling Parallel Requests

Status: Created (201)

When making requests while a previous transaction is still processing:

  • Returns 201 status code
  • Transaction was queued but is still processing
  • The data field will be null
  • Monitor via status endpoint or webhooks

Status: Cancelled (409/424)

  • 409: Previous transaction cancelled due to internal issues, can retry
  • 424: Current transaction failed to process, must use new external_id to retry

The payment process is asynchronous. After receiving a 201 status code, monitor the transaction status using the status endpoint or set up webhooks to receive real-time notifications.

Be careful when specifying Pix keys. Each key type has a specific format, and sending incorrect formats will result in errors or delayed payments.

On this page