Pix Key Validation
Verify the owner of a Pix key before making a payment
Overview
This endpoint validates a PIX key and returns the name of the bank account owner, allowing you to verify the recipient before making a payment. It supports standard PIX keys as well as QR code payloads (static and dynamic).
What are PIX Keys?
PIX Keys are aliases used by the Brazilian instant payment system to route payments to bank accounts. They can take several forms:
- CPF: Brazilian personal ID — use only numbers, no dots or dashes (e.g.,
12345678900) - CNPJ: Brazilian company ID — use only numbers (e.g.,
12345678000190) - Email address: Standard email format (e.g.,
user@example.com) - Phone number: Brazilian phone number. Accepted formats: with country code (
+5511999999999), without the+(5511999999999), or local number only (11999999999). kamiPay will normalize the number automatically to the full international format (+55...). - Random key: UUID format alphanumeric string (e.g.,
a1b2c3d4-e5f6-7890-abcd-ef1234567890) - QR Code payload (EMV): The full EMV string from a PIX QR code (starts with
0002...)
Validating a Pix key before making a payment is required. It ensures that funds are sent to the intended recipient and reduces the risk of errors.
Query Parameters
| Name | Type | Description |
|---|---|---|
| pix_key | string | Required. The Pix key to validate. Can be a CPF, CNPJ, email, phone number, random key, or a QR code EMV payload. |
Example Request
const pix_key = "mati@kamipay.io";
const url = `${baseURL}/v1/payments/pixKeyValidation?pix_key=${pix_key}`;
const response = await fetch(url, {
method: "GET",
headers: {
Authorization: `Bearer ${access_token}`,
"Content-Type": "application/json",
},
});
const data = await response.json();
console.log(data);import requests
pix_key = "mati@kamipay.io"
url = f"{base_url}/v1/payments/pixKeyValidation?pix_key={pix_key}"
headers = {
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
}
response = requests.get(url, headers=headers)
data = response.json()
print(data)package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
)
func main() {
pix_key := "mati@kamipay.io"
accessToken := "YOUR_ACCESS_TOKEN" // Replace with your actual token
baseURL := "https://your-api-base-url.com" // Replace with your actual base URL
// Create URL with query parameters
reqURL, _ := url.Parse(fmt.Sprintf("%s/v1/payments/pixKeyValidation", baseURL))
params := url.Values{}
params.Add("pix_key", pix_key)
reqURL.RawQuery = params.Encode()
// Create request
req, _ := http.NewRequest("GET", reqURL.String(), nil)
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", accessToken))
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()
// Read the response body
body, _ := ioutil.ReadAll(resp.Body)
// Print response status and body
fmt.Println("Response Status:", resp.Status)
fmt.Println("Response Body:", string(body))
}Response Format
Important: Successful responses (HTTP 200) and error responses have different JSON structures. Successful responses return fields at the root level. Error responses wrap the information inside a detail object.
Successful Responses (HTTP 200)
All successful validations return the same JSON structure at the root level. The values of amount and timeout vary depending on the type of PIX key.
{
"msg": "valid pixkey",
"reformated_key": "<validated key or EMV payload>",
"name": "<account holder name>",
"amount": "<amount or empty string>",
"timeout": "<epoch timestamp or 0>"
}Standard PIX key using a CPF (personal ID). No predefined amount or expiration.
{
"msg": "valid pixkey",
"reformated_key": "12345678900",
"name": "JOAO DA SILVA",
"amount": "",
"timeout": "0"
}Standard PIX key using a CNPJ (company ID). No predefined amount or expiration.
{
"msg": "valid pixkey",
"reformated_key": "12345678000190",
"name": "EMPRESA LTDA",
"amount": "",
"timeout": "0"
}Standard PIX key using an email address. No predefined amount or expiration.
{
"msg": "valid pixkey",
"reformated_key": "mati@kamipay.io",
"name": "LARISSA DA SILVA DIAS",
"amount": "",
"timeout": "0"
}Standard PIX key using a phone number. No predefined amount or expiration. The reformated_key always returns the normalized format with country code (+55), regardless of the format you sent.
{
"msg": "valid pixkey",
"reformated_key": "+5511999999999",
"name": "MARIA SANTOS",
"amount": "",
"timeout": "0"
}kamiPay accepts phone numbers in multiple formats and normalizes them automatically:
+5511999999999— full international format (returned as-is)5511999999999— without the+prefix (kamiPay adds the+)11999999999— local number without country code (kamiPay adds+55)
Standard PIX key using a random UUID. No predefined amount or expiration.
{
"msg": "valid pixkey",
"reformated_key": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "CARLOS FERREIRA",
"amount": "",
"timeout": "0"
}QR code payload without expiration. Static QR codes may or may not include a predefined amount.
Static QR without predefined amount — the user can pay any amount:
{
"msg": "valid pixkey",
"reformated_key": "00020126680014br.gov.bcb.pix0115***02275204000053039865802BR5925KAMIPAY LTDA6009SAO PAULO622905256673568298KP19478949731630470C8",
"name": "KAMIPAY LTDA",
"amount": "",
"timeout": "0"
}Static QR with predefined amount — the exact amount must be paid:
{
"msg": "valid pixkey",
"reformated_key": "00020126680014br.gov.bcb.pix0115***02275204000053039865802BR5925KAMIPAY LTDA6009SAO PAULO622905256673568298KP19478949731630470C8",
"name": "KAMIPAY LTDA",
"amount": "25.50",
"timeout": "0"
}Static QR codes do not expire (timeout is always "0"). Check the amount field: if it is empty (""), the payment amount must be collected from the user. If it contains a value, that exact amount must be paid. The reformated_key contains the full EMV payload.
QR code payload with a fixed amount and expiration. The exact amount must be paid before the timeout expires.
{
"msg": "valid pixkey",
"reformated_key": "00020126820014br.gov.bcb.pix25601da4ebd2-7fbb-4933-a6f7-7d392BR5925KAMIPAY_LTDA6009SAO_PAULO62070503***6304CFAB",
"name": "KAMIPAY LTDA",
"amount": "10.00",
"timeout": "1744116044"
}Dynamic QR codes have a fixed amount that must be paid exactly. The timeout is a Unix epoch timestamp — the payment must be submitted before this time. If the QR has already expired at the time of validation, the endpoint will return a 400 error instead (see error responses below).
Error Responses
Error responses wrap information inside a detail field. The detail can be either an object (for validation errors) or a string (for general HTTP errors).
Bad Request — Multiple validation scenarios can trigger a 400 error. The format of detail varies:
Missing pix_key parameter:
{
"detail": "pix_key parameter missing"
}Invalid PIX key format (key does not match any known format):
{
"detail": {
"msg": "Description of the format error",
"reformated_key": null,
"name": null
}
}PIX key not found (standard key — CPF, CNPJ, email, phone, random):
{
"detail": {
"msg": "pix key not found",
"reformated_key": null,
"name": null
}
}Expired or invalid QR code (QR code payload that is expired or cannot be decoded):
{
"detail": {
"msg": "Expired or Invalid QR code",
"reformated_key": null,
"name": null
}
}Dynamic QR already expired (QR was valid but its expiration timestamp has passed):
{
"detail": "Invalid Pix Key: already expired at 2026-03-16T10:00:00+00:00"
}Note that the detail field can be either a string or an object depending on the specific error. Your integration should handle both formats.
Unauthorized
Invalid or expired token:
{
"detail": "Incorrect Credentials"
}Valid token but insufficient permissions:
{
"detail": "Token Profile Not Authorized for this Endpoint"
}Forbidden — The QR code belongs to the same financial institution as the sender. This transaction cannot be processed through kamiPay.
{
"detail": {
"msg": "Same Payor and Receiver Insitution. Cannot Proceed",
"reformated_key": null,
"name": null
}
}Internal Server Error
{
"detail": {
"msg": "An unexpected error occurred.",
"detail": "the_pix_key_sent"
}
}Service Unavailable — The validation service or payment gateway is temporarily unavailable.
{
"detail": "Service temporarily unavailable"
}Gateway Timeout — The upstream provider did not respond in time while validating the PIX key.
{
"detail": {
"msg": "internal connection/read timeout",
"reformated_key": null,
"name": null
}
}This is a transient error. You can safely retry the request after a short delay.
Field Descriptions
Successful Response Fields (HTTP 200)
| Field | Type | Description |
|---|---|---|
msg | string | Status message. Always "valid pixkey" for successful validations. |
reformated_key | string | The validated and formatted PIX key. For standard keys (CPF, email, etc.) this is the normalized key. For QR codes, this is the full EMV payload. |
name | string | Name of the bank account holder associated with the PIX key. |
amount | string | Payment amount for QR codes with a predefined value (e.g., "10.00"). Empty string "" for standard keys and QR codes where no amount is predefined. When present, this exact amount must be paid. |
timeout | string | Expiration as a Unix epoch timestamp for dynamic QR codes (e.g., "1744116044"). "0" for standard keys and static QR codes that do not expire. |
Error Response Fields
| Field | Type | Description |
|---|---|---|
detail | string or object | Contains the error information. Can be a plain string (e.g., "pix_key parameter missing") or an object with msg, reformated_key, and name fields. |
detail.msg | string | Description of the error (when detail is an object). |
detail.reformated_key | null | Always null in error responses. |
detail.name | null | Always null in error responses. |
Implementation Notes
- Check the HTTP status code first. A
200means the key is valid. Any other status code indicates an error. - Successful (200) and error responses have different structures. On
200, the fields (msg,reformated_key,name,amount,timeout) are at the JSON root level. On errors, the information is inside thedetailfield. - Handle both
detailformats. Thedetailfield in error responses can be a string or an object — your integration should handle both. - For dynamic QR codes (
timeoutis not"0"), verify that the current time (as Unix epoch) is before thetimeoutvalue before proceeding with the payment. - When
amountis present (dynamic QR or static QR with predefined amount), use the exact value returned. The recipient expects that specific amount. - When
amountis empty ("") andtimeoutis"0", the payment amount must be collected from the user. This applies to standard PIX keys and static QR codes without a predefined amount. - A
504error is transient and can be retried after a short delay. Other errors (400, 403) should not be retried with the same input.