Skip to main content

When it fires

When a past_due or pending subscriber does not pay their invoice before the grace period ends. Settlx transitions the subscriber to expired and fires this event. The subscriber cannot be reactivated automatically. To reinstate them, you must re-enroll them into the plan.

What to do

Revoke access to your product here.
  • Downgrade or disable the customer’s account
  • Send a “subscription expired” email with a resubscribe link
  • Archive their session or active resources if applicable
subscriber.expired is the definitive signal that access must end. Do not wait for a manual action — revoke access in this handler.

Payload

{
  "event": "subscriber.expired",
  "subscriberId": "9f1e2d3c-4b5a-6789-abcd-ef0123456789",
  "merchantId": "f9e8d7c6-b5a4-3210-9876-543210fedcba",
  "planId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "email": "customer@example.com",
  "status": "expired",
  "currentPeriodEnd": "2026-06-19T00:00:00.000Z",
  "timestamp": "2026-05-26T00:00:01.000Z"
}
FieldTypeDescription
eventstringAlways subscriber.expired
subscriberIdstringUUID of the subscriber record
merchantIdstringYour merchant account UUID
planIdstringUUID of the plan
emailstringSubscriber email address
statusstringAlways expired
currentPeriodEndstringISO 8601 — the period that was not renewed
timestampstringISO 8601 — when the event was generated

Handler example

Node.js
app.post('/webhooks/settlx', express.raw({ type: 'application/json' }), async (req, res) => {
  verifySignature(req); // see Webhook Integration for verification code

  const event = JSON.parse(req.body);

  if (event.event === 'subscriber.expired') {
    const { subscriberId, email, planId } = event;

    // Revoke product access
    await db.subscriptions.update(subscriberId, { status: 'expired' });
    await revokeAccess(email);

    // Notify customer with resubscribe link
    await sendEmail(email, 'subscription-expired', {
      resubscribeUrl: `https://yourapp.com/plans/${planId}`,
    });
  }

  res.status(200).json({ received: true });
});