---
name: webhookjar
description: Catch and inspect webhooks with Webhook Jar (webhookjar.com). Use when testing or debugging a webhook integration: open an inbox, point a service at its URL, wait for the request, then read its headers, body and signature check, or replay it to your own server.
---

# Webhook Jar

Webhook Jar gives you private inboxes that catch HTTP requests. Point any service that sends webhooks (Stripe, GitHub, Shopify, Slack, OpenAI and anything else that makes an HTTP request) at an inbox's post URL, and every request is kept with its headers, raw body, sender, event name and signature check.

## When to use it

- You are building or fixing code that receives webhooks and need to see exactly what a provider sends.
- A test needs to wait for a webhook and assert on it (CI included).
- You want to check a signing secret: the inbox verifies each request the way a handler would.
- You want to resend a captured request to your own server after changing your handler (replay, Solo plan).

Not for: hosting a production webhook endpoint, or storing data you must keep. History is kept for the plan's days, then deleted.

## Getting access

- Sign in with Google at https://webhookjar.com/login. A Free account comes with an API key at https://webhookjar.com/account/api.
- Send the key on every API call as `Authorization: Bearer wj_live_...` (or `X-API-Key: wj_live_...`). Never put a key in front-end code or in a reply to the user.
- Without an account, a person can still open a temporary inbox from https://webhookjar.com in one click; the API needs a key.

## MCP server

- URL: `https://webhookjar.com/mcp` (Streamable HTTP, JSON-RPC). Send the key as the `Authorization: Bearer wj_live_...` header.
- Claude Code: `claude mcp add --transport http webhookjar https://webhookjar.com/mcp --header "Authorization: Bearer wj_live_..."`
- Tools: `create_inbox`, `list_inboxes`, `get_inbox`, `send_sample`, `wait_for_request`, `list_requests`, `get_request`, `set_inbox_answer`, `set_forwarding` (Solo), `replay_request` (Solo), `delete_inbox`, `get_usage`.
- A refused call comes back as a tool result with `isError` and the reason (`no_key`, `plan`, `not_found`, `slow_down`).

## The API

Base URL `https://webhookjar.com/v1`. JSON in and out. Times are UTC, ISO 8601. Ids: `ib_...` for an inbox, `rq_...` for a request; treat them as opaque.

Open an inbox:

```
curl -s -X POST https://webhookjar.com/v1/inboxes \
  -H "Authorization: Bearer $WJ_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Stripe test"}'
```
```json
{"id": "ib_8k2m", "name": "Stripe test", "post_url": "https://webhookjar.com/in/p3jd9xq7wlm2",
 "view_url": "https://webhookjar.com/inbox/hq81czt0v4", "kept": true, "requests": 0}
```

Wait for the next request (holds up to 25 seconds; 204 when nothing came):

```
curl -s "https://webhookjar.com/v1/inboxes/ib_8k2m/next?wait=25" -H "Authorization: Bearer $WJ_KEY"
```
```json
{"id": "rq_91fd2", "method": "POST", "provider": "stripe", "event": "invoice.paid",
 "headers": {"stripe-signature": "t=1790690728,v1=5257a8..."}, "body": "{\"id\":\"evt_1Q2w\",...}",
 "body_encoding": "utf8", "signature": "verified", "checks": [{"state": "ok", "title": "Signature verified"}]}
```

Other calls:

- `GET /v1/inboxes` lists open inboxes; `GET /v1/inboxes/{id}` gets one.
- `GET /v1/inboxes/{id}/requests?limit=50&before=rq_...&provider=stripe` lists requests without bodies, newest first.
- `GET /v1/requests/{id}` gets one request in full; `DELETE` removes it.
- `PATCH /v1/inboxes/{id}` with `name`, `answer` (`status`, `body`, `delay`, `challenges`) or `forward` (`url`, `on`, Solo).
- `POST /v1/requests/{id}/replay` sends it to the forward URL again and returns your server's answer (Solo).
- `POST /v1/inboxes/{id}/samples` with `{"provider": "stripe", "event": "invoice.paid"}` delivers a real provider webhook into the inbox (headers, body and signature as the provider sends them, marked `sample: true`). `GET /v1/samples` lists them: GitHub (push, pull_request.opened, issues.opened, workflow_run.completed, release.published, ping), Stripe (checkout.session.completed, invoice.paid, invoice.payment_failed, customer.subscription.deleted, charge.refunded, payment_intent.succeeded), Shopify (orders/create, orders/paid, customers/create), Slack (app_mention, message.channels, reaction_added, member_joined_channel, slash_command, block_actions), Twilio (message.received, message.delivered, message.undelivered, call.completed), SendGrid (delivered, open, bounce, batch) and OpenAI as `standard` (response.completed, batch.completed, fine_tuning.job.succeeded).
- `DELETE /v1/inboxes/{id}` deletes the inbox and its requests.
- `GET /v1/usage` returns the plan, today's calls and limits.

## Signature checks

Add a signing secret to an inbox in its settings and each request is checked: Stripe, GitHub, Shopify, Slack (v0), Twilio, SendGrid (signed Event Webhook), Paddle and Standard Webhooks (OpenAI, Anthropic, Google Gemini, Supabase and every Svix sender). `signature` is `verified`, `failed`, or `null` when no secret is set. The checks also say how long after signing it arrived and whether the event id was seen before.

## Limits

- Without an account: an inbox lasts 48 hours and takes 500 requests.
- Free: 3 inboxes, 7 days of history, 5,000 requests a day, 1 API key, 1,000 API calls a day, 30 a minute.
- Solo ($9 a month): 25 inboxes, 90 days of history, 50,000 requests a day, forwarding and replay, 5 keys, 25,000 calls a day, 300 a minute.
- Request bodies are kept up to 1 MB. Calls are counted per account across all keys; the day resets at 00:00 UTC.

## Errors

Every non-2xx answer is `{"error": {"code": "...", "message": "..."}}`.

- `400 bad_request`: a parameter or the body is wrong; the message names it. Do not retry unchanged.
- `401 no_key`: no key, or a rolled or revoked one.
- `403 plan`: Solo only (replay, forwarding), or the plan's inboxes are all in use. Delete one or upgrade.
- `404 not_found`: no such inbox or request on this account.
- `429 slow_down`: over a limit. Wait the `Retry-After` seconds.
- `500 server`: retry after 1, 2, then 4 seconds; stop after 3 tries.

## A typical agent workflow

1. `create_inbox` (or `POST /v1/inboxes`) and keep its `id` and `post_url`.
2. Give the `post_url` to the service and trigger the event. With no provider account to hand, `send_sample` delivers a real one instead (signed with the inbox's own secret for that provider when one is set, so the user's verification code can be tested).
3. `wait_for_request` with the inbox id; on "nothing arrived", call again with `after` set to the last request id you saw.
4. Read the request: check `event`, the body fields your code needs, and `signature`.
5. If the user's handler failed, change it, then `replay_request` (Solo) to send the same request again.
6. `delete_inbox` when the test is done, so the plan's inboxes stay free.

Full reference in Markdown: https://webhookjar.com/llms.txt. Operated by DeveloperData.net.
