Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.iterapay.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

Webhooks allow IteraPay to push real-time notifications to your server whenever a payment event occurs — such as an invoice being paid or a transaction being confirmed. Rather than polling the API, you register an endpoint on your server and IteraPay sends HTTP POST requests to it as events happen. This guide covers how to create your webhook, verify its authenticity, and handle incoming event payloads.
Always verify the webhook signature on every incoming request. Without signature verification, your endpoint is vulnerable to spoofed payloads from unauthorized sources.

Prerequisites

  • A publicly accessible HTTPS endpoint on your server
  • Your merchantID and a valid API key or JWT bearer token

Register a webhook endpoint

1

Create or update your webhook

Register your endpoint URL and a secret that IteraPay will use to sign payloads. If a webhook already exists for your merchant account, this request will update it.
curl --request POST \
  --url 'https://api.iterapay.com/weebhook/{merchantID}' \
  --header 'Authorization: Bearer YOUR_JWT_TOKEN' \
  --header 'Content-Type: application/json' \
  --data '{
    "url": "https://yoursite.com/webhooks/iterapay",
    "secret": "your-webhook-secret-min-32-chars-long"
  }'
Expected response:
{
  "token": "whk_eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Store the returned token securely. You’ll use it alongside your secret to verify that incoming webhook payloads genuinely originate from IteraPay.
2

Verify your webhook configuration

Confirm that your webhook is registered correctly by retrieving the current configuration.
curl --request GET \
  --url 'https://api.iterapay.com/weebhook/{merchantID}' \
  --header 'Authorization: Bearer YOUR_JWT_TOKEN'
Expected response:
{
  "url": "https://yoursite.com/webhooks/iterapay",
  "createdAt": "2024-01-01T10:00:00Z",
  "updatedAt": "2024-01-01T10:00:00Z"
}
3

Implement your webhook handler

Set up an HTTP endpoint on your server to receive POST requests from IteraPay. Your handler must:
  1. Read the raw request body (before any JSON parsing)
  2. Verify the signature (see the next section)
  3. Process the event
  4. Return a 200 status code promptly
webhook-handler.js
const express = require('express');
const crypto = require('crypto');
const app = express();

// Use raw body parser to preserve the original payload for signature verification
app.use('/webhooks/iterapay', express.raw({ type: 'application/json' }));

app.post('/webhooks/iterapay', (req, res) => {
  const signature = req.headers['x-iterapay-signature'];
  const rawBody = req.body;

  if (!verifySignature(rawBody, signature)) {
    return res.status(401).send('Invalid signature');
  }

  const event = JSON.parse(rawBody);

  switch (event.type) {
    case 'invoice.paid':
      // Handle paid invoice
      break;
    case 'transaction.confirmed':
      // Handle confirmed transaction
      break;
    default:
      console.log(`Unhandled event type: ${event.type}`);
  }

  res.status(200).send('OK');
});

function verifySignature(payload, signature) {
  const hmac = crypto.createHmac('sha256', process.env.WEBHOOK_SECRET);
  const computed = hmac.update(payload).digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(computed),
    Buffer.from(signature)
  );
}

Verify webhook signatures

Every request from IteraPay includes a signature header that you must validate before processing the payload. This confirms the request is genuine and the payload has not been tampered with. The signature is an HMAC-SHA256 hash of the raw request body, signed using your webhook secret. Verification steps:
  1. Extract the X-Iterapay-Signature header value
  2. Compute HMAC-SHA256(rawBody, yourSecret)
  3. Compare the computed hash to the header value using a constant-time comparison function (e.g., timingSafeEqual in Node.js or hmac.compare_digest in Python)
  4. Reject the request if the values do not match
Use a constant-time comparison function to prevent timing attacks. Do not use === or == to compare the signature strings directly.

Example webhook payload

IteraPay sends a JSON payload to your endpoint for each event. The structure includes an event type and an associated data object.
{
  "type": "invoice.paid",
  "merchantID": "merchant_e5f6a7b8-c9d0-1234-efab-345678901234",
  "timestamp": "2024-01-01T11:30:00Z",
  "data": {
    "invoiceID": "inv_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "amount": "100.500000",
    "currency": "USDT",
    "paidAt": "2024-01-01T11:30:00Z",
    "txHash": "a1b2c3d4e5f6789012345678901234567890abcdef1234567890abcdef12345678"
  }
}

Common event types

Event typeWhen it fires
invoice.paidA customer sends payment to an invoice address
transaction.confirmedAn on-chain transaction reaches the required number of confirmations
collection.completedA fund collection sweep finishes
withdrawal.completedA withdrawal transaction is confirmed on-chain

Remove a webhook

To stop receiving webhook notifications, delete your webhook configuration:
curl --request DELETE \
  --url 'https://api.iterapay.com/weebhook/{merchantID}' \
  --header 'Authorization: Bearer YOUR_JWT_TOKEN'
A successful deletion returns a 200 or 204 response with no body.

Next steps

Now that you’re receiving payment events in real time, you can automate your order fulfillment, update your database, or trigger downstream workflows on each payment confirmation.