PaybytokenDocs
Payment Requests
Guide · Payment Requests

Payment Request webhooks and operations

Fulfill receivables from verified events and monitor delivery, unapplied funds and aggregate drift.

Subscribe to payment_request.* or exact events. Verify signatures against the raw body, persist each event ID with a unique constraint, and tolerate duplicates and out-of-order delivery.

EventMeaning
payment_request.finalizedTerms were locked and the request became payable.
payment_request.sentThe email provider accepted one delivery attempt.
payment_request.delivery_failedEmail exhausted its retry policy.
payment_request.payment_processingFunds were observed and are awaiting finality.
payment_request.payment_appliedConfirmed funds were allocated.
payment_request.payment_unappliedConfirmed funds require review.
payment_request.payment_failedAn attempt ended without allocatable funds.
payment_request.paidThe remaining receivable balance reached zero.

payment_request.sent is not proof of inbox delivery. Likewise, payment_processing is not final payment. Fulfill only from valid terminal resource state, normally payment_request.paid, and retrieve the request if event order is ambiguous.

Process transitions idempotently

Keep the Payment Request ID separate from the Payment Intent and allocation IDs. A single request can receive several attempts and partial allocations.

async function processPaymentRequestEvent(event) {
  await database.transaction(async (transaction) => {
    if (await transaction.events.exists(event.id)) return

    await transaction.events.insert(event.id)

    if (event.type === 'payment_request.paid') {
      const request = await paybytoken.paymentRequests.get(event.data.id)
      if (request.status === 'paid') {
        await transaction.receivables.markPaid(request.id)
      }
    }
  })
}

Use a decimal library when your accounting workflow also compares monetary fields; never use JavaScript floating-point arithmetic for those checks.

Review unapplied payments

const unapplied = await paybytoken.paymentRequests.listAllPayments({
  status: 'unapplied',
  limit: 50,
})

For each item, inspect its unapplied_reason, Payment Intent, request status, amount requested, amount received and amount already applied. Resolve it through an authorized accounting or support workflow. Do not mutate allocation tables or change a paid request back to open.

Check aggregate reconciliation

const report = await paybytoken.paymentRequests.reconciliation()

if (!report.reconciled) {
  alertOperations(report.mismatches)
}

Reconciliation reports drift; they do not automatically move money or rewrite request history. Persist the report time and affected request IDs, investigate the underlying payments and escalate before taking a compensating action.

Operational checks should alert on reconciliation mismatches, unapplied payments, and terminal delivery failures. The API reports these without mutating financial data automatically.

On this page

API Workbench

Full Explorer

Open in new tab