/ Use case

Payment API Monitoring

The endpoint returned 200. The charge never landed.

Payment API Monitoring

A broken payment endpoint costs you money from the first failed request. Assert checks your gateway and your own payment endpoints on the same schedule, and reads the response body instead of the status line.

The Problem

The gateway returns 200 and the transaction fails anyway. One card type stops working while every other method goes through. Your provider has an incident and your checkout inherits it. Or your own validation starts rejecting requests that were fine yesterday.

How Assert Helps

Monitor Payment Gateway Health

Check that your payment provider is operational:

Monitor: Stripe Health Check
URL: POST https://api.stripe.com/v1/payment_methods
Assertions:
  ✓ Status code == 200
  ✓ $.object == "payment_method"
  ✓ Response time < 2000ms

Validate Your Payment Integration

Then the endpoints you wrote yourself:

Monitor: Checkout Payment Validation
URL: POST /api/payments/validate
Body: {"amount": 100, "currency": "USD", "method": "card"}
Assertions:
  ✓ $.valid == true
  ✓ $.available_methods contains "card"
  ✓ $.min_amount <= 100

Check Webhook Endpoints

Verify your webhook handlers are responding:

Monitor: Payment Webhook Health
URL: POST /webhooks/stripe
Assertions:
  ✓ Status code == 200
  ✓ Response time < 500ms

Critical Assertions for Payment APIs

Transaction Creation

// Expected response from payment creation:
{
  "id": "txn_abc123",
  "status": "pending",
  "amount": 9999,
  "currency": "usd"
}

Assertions:

  • $.id must exist
  • $.status must be one of ["pending", "succeeded", "processing"]
  • $.amount must equal expected amount
  • $.currency must equal expected currency

Payment Status

// Expected response from status check:
{
  "status": "succeeded",
  "paid": true,
  "receipt_url": "https://..."
}

Assertions:

  • $.status must exist
  • $.paid must be boolean
  • $.receipt_url must match URL pattern

Refund Processing

// Expected refund response:
{
  "id": "re_xyz789",
  "status": "succeeded",
  "amount": 5000
}

Assertions:

  • $.status must equal "succeeded"
  • $.amount must be positive integer
  • $.id must start with "re_"

Real-World Example

The Scenario

A SaaS company bills subscriptions through Stripe. Some webhook deliveries never arrive, so the renewal never gets recorded, and the customer wakes up downgraded.

The Assert Solution

Monitor 1: Stripe Webhook Endpoint

URL: POST /webhooks/stripe
Headers:
  Stripe-Signature: test_signature
Body: {"type": "test"}
Assertions:
  ✓ Status code == 200 or 400
  ✓ Response time < 1000ms

Monitor 2: Subscription Status API

URL: GET /api/subscriptions/health
Assertions:
  ✓ $.queue_size < 100
  ✓ $.last_processed within 5 minutes
  ✓ $.error_rate < 0.01

The Outcome

The endpoint monitor ran every minute while the health monitor watched the queue. Queue size crossed the threshold and Assert alerted once, with the failing response attached. The team traced it to a Redis connection issue and fixed it before a single renewal was missed. Both monitors are still running.

Payment Providers to Monitor

Stripe

Endpoint What to Monitor
Payment Intents Transaction creation works
Payment Methods Card tokenization succeeds
Webhooks Events are delivered
Customers Customer creation works

PayPal

Endpoint What to Monitor
Orders Order creation succeeds
Captures Payment capture works
Refunds Refund processing
Webhooks Event delivery

Your Payment Endpoints

Endpoint What to Monitor
POST /checkout Cart to payment works
POST /payments Payment processing
GET /payments/:id Status retrieval
POST /refunds Refund processing

Best Practices

Use Test/Sandbox Endpoints

Most payment providers offer test endpoints:

Production: api.stripe.com
Sandbox: api.stripe.com (with test keys)

Monitor both. Sandbox tells you your integration still works; production tells you about the failures that only happen with live keys.

Monitor from Multiple Regions

Payment latency matters globally:

US East:    Monitor latency to Stripe US
Europe:     Monitor latency to Stripe EU
Asia:       Monitor latency to Stripe APAC

Assert runs each check from six regions and needs them to agree before it alerts, so one slow route to Frankfurt doesn't wake anybody up.

Set Aggressive Alert Thresholds

For payment APIs, detect issues fast:

  • Check interval: 30 seconds, which every plan allows
  • Alert threshold: one or two failures, not three to five
  • Response time: alert above 3 seconds

Create Payment-Specific Alerts

Route payment alerts to specialized channels:

Payment API Down → PagerDuty (immediate page)
Payment Slow → Slack #payments (warning)
Webhook Queue Growing → Email (monitor)

Test Edge Cases

Monitor for specific scenarios:

  • Zero amount: free trials and $0 checkouts
  • Large amounts: high-value transactions
  • Currency handling: multi-currency support
  • Declined cards: the error your customer actually sees

Alert Response Runbook

When payment alerts fire:

  1. Check the provider's status page. Is this Stripe's problem or yours?
  2. Check your logs for a deploy or an error spike in the last hour.
  3. Run a test payment by hand. Does it go through?
  4. Check the dependencies: database, Redis, webhook handlers.
  5. Open a ticket with the provider if it's on their side.

Getting Started

Start with the flows that move money: checkout, subscription renewal, refunds. Map the endpoints on both sides, yours and your provider's. Build the first monitor around transaction creation, assert on the fields in the response rather than the status code, and send it to PagerDuty. Everything else can go to Slack.

Related Use Cases

Write your first assertion.

Five monitors, thirty-second checks, no card, no call.