kamiPay LogokamiPay Docs

Notifications

Query and replay webhook notifications

This endpoint allows you to search your webhook notification history and re-trigger failed or missed webhook deliveries. Useful for debugging integration issues or recovering from temporary webhook endpoint outages.

All notification endpoints are rate-limited to 5 requests per minute per IP address.

List Notifications

GET /v2/notifications

Search and list notifications with optional filters.

Query Parameters

NameTypeDescription
e2e_idstringBank e2e_id (E* for payments, D* for refunds). Min 20 characters.
transaction_idstringKamiPay transaction ID (kamipay_id or kamipay_refund_id).
statusstringFilter by webhook status: done, processing, failed, refunded.
typestringFilter by type: pay (payout), charge (payin), or refund.
from_datedatetimeStart date filter (ISO 8601 format).
to_datedatetimeEnd date filter (ISO 8601 format).
limitintMaximum results to return (1-100). Default: 25.
offsetintPagination offset. Default: 0.

Example Request

const params = new URLSearchParams({
  type: 'pay',
  status: 'failed',
  from_date: '2026-01-01T00:00:00Z',
  to_date: '2026-01-28T23:59:59Z',
  limit: '50'
});

const url = `${baseURL}/v2/notifications?${params}`;

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

params = {
    'type': 'pay',
    'status': 'failed',
    'from_date': '2026-01-01T00:00:00Z',
    'to_date': '2026-01-28T23:59:59Z',
    'limit': 50
}

url = f"{base_url}/v2/notifications"

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

response = requests.get(url, params=params, headers=headers)
package main

import (
  "fmt"
  "net/http"
  "net/url"
)

func main() {
  baseURL := "https://api.kamipay.io"
  params := url.Values{}
  params.Add("type", "pay")
  params.Add("status", "failed")
  params.Add("from_date", "2026-01-01T00:00:00Z")
  params.Add("to_date", "2026-01-28T23:59:59Z")
  params.Add("limit", "50")

  url := fmt.Sprintf("%s/v2/notifications?%s", baseURL, params.Encode())

  req, _ := http.NewRequest("GET", url, nil)
  req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", access_token))
  req.Header.Add("Content-Type", "application/json")

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  defer resp.Body.Close()
}

Response

{
  "notifications": [
    {
      "notification_id": "a1b2c3d4-0001-4000-8000-000000000001",
      "last_updated_at": "2026-01-22T12:30:00+00:00",
      "payload": {
        "status": "done",
        "transaction_hash": null,
        "data": {
          "operation_id": "txc_01kfktest001done",
          "address_in": "0x14eD551D293E41A26E62D605Bc64F9beC154A698",
          "usdt_amount": "19.10718",
          "brl_amount": "100.00",
          "bank_txid": "E27084098202601221953g4eyYfCurMV",
          "pix_key": "11999887766",
          "name": "Usuario Test Uno"
        },
        "type": "pay",
        "timestamp": "2026-01-22 09:30:00.000000+0000",
        "external_id": "ext_payout_done_001",
        "kamipay_id": "txc_01kfktest001done",
        "service_type": "prepaid"
      }
    }
  ],
  "total": 1,
  "limit": 50,
  "offset": 0
}
{
  "detail": "Invalid e2e_id format: ABC123. Expected format: E* for payments, D* for refunds (min 20 characters)"
}
{
  "detail": "Incorrect Credentials"
}

Get Notification by Transaction ID

GET /v2/notifications/{kp_transaction_id}

Retrieve a single notification by its KamiPay transaction ID.

Path Parameters

NameTypeDescription
kp_transaction_idstringRequired. The KamiPay transaction ID.

Query Parameters

NameTypeDescription
typestringTransaction type hint: pay, charge, or refund. Auto-detected from ID prefix if not provided.

Auto-detection: The type is automatically detected from the transaction ID prefix:

  • txc_*: payout (pay)
  • ptxr_*, pir_*: payin (charge)
  • rpt_*: refund

Example Request

const kp_transaction_id = "txc_01jrazd7a9fqpp0bym8km1dbd6";
const url = `${baseURL}/v2/notifications/${kp_transaction_id}`;

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

kp_transaction_id = "txc_01jrazd7a9fqpp0bym8km1dbd6"
url = f"{base_url}/v2/notifications/{kp_transaction_id}"

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

response = requests.get(url, headers=headers)
package main

import (
  "fmt"
  "net/http"
)

func main() {
  kpTransactionID := "txc_01jrazd7a9fqpp0bym8km1dbd6"
  url := fmt.Sprintf("%s/v2/notifications/%s", baseURL, kpTransactionID)

  req, _ := http.NewRequest("GET", url, nil)
  req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", access_token))
  req.Header.Add("Content-Type", "application/json")

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  defer resp.Body.Close()
}

Response

{
  "notification_id": "a1b2c3d4-0001-4000-8000-000000000001",
  "last_updated_at": "2026-01-22T12:30:00+00:00",
  "payload": {
    "status": "done",
    "transaction_hash": null,
    "data": {
      "operation_id": "txc_01kfktest001done",
      "address_in": "0x14eD551D293E41A26E62D605Bc64F9beC154A698",
      "usdt_amount": "19.10718",
      "brl_amount": "100.00",
      "bank_txid": "E27084098202601221953g4eyYfCurMV",
      "pix_key": "11999887766",
      "name": "Usuario Test Uno"
    },
    "type": "pay",
    "timestamp": "2026-01-22 09:30:00.000000+0000",
    "external_id": "ext_payout_done_001",
    "kamipay_id": "txc_01kfktest001done",
    "service_type": "prepaid"
  }
}
{
  "detail": "Invalid transaction ID format: invalid_id. Expected prefixes: txc_, txp_, dqr_, lnk_, sqr_, ptxr_, pir_, rpt_, rbc_"
}
{
  "detail": "Notification not found"
}

Get Refunds for Transaction

GET /v2/notifications/{kp_transaction_id}/refunds

Find all refund notifications associated with a transaction.

Path Parameters

NameTypeDescription
kp_transaction_idstringRequired. The original KamiPay transaction ID.

Example Request

const kp_transaction_id = "txc_01jrazd7a9fqpp0bym8km1dbd6";
const url = `${baseURL}/v2/notifications/${kp_transaction_id}/refunds`;

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

kp_transaction_id = "txc_01jrazd7a9fqpp0bym8km1dbd6"
url = f"{base_url}/v2/notifications/{kp_transaction_id}/refunds"

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

response = requests.get(url, headers=headers)
package main

import (
  "fmt"
  "net/http"
)

func main() {
  kpTransactionID := "txc_01jrazd7a9fqpp0bym8km1dbd6"
  url := fmt.Sprintf("%s/v2/notifications/%s/refunds", baseURL, kpTransactionID)

  req, _ := http.NewRequest("GET", url, nil)
  req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", access_token))
  req.Header.Add("Content-Type", "application/json")

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  defer resp.Body.Close()
}

Response

{
  "original_transaction_id": "txc_01kfktest004refunded",
  "refunds": [
    {
      "notification_id": "c1b2c3d4-0001-4000-8000-000000000001",
      "last_updated_at": "2026-01-22T13:00:00+00:00",
      "payload": {
        "kamipay_refund_id": "rpt_01kfktest001refund",
        "kamipay_id": "txc_01kfktest004refunded",
        "external_id": "ext_payout_refunded",
        "refund_bank_txid": "D14796606202601222051497837G0003",
        "original_bank_txid": "E270840982026012219462noRErpDQMV",
        "service_type": "prepaid",
        "type": "pay",
        "status": "refunded",
        "refunded_brl_amount": "171.93",
        "refunded_usdt_amount": "32.850973",
        "original_brl_amount": "171.93",
        "original_usdt_amount": "32.850973",
        "original_recipient_name": "Usuario Refund Test",
        "timestamp": "2026-01-22 10:00:00.000000+0000"
      }
    }
  ],
  "total": 1
}
{
  "detail": "No refunds found for this transaction"
}

Replay Single Notification

POST /v2/notifications/{kp_transaction_id}/replay

Queue a single notification for replay. The notification will be re-delivered to your webhook URL.

Path Parameters

NameTypeDescription
kp_transaction_idstringRequired. The KamiPay transaction ID to replay.

The notification type is auto-detected from the transaction ID prefix. Ensure you're using the correct transaction ID format.

Example Request

const kp_transaction_id = "txc_01jrazd7a9fqpp0bym8km1dbd6";
const url = `${baseURL}/v2/notifications/${kp_transaction_id}/replay`;

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

kp_transaction_id = "txc_01jrazd7a9fqpp0bym8km1dbd6"
url = f"{base_url}/v2/notifications/{kp_transaction_id}/replay"

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

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

import (
  "fmt"
  "net/http"
)

func main() {
  kpTransactionID := "txc_01jrazd7a9fqpp0bym8km1dbd6"
  url := fmt.Sprintf("%s/v2/notifications/%s/replay", baseURL, kpTransactionID)

  req, _ := http.NewRequest("POST", url, nil)
  req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", access_token))
  req.Header.Add("Content-Type", "application/json")

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  defer resp.Body.Close()
}

Response

{
  "status": "queued",
  "notification_id": "a1b2c3d4-0001-4000-8000-000000000001",
  "kp_transaction_id": "txc_01kfktest001done"
}
{
  "detail": "Invalid transaction ID format"
}
{
  "detail": "Notification not found"
}
{
  "status": "already_queued",
  "notification_id": "a1b2c3d4-0001-4000-8000-000000000001",
  "kp_transaction_id": "txc_01kfktest001done"
}

Batch Replay Notifications

POST /v2/notifications/replay

Queue multiple notifications for replay by date range. All notifications matching the criteria will be re-delivered to your webhook URL.

Request Body

NameTypeDescription
start_datedatetimeRequired. Start of date range (ISO 8601 format).
end_datedatetimeRequired. End of date range (ISO 8601 format).
typestringRequired. Transaction type: pay, charge, or refund.

Maximum date range is 24 hours. For longer periods, make multiple requests with different date ranges.

Example Request

const url = `${baseURL}/v2/notifications/replay`;

const body = {
  start_date: "2026-01-15T00:00:00Z",
  end_date: "2026-01-15T23:59:59Z",
  type: "pay"
};

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

url = f"{base_url}/v2/notifications/replay"

body = {
    'start_date': '2026-01-15T00:00:00Z',
    'end_date': '2026-01-15T23:59:59Z',
    'type': 'pay'
}

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/v2/notifications/replay", baseURL)

  requestBody, _ := json.Marshal(map[string]interface{}{
    "start_date": "2026-01-15T00:00:00Z",
    "end_date":   "2026-01-15T23:59:59Z",
    "type":       "pay",
  })

  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")

  client := &http.Client{}
  resp, err := client.Do(req)
  if err != nil {
    fmt.Println("Error:", err)
    return
  }
  defer resp.Body.Close()
}

Response

Notifications queued successfully

{
  "status": "queued",
  "total_found": 2,
  "queued_count": 2,
  "already_queued_count": 0,
  "failed_count": 0,
  "notifications": [
    {
      "notification_id": "b1b2c3d4-0001-4000-8000-000000000001",
      "kp_transaction_id": "ptxr_01kfktest001done",
      "status": "queued",
      "error": null
    },
    {
      "notification_id": "b1b2c3d4-0002-4000-8000-000000000002",
      "kp_transaction_id": "ptxr_01kfktest002proc",
      "status": "already_queued",
      "error": null
    }
  ]
}
{
  "detail": "'end_date' must be after 'start_date'"
}
{
  "detail": "Date range cannot exceed 24 hours (got 48.0 hours)"
}

Response Status Values

StatusDescription
queuedNotifications were successfully queued for replay.
already_queuedAll notifications were already queued from a previous request.
none_foundNo notifications found matching the criteria.
partial_failureSome notifications failed to queue. Check individual notification errors.

On this page