NextRouteNextRoute

Webhooks

Webhook integrations — Stripe payment events, Twilio SMS delivery, and Sendro email tracking with signature verification.

Webhooks

NextRoute processes incoming webhooks from three external services: Stripe (payments), Twilio (SMS delivery), and Sendro (email delivery). These webhooks keep your data in sync with external payment and communication platforms.

Stripe Webhooks

Endpoint

POST https://api.nextroute.app/api/webhooks/stripe

This endpoint receives events from Stripe and processes them to update invoice statuses, create payment records, manage subscriptions, and handle refunds.

Signature Verification

Every Stripe webhook is verified using the Stripe-Signature header and your STRIPE_WEBHOOK_SECRET. If the signature is invalid or missing, the request is rejected with a 400 status.

Configure the webhook secret in your environment:

STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxx

Supported Events

EventAction
invoice.paidMarks the matching invoice as paid, creates a payment record
invoice.payment_failedMarks the matching invoice as overdue
payment_intent.succeededMarks invoice as paid, creates payment record with card details
payment_intent.payment_failedUpdates payment record status to failed
customer.subscription.updatedUpdates tenant subscription status and customer billing status
customer.subscription.deletedSets tenant and customer status to canceled
checkout.session.completedLinks the Stripe subscription to the tenant after checkout
setup_intent.succeededSaves the payment method (card brand, last4, expiry) to the customer
charge.refundedUpdates payment status to refunded or partially_refunded, updates invoice if fully refunded

Event Processing Details

invoice.paid

When Stripe confirms an invoice is paid:

  1. The matching NextRoute invoice is looked up by stripe_payment_intent_id
  2. The invoice status is set to paid and paid_at is recorded
  3. A payment record is created with the Stripe payment intent ID
  4. Card details (brand, last4) and receipt URL are saved if available
  5. Duplicate payments are prevented by checking for existing records

payment_intent.succeeded

For direct payment intents (e.g., Tap to Pay):

  1. The invoice is looked up by stripe_payment_intent_id
  2. Card details are extracted from the charge object
  3. Payment method type is determined (tap_to_pay for card-present, stripe_online otherwise)
  4. If no matching invoice is found, the system falls back to matching by stripe_customer_id

setup_intent.succeeded

When a customer saves a payment method:

  1. The payment method details are fetched from Stripe
  2. Card brand, last4, and expiry are stored in customer_payment_method
  3. If this is the customer's first payment method, it is automatically set as default

charge.refunded

Handles both full and partial refunds:

  • Full refund (refunded amount >= total): payment status = refunded, invoice status = refunded
  • Partial refund: payment status = partially_refunded, refund amount is recorded

Configuring Stripe Webhooks

In your Stripe Dashboard:

  1. Go to Developers > Webhooks
  2. Click Add endpoint
  3. Set the URL to https://api.nextroute.app/api/webhooks/stripe
  4. Select the events listed above
  5. Copy the Signing secret and set it as STRIPE_WEBHOOK_SECRET

Twilio Webhooks (SMS Delivery)

Endpoint

POST https://api.nextroute.app/api/webhooks/twilio

Receives SMS delivery status updates from Twilio and maps them to NextRoute communication log statuses.

Status Mapping

Twilio StatusNextRoute Status
queuedpending
sendingpending
sentsent
delivereddelivered
failedfailed
undeliveredfailed

The webhook matches messages using the MessageSid (or SmsSid) field and updates the corresponding communication_log record.

Configuring Twilio Webhooks

In your Twilio Console:

  1. Go to Phone Numbers > Active Numbers
  2. Select your number
  3. Under Messaging, set the status callback URL to https://api.nextroute.app/api/webhooks/twilio

Sendro Webhooks (Email Delivery)

Endpoint

POST https://api.nextroute.app/api/webhooks/sendro

Receives email delivery status updates from Sendro and updates communication log records.

Signature Verification

Sendro webhooks are verified using HMAC-SHA256. The raw request body is signed with your SENDRO_WEBHOOK_SECRET, and the result is compared against the X-Webhook-Signature header.

The expected signature format is:

v1=<hex-encoded HMAC-SHA256>

Configure the secret in your environment:

SENDRO_WEBHOOK_SECRET=your_sendro_webhook_secret

Supported Events

Sendro EventNextRoute Status
email.delivereddelivered
email.bouncedbounced
email.failedfailed
email.openedopened
email.complainedcomplained

Payload Format

{
  "type": "email.delivered",
  "emailId": "msg_abc123"
}

The emailId is matched against the external_id field in the communication_log table.

Security Best Practices

  1. Always verify signatures — never process webhooks without verifying the signature. All three webhook endpoints enforce verification.
  2. Use HTTPS — webhook URLs must use HTTPS to prevent man-in-the-middle attacks.
  3. Idempotency — webhook handlers check for existing records before creating duplicates. Events may be delivered more than once.
  4. Return 200 quickly — all webhook handlers return a 200 status to acknowledge receipt, even if downstream processing encounters errors. This prevents unnecessary retries.

Retry Behavior

ServiceRetry policy
StripeRetries up to 3 days with exponential backoff
TwilioSingle delivery attempt
SendroConfigurable in Sendro dashboard