PayLinkr

Webhooks

PayLinkr can send signed webhook events whenever invoice state changes. Webhooks are intended for PRO accounts that want fulfillment, entitlement, or accounting workflows to run automatically.

01 Setup

  1. Open your dashboard webhook settings or use the PRO webhook API routes.
  2. Set a publicly reachable HTTPS endpoint that accepts POST requests.
  3. Store the webhook signing secret securely in your application.
  4. Send a test event before relying on live delivery.
Do not process live webhook traffic until signature verification is in place. The signature is your first line of defense against spoofed requests.

02 Event types

EventMeaning
invoice.createdA new invoice was created and is now available for payment.
invoice.paidThe invoice has been fully satisfied and marked paid.
invoice.partially_paidA payment was matched, but the invoice still has an outstanding balance.
invoice.underpaidThe platform classified the current payment state as underpaid.
invoice.overpaidThe total amount received is above the expected amount.
invoice.expiredThe invoice expired before a valid final settlement state was reached.

Depending on how you use invoice actions and settlement controls, your system may see more than one event over the life of a single invoice.

03 Payload shape

Webhooks are delivered as JSON POST requests. The payload includes invoice identifiers, settlement information, and timestamps so your application can make deterministic decisions.

{
  "event": "invoice.paid",
  "invoiceId": "clxxxxxxxxxxxxx",
  "publicId": "a1b2c3d4e5f6g7h8",
  "status": "paid",
  "title": "Consulting Deposit",
  "expectedAmount": "250.00",
  "receivedAmount": "250.00",
  "asset": "USDC",
  "paymentNetwork": "STELLAR",
  "memo": "PLR-A1B2C3D4",
  "reference": "PLR-A1B2C3D4",
  "referenceLabel": "Memo",
  "destinationAddress": "GABC...XYZ",
  "orderId": "ORD-9001",
  "createdAt": "2026-04-03T10:00:00.000Z",
  "paidAt": "2026-04-03T10:05:32.000Z",
  "expiresAt": "2026-04-04T10:00:00.000Z",
  "timestamp": "2026-04-03T10:05:33.000Z"
}

04 Signature verification

Each request includes an X-PayLinkr-Signature header in the format sha256=<digest>. Compute an HMAC SHA-256 digest over the raw request body using your webhook secret and compare it using a timing-safe method.

import crypto from 'crypto'

export function verifyPayLinkrWebhook(rawBody: string, signature: string, secret: string) {
  const expected =
    'sha256=' +
    crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex')

  try {
    return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))
  } catch {
    return false
  }
}
Verify against the raw body, not a re-serialized JSON object. Many frameworks mutate formatting, which breaks signature validation.

05 Headers

HeaderPurpose
X-PayLinkr-SignatureHMAC SHA-256 signature for the raw request body.
X-PayLinkr-EventThe logical event type, such as invoice.paid.
X-PayLinkr-DeliveryUnique delivery identifier for that specific attempt.
Content-Typeapplication/json
User-AgentPayLinkr-Webhook/1.0

06 Delivery and retries

Treat webhook delivery as at-least-once. Your handler should respond quickly with a 2xx status code, queue any heavier work, and make downstream processing idempotent.

Recommended practiceWhy it matters
Return 2xx quicklyAvoid unnecessary retries caused by long-running business logic.
Use event plus invoice ID as an idempotency keyThe same invoice may be retried or re-sent across delivery attempts.
Log delivery IDsLets you reconcile a specific webhook attempt with PayLinkr delivery logs.
Store raw payloads during rolloutMakes debugging easier while your integration hardens.

07 Operating webhooks in production

  • - Rotate webhook secrets when operators change or a secret may have leaked.
  • - Use the dashboard or webhook API to send test events before enabling live fulfillment.
  • - Review delivery logs when a customer says a paid invoice did not unlock service in your app.
  • - Combine webhook handling with the API if you need to re-check invoice state before committing fulfillment.
Need more control? Pair webhooks with the API Reference so your application can both react to events and fetch current invoice state when needed.