Use Case

Payment Gateway Monitoring: What Breaks When It's Not Stripe

11 min read

TL;DR: Payment gateway monitoring breaks the moment you copy a Stripe monitor onto something that is not Stripe, and that is the fastest way to get a false DOWN alert on PayPal or Square. Stripe uses a static secret key that never expires. PayPal and Square use OAuth bearer tokens that do, so a cloned monitor fires when its token lapses, not when the gateway is down. Adyen avoids that trap with API-key auth but hides its webhook signature in the JSON body instead of a header. This post is the per-vendor delta for PayPal, Square, and Adyen, the table of what actually differs, and how to build a token-refreshing monitor for free with no code. Start for free.

Square went dark for 15 hours and never called you

On September 7 2023, Square went down. The outage began at 1:54 PM ET and was not resolved until 5:19 AM ET the next morning, roughly 15 hours later. Square's own incident summary traces the root cause to a DNS failure: an unrelated change to host-based firewalls combined with a DNS service upgrade overloaded the internal DNS servers and knocked them over (Square's incident summary, 2023-09-07, verified 2026-06-02). For most of that window, sellers on Square Online could not process payments at all.

Here is the part that matters for you. Square has a status page. Square published a postmortem. Square told the world. What Square did not do, what no payment gateway does, is call you when your specific integration with it stops working. The status page tracks Square's platform. It does not track whether your token expired this morning, whether your webhook endpoint started returning 500 after last night's deploy, or whether the checkout SDK quietly fails to load for your customers in one region. That gap is yours to close, and it is the same on every gateway that is not Stripe.

Payment gateway monitoring with the Stripe playbook does not port

Most monitoring advice on the internet assumes Stripe. If you are on Stripe, that advice is good and you should follow it. See monitor its API health for the outbound side and monitoring Stripe webhooks for the inbound side. The problem starts when you copy that playbook onto PayPal, Square, or Adyen, because three structural things are different and each one breaks a copied monitor in a different way.

First, the auth model. Stripe authenticates with a static secret key that never expires. PayPal and Square authenticate with OAuth bearer tokens that do expire. Adyen uses an API key or basic auth. A monitor that pastes one fixed credential into a header works forever on Stripe and breaks on a schedule on PayPal and Square.

Second, the webhook signature mechanics. Stripe signs events one way, PayPal a second way with a set of headers and a verify endpoint, Square a third way with a single header, and Adyen a fourth way that is not a header at all. A handler or monitor written to read a signature header silently misses Adyen.

Third, the status-page machine-readability. Stripe and Square expose status JSON a monitor can fetch and assert on. PayPal exposes a custom endpoint with field names you should not assume. Adyen is page-only. So the easy assertion you wrote for Stripe is only portable to one of the three. The rest of this post is that table, then the fixes.

The per-vendor delta table

This is the centerpiece. Stripe is the baseline column. Read across any row to see exactly where a copied monitor will break for the gateway you are actually on.

DimensionStripe (baseline)PayPalSquareAdyen
Auth modelStatic secret key (no expiry)OAuth bearer (expires), POST /v1/oauth2/tokenOAuth bearer (expires), /oauth2/tokenAPI key / basic auth (no public OAuth token endpoint)
Token-trap riskNoneHIGHHIGHLOW
Webhook signatureSee how Stripe signs webhook eventsHeaders PAYPAL-TRANSMISSION-SIG / -ID / -TIME / -CERT-URL / -AUTH-ALGO (e.g. SHA256withRSA) plus verify endpointHeader x-square-hmacsha256-signature (HMAC-SHA-256)JSON field additionalData.hmacSignature (HMAC-SHA256 base64). Not a header.
Webhook retriesSee how Stripe retries failed deliveries~25 times over ~3 daysRetries with backoffRetries with backoff
Status JSON a monitor can assertSee the Stripe API health guideCustom /api/production (fields PayPal-specific, do not assume)/api/v2/status.json (Atlassian, assertable)Page only, no confirmed JSON
Sandbox / prod hostsn/a for this postapi-m.sandbox.paypal.com / api-m.paypal.comconnect.squareupsandbox.com / connect.squareup.comcheckout-test.adyen.com / {PREFIX}-checkout-live.adyenpayments.com

The expiring-token trap: why a copied Stripe monitor goes false-DOWN

This is the single most common false alert on non-Stripe gateways, so it gets its own section. A Stripe secret key never expires. You paste it into an Authorization header once and the monitor authenticates forever. So the natural thing to do when you move to PayPal or Square is the same thing: grab a token, paste it into the header, save the monitor.

It works. For a while. PayPal and Square access tokens are OAuth bearer tokens with a finite lifetime. The token you pasted in is already counting down. When it lapses, the gateway starts answering your monitor with a 401 Unauthorized. Your monitor reads a non-2xx response and flips to DOWN. PayPal is up. Square is up. Every other customer is checking out fine. The only thing that is down is your stale token, and your monitor has no way to tell the difference between "the gateway is unreachable" and "my credential expired."

Now you have the worst kind of monitor: one that cries wolf on a schedule. After the third or fourth 3 AM page that turned out to be nothing, the team mutes it. Then the gateway actually goes down and nobody is watching. A monitor that fires on its own expiring credential is worse than no monitor, because it trains you to ignore it.

Adyen is the contrast that proves the point. Adyen authenticates with an API key or basic auth and has no public OAuth token endpoint, so there is no short-lived bearer to go stale between runs. The expiring-token trap does not apply to Adyen the same way. You still rotate API keys deliberately, but a correctly configured Adyen monitor does not false-DOWN on a timer. The trap is specific to the OAuth gateways, which is exactly why the fix below is too.

The fix: refresh the token as step 1 of a multi-step monitor

The fix is to stop pasting a token and start minting one. Make the token refresh the first step of a multi-step monitor, then use the fresh token in the second step. The monitor mints a new bearer on every single run, so it never carries a stale one, and it can never false-DOWN because a credential lapsed between runs.

For PayPal, step 1 is a POST /v1/oauth2/token with your client credentials, which returns a fresh bearer. Step 2 calls the real endpoint you care about and sends that bearer in the Authorization header. For Square, step 1 is a POST to /oauth2/token to mint the bearer, step 2 uses it on the protected endpoint. In prose: step 1 posts the token endpoint and captures the bearer, step 2 GETs the protected route with it and asserts the status code is 200.

Why does the orderingmatter so much here, when it is irrelevant on Stripe? Because on Stripe step 1 would be busywork. The secret key is already valid, so a refresh step adds nothing. On an OAuth gateway the refresh step is the entire reason the monitor stays honest. It converts "is my pasted token still alive" into "can I get a token and use it right now," which is the question you actually want answered. The token lifetime stops mattering because you never reuse a token across runs.

This post owns only why that ordering matters for OAuth gateways. For the mechanics of building a multi-step monitor, capturing a value from step 1, and passing it into step 2, follow the multi-step API monitoring guide. The pattern is the same one used there; only the token endpoint and the protected route change per vendor.

Step 1 mints a fresh PayPal bearer and saves it as {{token}}; step 2 sends Authorization: Bearer {{token}} to a protected endpoint and asserts a 200. The monitor refreshes the token every run, so it never carries a stale one.
Velprove Create New Monitor wizard on the Configure step, building a two-step PayPal OAuth chain. Step 1 posts to https://api-m.paypal.com/v1/oauth2/token and a 'Save values from response' row captures the response field $.access_token into a variable named token. Step 2 sends a GET request to a protected PayPal endpoint with an Authorization header set to Bearer {{token}} and a Status Code Equals 200 success condition.

Monitoring the webhook leg

The inbound webhook leg fails the same way on every gateway: signature verification breaks, the endpoint times out, or deliveries get dropped at your edge. The generic pattern for catching that, a chained monitor that proves an event arrived and your handler moved real state, is the same idea regardless of vendor. We cover it in full in the end-to-end webhook delivery monitor walkthrough, and the structure ports cleanly. What does not port is the signature format, so that is all this section owns.

  • PayPal. PayPal does not use a single signature header. It sends a set: PAYPAL-TRANSMISSION-SIG, PAYPAL-TRANSMISSION-ID, PAYPAL-TRANSMISSION-TIME, PAYPAL-CERT-URL, and PAYPAL-AUTH-ALGO (for example SHA256withRSA). It also offers a verify-webhook-signature endpoint you can call to confirm a payload server-side. PayPal retries a failed delivery roughly 25 times over about 3 days, so a handler that is down for an hour still gets the event later, but a handler that is silently rejecting forever burns the whole window.
  • Square. Square uses one header, x-square-hmacsha256-signature, an HMAC-SHA-256 value. Closer to the Stripe shape, single header, but a different header name and a different signing input, so a copied Stripe verifier will not validate it as-is.
  • Adyen. Adyen is the one that breaks naive code. The HMAC is not in a header at all. It lives in the JSON body at notificationItems[].NotificationRequestItem.additionalData.hmacSignature, a base64 HMAC-SHA256 value. A handler or monitor that scans request headers for a signature finds nothing and either fails open or rejects everything. You have to read the body.

Status pages: which one a monitor can actually read

If a gateway exposes machine-readable status, you can add a cheap second signal: assert directly on its status feed. Only one of the three makes that easy.

Square runs an Atlassian Statuspage and exposes a clean JSON summary at issquareup.com/api/v2/status.json. A monitor can fetch it and assert on the documented Atlassian schema, which is the same shape across every Statuspage-hosted service. This is the one status feed in the group you can confidently assert on.

The Configure step of an API monitor pointed at Square's public Statuspage feed, https://www.issquareup.com/api/v2/status.json. This is the documented JSON feed Square publishes for polling, so it is the one Square-side signal a monitor can read directly.
Velprove Create New Monitor wizard on the Configure API Endpoint step, with the API URL field populated with Square's status feed at https://www.issquareup.com/api/v2/status.json, showing that the Square platform status feed is the endpoint being monitored.
Square's Atlassian status.json is the one payment-gateway status feed a monitor can assert on directly: a JSON Path condition on $.status.indicator equals none turns the documented Statuspage schema into a cheap platform-health signal.
Velprove Create New Monitor wizard on the Success Conditions step for an API monitor pointed at Square's status feed, with two conditions: Status Code Equals 200, and a JSON Path condition where path $.status.indicator Equals none, asserting the Statuspage indicator reports no active incident.

PayPal publishes a status page at paypal-status.com with a custom endpoint at /api/production. It exists, but the field names are PayPal-specific and not a documented contract, so do not write assertions against specific fields you have not verified will stay stable. Adyen publishes a status page at status.adyen.com but has no confirmed machine-readable endpoint, so treat it as page-only.

The practical rule: assert on Square's status JSON if you want a cheap platform-health signal, but for PayPal and Adyen do not lean on the status feed. Monitor your own integration path instead, the token refresh and the protected endpoint, because that is the signal that actually tells you whether your customers can pay. Deciding which third-party dependencies earn a monitor at all is its own triage, walked through in monitoring a third-party dependency you do not own.

Sandbox vs production: the base-host swap you will forget

Short gotcha, expensive when missed. All three gateways use a different base host for sandbox and production. Point a monitor at the sandbox host by accident and it reports green while production is on fire, because the sandbox really is up. Confirm the host before you save.

  • PayPal: api-m.sandbox.paypal.com (sandbox) versus api-m.paypal.com (production).
  • Square: connect.squareupsandbox.com (sandbox) versus connect.squareup.com (production).
  • Adyen: checkout-test.adyen.com (test) versus {PREFIX}-checkout-live.adyenpayments.com (live, where {PREFIX} is your account-specific live prefix).

The same swap shows up on the client side if you probe whether the checkout SDK loads. PayPal serves its JS SDK from https://www.paypal.com/sdk/js?client-id=..., which you probe with a GET using a valid client-id, not a bare URL. Square serves https://web.squarecdn.com/v1/square.js in production and https://sandbox.web.squarecdn.com/v1/square.js in sandbox. Adyen serves https://checkoutshopper-live.adyen.com/checkoutshopper/sdk/{VERSION}/adyen.js, where {VERSION} is the SDK version you have pinned.

How to do this in Velprove, free and no-code

Velprove is built for exactly this gap. The headline differentiator is the free, no-code browser login monitor: it opens a real browser, signs in to your own application with a dedicated test account, and confirms the signed-in path renders. If your checkout sits behind a customer login, that monitor proves a real user can actually reach it, with no code to write.

For the gateway calls themselves, the free plan includes multi-step API monitors of up to 3 steps, which is all the token-refresh pattern needs. Step 1 posts the OAuth token endpoint and captures the bearer, step 2 calls the protected endpoint with it and asserts the status code is 200. You can add a third step to assert on a read-back if you want to prove a real object exists. You pick which of 5 global regions each monitor runs from, on every plan. To catch a checkout SDK that fails to load in just one geography, deploy the same monitor in each region you care about. Each copy uses one of your monitor slots, and the region where the SDK breaks goes red while the others stay green. Commercial use is allowed on every plan including free, with no credit card.

One safety rule, the same on every gateway: use low-privilege test credentials against read paths, never a real admin key, and never run monitors that move real money. A monitoring credential that leaks should be able to read that a token can be minted and an endpoint responds, nothing more.

If your gateway sits inside a store rather than a raw API integration, the monitor you want is on the checkout flow, not the gateway endpoint. For WooCommerce see monitoring the WooCommerce checkout, and for Shopify see monitoring the Shopify checkout flow. Both drive the actual buy path a customer takes, which is the truest signal that payments work.

Set up a free, no-code payment gateway monitor with Velprove. Two steps, the region you choose, no credit card, commercial use allowed.

Frequently asked questions

Why does my PayPal monitor report DOWN when PayPal is actually up?

Almost always because the monitor is holding a stale OAuth bearer token. PayPal access tokens expire, unlike a Stripe secret key, which never does. If you copied a Stripe-style monitor that pastes one static token into a header, that token lapses after its lifetime and PayPal starts returning 401 Unauthorized. Your monitor reads the 401 as DOWN even though PayPal is serving every other customer fine. The fix is to mint a fresh token as step 1 of a multi-step monitor by posting to the OAuth token endpoint, then use that token in step 2. The monitor refreshes the token on every run, so it never carries a stale one.

Do Square and PayPal access tokens expire, and how often do I need to refresh them?

Yes, both PayPal and Square use OAuth bearer tokens that expire. The exact lifetime depends on your app and the grant type, and you should read the value the token endpoint returns rather than hardcode a number. The safe pattern for monitoring is to stop tracking the lifetime entirely: mint a fresh token at the start of every monitor run. Step 1 of a multi-step monitor posts to the token endpoint and captures the new bearer, step 2 uses it. Adyen is different. It authenticates with an API key or basic auth and has no public OAuth token endpoint, so the expiring-token trap does not apply the same way.

How is Adyen's webhook signature different from PayPal's or Square's?

Adyen puts its HMAC signature inside the JSON body, not in an HTTP header. You read it from notificationItems[].NotificationRequestItem.additionalData.hmacSignature, a base64 HMAC-SHA256 value. Square puts its signature in the x-square-hmacsha256-signature header. PayPal uses a set of headers, PAYPAL-TRANSMISSION-SIG, PAYPAL-TRANSMISSION-ID, PAYPAL-TRANSMISSION-TIME, PAYPAL-CERT-URL, and PAYPAL-AUTH-ALGO, and offers a verify-webhook-signature endpoint you can call to confirm a payload. So a monitor or handler written to read a signature header will silently miss Adyen entirely, because there is no signature header to read.

Which payment gateway has a status page my monitor can actually read?

Square is the clean one. It runs an Atlassian Statuspage and exposes a machine-readable summary at issquareup.com/api/v2/status.json that a monitor can fetch and assert on directly. PayPal publishes a status page at paypal-status.com with a custom endpoint at /api/production, but the field names are PayPal-specific and not a documented contract, so do not assume them. Adyen publishes a status page at status.adyen.com but has no confirmed machine-readable JSON endpoint, so treat it as page-only. For PayPal and Adyen the more reliable signal is to monitor your own integration path rather than parse their status feed.

Can I monitor PayPal, Square, or Adyen for free without writing code?

Yes. Velprove's free plan includes no-code browser login monitors and multi-step API monitors of up to 3 steps, and you pick which of 5 global regions each monitor runs from. For a gateway with an expiring token you build a 2-step API monitor in the wizard: step 1 posts to the OAuth token endpoint and captures the bearer, step 2 calls the protected endpoint with it and asserts the status code. No code, no credit card, and commercial use is allowed on every plan including free.

Will any of these gateways alert me when my integration breaks?

No. PayPal, Square, and Adyen publish status pages for their own platform health, but none of them watches your specific integration and none of them emails you when your token expired, your webhook endpoint started returning 500, or your checkout SDK stopped loading in one region. Their status page stays green because their platform is fine. Your integration is the part that broke, and only a monitor pointed at your own path catches it. That is the entire reason to run external functional monitoring on a gateway you do not own.

Should I monitor the sandbox or production host?

Monitor production, because that is the host your customers pay through. The trap is that PayPal, Square, and Adyen all use different base hosts for sandbox and production, and a monitor accidentally pointed at the sandbox host will report green while production is on fire. PayPal production is api-m.paypal.com versus api-m.sandbox.paypal.com. Square production is connect.squareup.com versus connect.squareupsandbox.com. Adyen production is your prefixed live host versus checkout-test.adyen.com. Use low-privilege test credentials against production read paths, never a real admin key, and confirm the base host before you save the monitor.

Start monitoring for free

Free browser login monitors. Multi-step API chains. No credit card required.

Start for free