KiraPay Public API

Public APIs secured via x-api-key. No JWT required.

Base URLs
  • Production: https://kirapay.focalfossa.site/api
Authentication

Include your API key in every request header:

x-api-key: YOUR_API_KEY

Endpoints

POST Generate Payment Link

/link/generate

Create a new payment link your customers can pay to.

Headers:
x-api-key: YOUR_API_KEY
Content-Type: application/json
Request Body:
{
  "currency": "USDC",
  "receiver": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
  "price": 100.5,
  "name": "Order #A1209",
  "redirectUrl": "https://merchant.example.com/thank-you"
}
Request Body Fields:
Field Type Required Description
currency string (enum) Yes Currency type for the payment. Supported values: USDC
receiver string Yes Ethereum wallet address (42 characters starting with 0x) where payments will be sent
price number Yes Payment amount in the specified currency (must be ≥ 0)
name string Yes Display name for the payment link (e.g., "Order #A1209", "Product Purchase")
redirectUrl string (URL) No URL to redirect users after successful payment completion
cURL:
curl -X POST "https://kirapay.focalfossa.site/api/link/generate" \
  -H "x-api-key: <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{
    "currency": "USDC",
    "receiver": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
    "price": 100.5,
    "name": "Order #A1209",
    "redirectUrl": "https://merchant.example.com/thank-you"
  }'
Success (201):
{
  "message": "success",
  "data": {
    "url": "https://kirapay.focalfossa.site/abc123def4"
  },
  "code": 201
}
Response Fields:
Field Type Description
message string Response status message, always "success" for successful requests
data.url string (URL) Complete payment link URL that customers can use to make payments
code number HTTP status code (201 for successful creation)
Errors:
{"statusCode": 400, "message": "INVALID_ETHEREUM_ADDRESS"}
{"statusCode": 400, "message": "ADDRESS_REQUIRED"}
{"statusCode": 400, "message": "NAME_MUST_BE_STRING"}
{"statusCode": 401, "message": "API_KEY_INVALID"}
{"statusCode": 500, "message": "Internal server error"}

GET Get User Links

/link

Retrieve a paginated list of payment links created by the authenticated user.

Headers:
x-api-key: YOUR_API_KEY
Query Parameters:
{
  "page": 1,                                // Optional: Page number (default: 1)
  "limit": 10                               // Optional: Items per page (default: 10)
}
Query Parameters Fields:
Field Type Required Description
page number No Page number for pagination (starts from 1, default: 1)
limit number No Number of items per page (default: 10, max: 100)
cURL:
curl -X GET "https://kirapay.focalfossa.site/api/link?page=1&limit=10" \
  -H "x-api-key: <YOUR_API_KEY>"
Success (200):
{
  "message": "success",
  "data": {
    "links": [
      {
        "_id": "67a1b3f2c4d5e6f7g8h9i0j1",
        "code": "abc123def4",
        "price": 100.5,
        "tokenOut": {
          "symbol": "USDC",
          "address": "0xA0b86a33E6441b8c4C8C0C8C0C8C0C8C0C8C0C8C",
          "decimals": 6,
          "chain": "ethereum"
        },
        "receiver": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
        "user": "507f1f77bcf86cd799439011",
        "key": "api_key_123",
        "name": "Order #A1209",
        "redirectUrl": "https://merchant.example.com/thank-you",
        "createdAt": "2025-01-25T10:00:00.000Z",
        "updatedAt": "2025-01-25T10:00:00.000Z"
      }
    ],
    "total": 1,
    "page": 1,
    "totalPages": 1
  },
  "code": 200
}
Response Fields:
Field Type Description
message string Response status message, always "success" for successful requests
data.links array Array of payment link objects
data.links[]._id string (MongoDB ObjectId) Unique identifier for the payment link
data.links[].code string Short code used in the payment URL (e.g., "abc123def4")
data.links[].price number Payment amount in the specified currency
data.links[].tokenOut object Token configuration object
data.links[].tokenOut.symbol string Token symbol (e.g., "USDC")
data.links[].tokenOut.address string Smart contract address of the token
data.links[].tokenOut.decimals number Number of decimal places for the token (usually 6 for USDC)
data.links[].tokenOut.chain string Blockchain network (e.g., "ethereum", "polygon")
data.links[].receiver string Ethereum wallet address where payments will be sent
data.links[].user string (MongoDB ObjectId) ID of the user who created the link
data.links[].key string API key used to create the link
data.links[].name string Display name for the payment link
data.links[].redirectUrl string (URL) URL to redirect users after payment completion
data.links[].createdAt string (ISO 8601) Timestamp when the link was created
data.links[].updatedAt string (ISO 8601) Timestamp when the link was last updated
data.total number Total number of links matching the query
data.page number Current page number
data.totalPages number Total number of pages available
code number HTTP status code (200 for successful requests)
Errors:
{"statusCode": 401, "message": "API_KEY_INVALID"}

GET Get Link by Code

/link/{code}

Retrieve the details of a payment link by its code. This is a public endpoint that doesn't require authentication.

cURL:
curl -X GET "https://kirapay.focalfossa.site/api/link/abc123def4"
Success (200):
{
  "message": "success",
  "data": {
    "_id": "67a1b3f2c4d5e6f7g8h9i0j1",
    "code": "abc123def4",
    "price": 100.5,
    "tokenOut": {
      "symbol": "USDC",
      "address": "0xA0b86a33E6441b8c4C8C0C8C0C8C0C8C0C8C0C8C",
      "decimals": 6,
      "chain": "ethereum"
    },
    "receiver": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
    "user": {
      "_id": "507f1f77bcf86cd799439011",
      "username": "merchant_user",
      "address": "0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6",
      "isVerified": true
    },
    "name": "Order #A1209",
    "redirectUrl": "https://merchant.example.com/thank-you",
    "createdAt": "2025-01-25T10:00:00.000Z",
    "updatedAt": "2025-01-25T10:00:00.000Z",
    "url": "https://kirapay.focalfossa.site/abc123def4"
  },
  "code": 200
}
Response Fields:
Field Type Description
message string Response status message, always "success" for successful requests
data._id string (MongoDB ObjectId) Unique identifier for the payment link
data.code string Short code used in the payment URL (e.g., "abc123def4")
data.price number Payment amount in the specified currency
data.tokenOut object Token configuration object
data.tokenOut.symbol string Token symbol (e.g., "USDC")
data.tokenOut.address string Smart contract address of the token
data.tokenOut.decimals number Number of decimal places for the token (usually 6 for USDC)
data.tokenOut.chain string Blockchain network (e.g., "ethereum", "polygon")
data.receiver string Ethereum wallet address where payments will be sent
data.user object User information object (populated from database)
data.user._id string (MongoDB ObjectId) Unique identifier of the user who created the link
data.user.username string Username of the link creator
data.user.address string Ethereum wallet address of the user
data.user.isVerified boolean Whether the user account is verified
data.name string Display name for the payment link
data.redirectUrl string (URL) URL to redirect users after payment completion
data.createdAt string (ISO 8601) Timestamp when the link was created
data.updatedAt string (ISO 8601) Timestamp when the link was last updated
data.url string (URL) Complete payment link URL that customers can use to make payments
code number HTTP status code (200 for successful requests)
Errors:
{"statusCode": 404, "message": "Link not found"}

GET Get Wallet Transactions

/wallet/transactions

Retrieve a paginated list of wallet transactions for the authenticated user.

Headers:
x-api-key: YOUR_API_KEY
Query Parameters:
{
  "status": "PENDING",                      // Optional: Filter by status (PENDING, COMPLETED, FAILED, CANCELLED)
  "transaction_hash": "0x1234567890",       // Optional: Filter by transaction hash
  "from_date": "2025-01-01T00:00:00.000Z", // Optional: Filter from date
  "to_date": "2025-01-31T23:59:59.999Z",   // Optional: Filter to date
  "page": 1,                                // Optional: Page number (default: 1)
  "limit": 10                               // Optional: Items per page (default: 10)
}
Query Parameters Fields:
Field Type Required Description
status string (enum) No Filter by transaction status. Values: PENDING, COMPLETED, FAILED, CANCELLED
transaction_hash string No Filter by specific blockchain transaction hash
from_date string (ISO 8601) No Filter transactions from this date onwards (inclusive)
to_date string (ISO 8601) No Filter transactions up to this date (inclusive)
page number No Page number for pagination (starts from 1, default: 1)
limit number No Number of items per page (default: 10, max: 100)
cURL:
curl -X GET "https://kirapay.focalfossa.site/api/wallet/transactions?page=1&limit=10&status=PENDING" \
  -H "x-api-key: <YOUR_API_KEY>"
Success (200):
{
  "message": "success",
  "data": {
    "transactions": [
      {
        "_id": "689324309eb9e6e8e0f842cd",
        "price": 0.015,
        "hash": "0xb6accc136297ad17ab831028f967cbf2bdd9ff67b8fab5d4e8e4f34f8681eb59",
        "status": "Success",
        "type": "Contract",
        "user": {
          "_id": "688c82d81c6a157748c5ca7b",
          "username": "john_doe"
        },
        "link": "6891c0896aad1cd3bf2f3490",
        "source": "7",
        "createdAt": "2025-08-06T09:45:20.374Z",
        "updatedAt": "2025-08-06T09:45:50.365Z",
        "__v": 0,
        "payload": {
          "eventNonce": "0x9bd7d21d481bd64a3f046b6c9e930b5843a0c36f8832a1c8e8e2319c16da6f28",
          "attestation": "0x8730053fe55a898df9f81f4c45364ef1ad7541125e20656278ec9749d92ec7bb3bd5b5c81703be23d9013e03db36f2b57e8074032f68e1b9dea26570c254c0b41c2bb48dbabb202780d06305148f768bc8af82b92632fddffa88e54950deadf5774fea1bd99f721c08e88d72e15f674200438b25256c88919a6ddf29fee5df91c91c",
          "cctpVersion": 2,
          "sender": "0x28b5a0e9c621a5badaa536219b3a228c8168cf5d",
          "recipient": "0x28b5a0e9c621a5badaa536219b3a228c8168cf5d",
          "mintRecipient": "0x4b6aee828992738f64b1e908f082aa9f2cc6936a",
          "messageSender": "0x4b6aee828992738f64b1e908f082aa9f2cc6936a",
          "amount": "15000",
          "maxFee": 2,
          "feeExecuted": 0,
          "sourceDomain": 7,
          "destinationDomain": 6,
          "status": "complete"
        }
      }
    ],
    "total": 1,
    "page": 1,
    "totalPages": 1
  },
  "code": 200
}
Response Fields:
Field Type Description
message string Response status message, always "success" for successful requests
data.transactions array Array of transaction objects
data.transactions[]._id string (MongoDB ObjectId) Unique identifier for the transaction
data.transactions[].price number Transaction amount in the specified currency
data.transactions[].hash string Blockchain transaction hash (66 characters starting with 0x)
data.transactions[].status string Transaction status (e.g., "Success", "Pending", "Cancel")
data.transactions[].type string Transaction type (e.g., "Contract", "Transfer", "Refund")
data.transactions[].user object User information object (populated from database)
data.transactions[].user._id string (MongoDB ObjectId) Unique identifier of the user
data.transactions[].user.username string Username of the user
data.transactions[].link string (MongoDB ObjectId) ID of the payment link associated with this transaction
data.transactions[].source string Source domain identifier for cross-chain transactions
data.transactions[].createdAt string (ISO 8601) Timestamp when the transaction was created
data.transactions[].updatedAt string (ISO 8601) Timestamp when the transaction was last updated
data.transactions[].__v number MongoDB version key (internal field)
data.transactions[].payload object CCTP (Cross-Chain Transfer Protocol) transaction payload
data.transactions[].payload.eventNonce string Unique event nonce for the cross-chain transaction
data.transactions[].payload.attestation string Attestation signature for cross-chain verification
data.transactions[].payload.cctpVersion number Version of the CCTP protocol used
data.transactions[].payload.sender string Original sender's wallet address
data.transactions[].payload.recipient string Recipient's wallet address
data.transactions[].payload.mintRecipient string Address where tokens will be minted on destination chain
data.transactions[].payload.messageSender string Address that initiated the cross-chain message
data.transactions[].payload.amount string Transaction amount as string (in smallest token unit)
data.transactions[].payload.maxFee number Maximum fee allowed for the transaction
data.transactions[].payload.feeExecuted number Actual fee executed for the transaction
data.transactions[].payload.sourceDomain number Source blockchain domain identifier
data.transactions[].payload.destinationDomain number Destination blockchain domain identifier
data.transactions[].payload.status string CCTP transaction status (e.g., "complete", "pending")
data.total number Total number of transactions matching the query
data.page number Current page number
data.totalPages number Total number of pages available
code number HTTP status code (200 for successful requests)
Errors:
{"statusCode": 401, "message": "API_KEY_INVALID"}
{"statusCode": 400, "message": "INVALID_STATUS"}
{"statusCode": 400, "message": "Invalid date format"}

Webhooks

KiraPay can send webhook notifications to your server when important events occur. This allows you to react to events in real-time without polling our API.

How Webhooks Work

  1. You register a webhook endpoint URL with KiraPay
  2. When an event occurs, KiraPay sends a POST request to your endpoint
  3. Your server processes the webhook and returns a 200 status code
  4. If your server doesn't respond with 200, KiraPay will retry the delivery

Webhook Events

KiraPay currently supports the following webhook events:

  • transaction.created - A new transaction has been created
  • transaction.succeeded - A transaction has completed successfully
  • transaction.failed - A transaction has failed

Webhook Payload Structure

All webhook payloads follow this structure:

{
  "id": "evt_1704067200000_abc123",
  "type": "transaction.succeeded",
  "createdAt": "2025-01-25T10:00:00.000Z",
  "data": {
    // Event-specific data (see examples below)
  }
}

Webhook Headers

KiraPay includes the following headers with each webhook request:

Header Description
Content-Type Always application/json
X-KiraPay-Event The event type (e.g., transaction.succeeded)
X-KiraPay-Id Unique event ID (e.g., evt_1704067200000_abc123)
X-KiraPay-Timestamp Unix timestamp when the event was created
X-KiraPay-Signature HMAC-SHA256 signature for webhook verification

Webhook Verification

To verify that webhooks are coming from KiraPay, you should verify the signature:

const crypto = require('crypto');

function verifyWebhook(payload, signature, secret, timestamp) {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(`${timestamp}.${payload}`)
    .digest('base64');
  
  const expectedHeader = `sha256=${expectedSignature}`;
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedHeader)
  );
}

// Usage
const isValid = verifyWebhook(
  request.body,
  request.headers['x-kirapay-signature'],
  'your_webhook_secret',
  request.headers['x-kirapay-timestamp']
);

Event Examples

transaction.created

Sent when a new transaction is created:

{
  "id": "evt_1704067200000_abc123",
  "type": "transaction.created",
  "createdAt": "2025-01-25T10:00:00.000Z",
  "data": {
    "_id": "689324309eb9e6e8e0f842cd",
    "price": 0.015,
    "hash": "0xb6accc136297ad17ab831028f967cbf2bdd9ff67b8fab5d4e8e4f34f8681eb59",
    "status": "Pending",
    "type": "Contract",
    "user": {
      "_id": "688c82d81c6a157748c5ca7b",
      "username": "john_doe"
    },
    "link": "6891c0896aad1cd3bf2f3490",
    "source": "7",
    "createdAt": "2025-01-25T10:00:00.000Z",
    "updatedAt": "2025-01-25T10:00:00.000Z"
  }
}
transaction.succeeded

Sent when a transaction completes successfully:

{
  "id": "evt_1704067260000_def456",
  "type": "transaction.succeeded",
  "createdAt": "2025-01-25T10:01:00.000Z",
  "data": {
    "_id": "689324309eb9e6e8e0f842cd",
    "price": 0.015,
    "hash": "0xb6accc136297ad17ab831028f967cbf2bdd9ff67b8fab5d4e8e4f34f8681eb59",
    "status": "Success",
    "type": "Contract",
    "user": {
      "_id": "688c82d81c6a157748c5ca7b",
      "username": "john_doe"
    },
    "link": "6891c0896aad1cd3bf2f3490",
    "source": "7",
    "createdAt": "2025-01-25T10:00:00.000Z",
    "updatedAt": "2025-01-25T10:01:00.000Z",
    "payload": {
      "eventNonce": "0x9bd7d21d481bd64a3f046b6c9e930b5843a0c36f8832a1c8e8e2319c16da6f28",
      "attestation": "0x8730053fe55a898df9f81f4c45364ef1ad7541125e20656278ec9749d92ec7bb3bd5b5c81703be23d9013e03db36f2b57e8074032f68e1b9dea26570c254c0b41c2bb48dbabb202780d06305148f768bc8af82b92632fddffa88e54950deadf5774fea1bd99f721c08e88d72e15f674200438b25256c88919a6ddf29fee5df91c91c",
      "cctpVersion": 2,
      "sender": "0x28b5a0e9c621a5badaa536219b3a228c8168cf5d",
      "recipient": "0x28b5a0e9c621a5badaa536219b3a228c8168cf5d",
      "mintRecipient": "0x4b6aee828992738f64b1e908f082aa9f2cc6936a",
      "messageSender": "0x4b6aee828992738f64b1e908f082aa9f2cc6936a",
      "amount": "15000",
      "maxFee": 2,
      "feeExecuted": 0,
      "sourceDomain": 7,
      "destinationDomain": 6,
      "status": "complete"
    }
  }
}
transaction.failed

Sent when a transaction fails:

{
  "id": "evt_1704067320000_ghi789",
  "type": "transaction.failed",
  "createdAt": "2025-01-25T10:02:00.000Z",
  "data": {
    "_id": "689324309eb9e6e8e0f842cd",
    "price": 0.015,
    "hash": "0xb6accc136297ad17ab831028f967cbf2bdd9ff67b8fab5d4e8e4f34f8681eb59",
    "status": "Failed",
    "type": "Contract",
    "user": {
      "_id": "688c82d81c6a157748c5ca7b",
      "username": "john_doe"
    },
    "link": "6891c0896aad1cd3bf2f3490",
    "source": "7",
    "createdAt": "2025-01-25T10:00:00.000Z",
    "updatedAt": "2025-01-25T10:02:00.000Z",
    "error": "Transaction reverted due to insufficient gas"
  }
}

Webhook Endpoint Management

Webhook endpoints are managed through the admin API. You need to be authenticated with an admin API key to manage webhooks.

Create Webhook Endpoint
curl -X POST "https://kirapay.focalfossa.site/api/admin/webhooks/endpoints" \
  -H "x-api-key: YOUR_ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-app.com/webhooks/kirapay",
    "secret": "whsec_your_webhook_secret"
  }'
List Webhook Endpoints
curl -X GET "https://kirapay.focalfossa.site/api/admin/webhooks/endpoints" \
  -H "x-api-key: YOUR_ADMIN_API_KEY"
Update Webhook Endpoint
curl -X PATCH "https://kirapay.focalfossa.site/api/admin/webhooks/endpoints/ENDPOINT_ID" \
  -H "x-api-key: YOUR_ADMIN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-new-app.com/webhooks/kirapay",
    "secret": "whsec_new_webhook_secret"
  }'
View Webhook Deliveries
curl -X GET "https://kirapay.focalfossa.site/api/admin/webhooks/deliveries?endpointId=ENDPOINT_ID&status=success" \
  -H "x-api-key: YOUR_ADMIN_API_KEY"

Best Practices

  • Always verify webhook signatures to ensure requests are from KiraPay
  • Return 200 status codes quickly to acknowledge receipt
  • Handle duplicate events by checking the event ID
  • Use HTTPS endpoints for security
  • Implement idempotency in your webhook handlers
  • Log webhook events for debugging and auditing

Retry Logic

If your webhook endpoint doesn't return a 200 status code, KiraPay will retry the delivery:

  • Initial delivery attempt
  • Retry after 1 minute if failed
  • Additional retries with exponential backoff
  • Maximum retry attempts: 3

Error Handling

Error Response Format

All error responses follow the same structure:

{
  "statusCode": 400,
  "message": "ERROR_CODE",
  "timestamp": "2025-01-25T10:00:00.000Z",
  "path": "/request/path"
}

Common HTTP Status Codes

  • 200: OK
  • 201: Created
  • 400: Bad Request
  • 401: Unauthorized (missing/invalid x-api-key)
  • 404: Not Found
  • 429: Too Many Requests
  • 500: Internal Server Error