invoicePostedEvent
Webhook

Invoice posted

​

Fires when an invoice is posted to your customer: when the billing run posts an invoice for an order that posts its invoices automatically (autoPostInvoices), when a draft is posted in the dashboard, or when Stripe finalises an invoice it issued for a subscription. From then on it can be paid and payments can be allocated to its lines, and credits the order grants on posting become available. data.invoice is the invoice, as Get an invoice returns it, with status: posted and its postedDate. An invoice handed to Stripe to collect is announced once Stripe has it, so its paymentLink is Stripe's hosted page.

Headers

  • t=<timestamp>,s=<signature>. t is when the delivery was signed, in Unix milliseconds; each attempt is signed afresh, so a retry has a new t. s is the Base64 (standard alphabet, padded) HMAC-SHA256 of the string <t>.<raw request body>, keyed with your signing secret: the whole whsec_… string as UTF-8. To verify, recompute it over the raw body exactly as received and compare in constant time, then reject a t too far from now (5 minutes is a good limit) so an old delivery can't be replayed. s can end in =, so split each part on its first = only.

Body

required
application/json

Every delivery's body.

Responses

  • Return any 2xx to acknowledge. Any other status, a redirect (redirects aren't followed), or no answer within 5 seconds is a failed attempt, recorded in the webhook's lastStatus. A failed delivery is retried 1 minute, 5 minutes, 30 minutes, 2 hours and then 12 hours after each failed attempt in turn (retries are sent by a sweep that runs every minute, so each can be up to a minute later), and dropped after the sixth failed attempt. A retry carries the same id and timestamp and goes to the webhook's current URL; a delivery whose webhook has since been switched off is dropped. Because of retries, an event can arrive more than once or after a later one: use id to ignore repeats. The response body is ignored.

Request Example for postbilling-invoice-posted
{
  "id": "whd_Bc7Yw2Ln5Hq9Jd3F",
  "event": "billing-invoice-posted",
  "timestamp": "2026-11-01T00:00:04.217Z",
  "isTest": false,
  "data": {
    "invoice": {
      "id": "inv_3Rk8Wq1Zp6Ty0Xm2",
      "displayNumber": "INV-1007",
      "orderId": "ord_8Jt3Vw0Ym5Ln2Qp7",
      "customerId": "cus_Q2x9vB7mK4pT1sLw",
      "status": "posted",
      "paymentStatus": "pending",
      "source": "order_based",
      "startDate": "2026-10-01T00:00:00.000Z",
      "endDate": "2026-11-01T00:00:00.000Z",
      "issueDate": "2026-11-01T00:00:00.000Z",
      "postedDate": "2026-11-01T00:00:04.198Z",
      "dueDate": "2026-11-15T00:00:04.198Z",
      "currency": "USD",
      "taxAmount": 888,
      "taxRate": 0.08,
      "taxStatus": "committed",
      "invoiceTotalExcludingTax": 11100,
      "invoiceTotal": 11988,
      "amountDue": 11988,
      "amountPaid": 0,
      "amountRemaining": 11988,
      "creditNotesTotal": 0,
      "metadata": null,
      "createdAt": "2026-11-01T00:00:00.000Z",
      "updatedAt": "2026-11-01T00:00:04.198Z",
      "paymentLink": "https://billing.getspondo.com/public/invoices/5c1e9a7b3d2f4e60_kV9xQ2mL7pR4tW8yZ1nC6bD3",
      "disputeLink": null,
      "publicUrlToken": "5c1e9a7b3d2f4e60_kV9xQ2mL7pR4tW8yZ1nC6bD3",
      "taxExempt": false,
      "billingContactId": "con_5Tg8Kd2Wq7Lm4Rx1",
      "purchaseOrderReference": null
    }
  }
}
No Body