API and Webhook Integration Basics for SaaS Builders
Most SaaS products are integrations — they send and receive data from external systems via APIs and webhooks. This guide covers the two fundamental patterns (request-response and event-driven), explains how to debug both when they fail, and introduces the tools that make integration work faster.
TL;DR
- • APIs are request-response: your code asks, the server answers.
- • Webhooks are event-driven: the server pushes data to your endpoint when something happens.
- • Most integration bugs are payload parsing errors, missing headers, or misconfigured endpoints.
- • Debug by capturing the raw request first, then writing the handler.
- • Use the Webhook Tester to receive and inspect webhooks before you write a single line of handler code.
1. What APIs and Webhooks Are
An API (Application Programming Interface) is a structured contract that lets two systems communicate. In web integrations, this almost always means HTTP-based APIs: your application sends an HTTP request (GET, POST, PUT, DELETE) to a remote server, and the server sends back a response — typically JSON.
A webhook is an HTTP callback: instead of your system asking for data, the remote system sends data to you. You register a URL (your endpoint), and when an event occurs in the remote system, it sends an HTTP POST to that URL with the event payload in the body.
| Concept | Direction | Triggered by | Typical use |
|---|---|---|---|
| API call | You → them | Your code | Fetch data, create resources, query state |
| Webhook | Them → you | Remote event | Payment completed, order shipped, user signed up |
2. Request-Response vs Event-Driven Systems
Request-response is the older and simpler pattern. Your code controls when data is fetched. This works well for on-demand queries (look up a user, create a record, check a status). The downside: if you need to know when something changes, you have to keep asking — a technique called polling.
Event-driven (webhooks) inverts this: the data finds you. When a payment completes in Stripe, Stripe sends a payment_intent.succeeded event to your registered endpoint. No polling, no delay.
Most modern SaaS products use both: APIs for querying and creating resources, webhooks for receiving real-time notifications. See Webhooks vs Polling for a detailed comparison.
3. Typical Integration Workflows
API integration flow
- Obtain credentials (API key, OAuth token, client secret).
- Construct the request — set the method, URL, headers (Authorization, Content-Type), and body.
- Send the request; check the HTTP status code (200, 201, 400, 401, 403, 404, 429, 500).
- Parse the response body — usually JSON.
- Handle errors and retry logic (check for
Retry-Afterheaders on 429).
Webhook integration flow
- Register your endpoint URL in the provider's dashboard.
- Receive the POST request at your endpoint — return a
200 OKimmediately. - Verify the webhook signature (HMAC-SHA256 or similar) to confirm authenticity.
- Parse the event type and route to the appropriate handler.
- Process asynchronously — do not block the HTTP response with slow operations.
4. Debugging API Calls
When an API call fails, start with the response body — not the status code. Status codes tell you the category of error; the body tells you what went wrong.
Common causes by status code:
| Status | Meaning | Check first |
|---|---|---|
| 400 | Bad Request | Request body / query params format |
| 401 | Unauthorized | Authorization header — token present and valid? |
| 403 | Forbidden | Scopes / permissions — does the token have access? |
| 404 | Not Found | URL path — typo, wrong version, resource deleted? |
| 422 | Unprocessable | Business logic validation — read the error field in body |
| 429 | Rate Limited | Retry-After header; implement exponential backoff |
| 500 | Server Error | Provider-side issue; check their status page |
Use the API Response Formatter to pretty-print and inspect the raw response body — especially useful for large or nested JSON error objects.
5. Debugging Webhook Payloads
The hardest part of webhook development is that the sender controls the payload — you can't easily reproduce it locally. The safest workflow:
- 1.Capture the raw request first. Use the Webhook Tester to receive the live event from the provider. This shows you the exact headers, method, and body before you write any handler code.
- 2.Check the signature header. Stripe sends
Stripe-Signature; GitHub sendsX-Hub-Signature-256. These are HMAC-SHA256 hashes of the raw body using your webhook secret. Verify before trusting the payload. - 3.Return 200 immediately. Most providers retry if your endpoint doesn't respond within a few seconds. Offload heavy processing to a queue.
- 4.Handle duplicates. Webhooks can arrive more than once (network retries). Use the event ID to deduplicate: store seen IDs and skip processing if the ID has already been handled.
Never trust a webhook without verifying its signature. Anyone can send a POST to your public endpoint. Always validate the HMAC signature using the raw request body (before parsing) and your shared secret.
6. Common Integration Mistakes
Parsing the body before verifying the signature
Signature verification must use the raw bytes of the request body — not the parsed JSON. Parsing first may alter whitespace or key ordering, breaking the HMAC comparison.
Not returning 200 quickly enough
If your webhook handler takes more than 5–10 seconds (provider-dependent), the provider marks the delivery as failed and retries. Move slow operations (database writes, email sends) to an async queue.
Missing the Content-Type header on API requests
Many APIs reject POST requests without Content-Type: application/json. Use the Cookie Parser and Query String Parser to inspect request components when debugging unexpected 400 errors.
Ignoring retry logic
On 429 Too Many Requests, check the Retry-After header and implement exponential backoff. Retrying immediately worsens rate-limit situations.
Storing webhook payloads synchronously
If your database is slow or down when a webhook arrives, your endpoint returns a 500, the provider retries, and you end up with duplicates. Use an idempotency key (the event ID) and process asynchronously.
Try the Tools
These tools accelerate the debugging workflows described in this guide — all free and browser-based.
API Request Builder
Build and send HTTP requests with custom headers, params, and body. Copy the equivalent cURL command for terminal use.
Webhook Tester
Generate a unique URL and receive live webhook payloads. Inspect headers, method, and body before writing your handler.
API Response Formatter
Pretty-print and inspect raw API responses. Supports JSON, XML, and plain text.
Query String Parser
Decode URL query parameters from a full URL or raw query string.
Cookie Parser
Parse Cookie or Set-Cookie headers into structured fields with attribute analysis.
FAQ
What is the difference between an API and a webhook?
An API call is initiated by your code — you ask, they answer. A webhook is initiated by the remote system — an event happens, they tell you. APIs are synchronous and on-demand; webhooks are asynchronous and event-driven.
How do I receive webhooks during local development?
Use the Webhook Tester to capture and inspect the payload structure first. For local handler testing, tools like ngrok or Cloudflare Tunnel expose your local server to the public internet, allowing real webhooks to reach your dev machine.
How do I verify a webhook signature?
Compute HMAC-SHA256 of the raw request body using your webhook secret as the key. Compare the result (hex-encoded) to the value in the signature header. If they match, the payload is authentic. Never verify on the parsed body — parsing can alter bytes.
What should my webhook endpoint return?
Return HTTP 200 (or 201/204) as quickly as possible — ideally within 3 seconds. If the provider gets no response, it retries. Do not run slow operations (database inserts, email sends, API calls) synchronously in the webhook handler.
What is idempotency and why does it matter for webhooks?
Idempotency means processing the same event multiple times produces the same result as processing it once. Webhooks can arrive more than once (due to retries). Check the event ID against a store of already-processed IDs and skip if the event has been handled before.
How do I debug a webhook that is failing silently?
Use the Webhook Tester to confirm the payload is reaching an endpoint correctly. Check the provider's webhook delivery logs (most providers like Stripe and GitHub show delivery attempts and response codes). Then inspect the request headers and body with the tools on this page.