Skip to main content
Kibble gives you three ways to track whether a payment link or invoice has been paid. You can check the merchant portal for a visual overview, poll the status API from your own code, or configure a webhook to receive a push notification the moment a payment is confirmed on-chain.

Payment and invoice statuses

Before diving into each method, here is what each status value means:

Payment statuses

StatusMeaning
pendingNo payment received yet
confirmedExact amount received and confirmed on Base
partialA payment arrived but it is below the expected amount
excessA payment arrived that exceeds the expected amount

Invoice statuses

StatusMeaning
draftInvoice created but not yet sent to the vendor
sentInvoice emailed to the vendor, awaiting payment
paidFull payment received (maps to confirmed payment)
partialPartial payment received
excessOverpayment received
GET /api/invoices/{id}/status also returns overdue as a derived status when the invoice is in draft or sent state and the due date has passed.

Option 1: merchant portal

The merchant portal gives you a real-time visual view of your payment links. Access it at:
https://pay.kibble.sh/merchant/{slug}
Replace {slug} with the slug returned when you created the payment link. The portal is available for payment links created with the privy wallet type and shows the current payment status, received amount, and transaction details.

Option 2: status polling API

Poll the status endpoints directly from your application. Both endpoints return lightweight JSON responses with no authentication required.
GET /api/payments/status/{slug}
curl https://pay.kibble.sh/api/payments/status/abc12345
Example response when paid:
{
  "status": "confirmed",
  "tx_hash": "0xabc123...",
  "amount_usdc": "150.00",
  "confirmed_at": "2026-04-28T14:23:01.000Z"
}
Example response when still pending:
{
  "status": "pending"
}

Invoice status

GET /api/invoices/{id}/status
curl https://pay.kibble.sh/api/invoices/a1b2c3d4-e5f6-7890-abcd-ef1234567890/status
Example response:
{
  "status": "paid",
  "paid_amount": "2500.0",
  "tx_hash": "0xdef456...",
  "paid_at": "2026-04-28T15:00:00.000Z"
}

Polling from your application

A simple polling loop in JavaScript:
async function waitForPayment(slug: string, intervalMs = 5000): Promise<void> {
  while (true) {
    const res = await fetch(`https://pay.kibble.sh/api/payments/status/${slug}`);
    const data = await res.json();

    if (data.status === "confirmed" || data.status === "excess") {
      console.log("Payment confirmed:", data.tx_hash);
      break;
    }
    if (data.status === "partial") {
      console.warn("Partial payment received:", data.amount_usdc);
    }

    await new Promise((resolve) => setTimeout(resolve, intervalMs));
  }
}
The hosted checkout and invoice pages poll GET /api/payments/status/{slug} automatically every five seconds. You only need to implement your own polling if you are tracking payments server-side or in a custom UI.

Option 3: webhooks

Webhooks are the most efficient way to track payments if you have a server that can receive HTTP requests. Instead of polling, Kibble POSTs to your endpoint the moment an invoice payment is confirmed — no repeated API calls needed. Configure a webhook by passing webhook_url when you create an invoice. See Webhooks overview for setup instructions and Webhook verification to learn how to validate incoming requests.

Choosing the right approach

ApproachBest for
Merchant portalManual monitoring, quick spot checks
Status pollingCustom checkout UIs, frontend status displays
WebhooksServer-side automation, fulfillment triggers, database updates
You can combine all three — for example, use a webhook for server-side processing and display polling-based status updates in your checkout UI.
Only USDC on Base (chain ID 8453) triggers a status change. Transfers of other tokens to the deposit address are silently ignored and will not change the payment or invoice status.