Webhook operations, with a way forward

Your webhooks deserve a second chance.

Receive, inspect, and recover the webhooks your application depends on. Keep the original payload, understand each failed delivery, and replay when your handler is ready.

Free for 15,000 events a month, no card. Paid plans start at $20.

POST https://hooks.shellorbit.com/e/{ingest_key}

202 Accepted, stored before the reply

Verifies signatures from

  • Stripe
  • GitHub
  • Shopify
  • Paddle
  • Clerk
  • Resend
  • Svix
  • Dodo Payments
and any Standard Webhooks sender →

An event. Every attempt. One clear trail.

See the story behind each delivery.

Inspect what arrived, follow each retry, and recover with confidence when your handler is ready.

Explore the event log →
Inbound endpoint hooks.shellorbit.com/e/whk_example
Example webhook delivery history
SourceEventStateAttempts
stripeinvoice.paiddelivered 2001
githubpushdelivered 2001
stripecharge.refundedretrying delivered 2003
shopifyorders/createdelivered 2002

Delivery attempts for evt_9c41f0

  1. 12:04:01 Attempt 1 returned 502 from api.yourapp.com
  2. 12:04:09 Attempt 2 returned 502, next try in 32 seconds
  3. 12:04:41 Attempt 3 in flight Attempt 3 returned 200 in 240 ms

15,000 events free each month

15–180 days of event history

From $20 per month

Compare every plan →

For the terminal you already have open

One URL in. Signed requests out. An API for the rest.

Everything the dashboard does is a plain HTTP call, and none of it needs an SDK. Copy an example, set your own key, run it.

Ingest
POST /e/{ingest_key}, 202 once stored
Delivery
At least once, signed with HMAC SHA256
Retries
5 on Hobby, up to 50 on paid plans
Replay
One event or a range, 15 to 180 days back
Verify
Stripe, GitHub, Shopify, Paddle, Standard Webhooks
Payloads
Up to 5 MB, kept byte for byte

Receive

terminal
# Your provider calls this URL. So can you, to try it.
curl -X POST "https://hooks.shellorbit.com/e/$INGEST_KEY" \
  -H "content-type: application/json" \
  -d '{"type":"order.created","id":"ord_123"}'
Response
HTTP/2 202
{"id":"evt_01m4d6rgyr4pfks4hy1fbpkz3b","received_at":"2026-10-08T09:30:00Z"}

The event is stored before the 202 goes back, then delivered to your destinations with retries.

Quickstart →

Verify

verify.js
import crypto from "node:crypto";

// Every delivery carries ShellOrbit-Signature: t=<unix>,v1=<hex>
export function verify(rawBody, header, secret, toleranceSeconds = 300) {
  const pairs = header.split(",").map((part) => part.split("="));
  const t = pairs.filter(([name]) => name === "t").map(([, value]) => value);
  if (t.length !== 1 || !/^\d+$/.test(t[0])) return false;
  const timestamp = Number(t[0]);
  if (Math.abs(Date.now() / 1000 - timestamp) > toleranceSeconds) return false;
  const expected = crypto.createHmac("sha256", secret)
    .update(`${timestamp}.`).update(rawBody).digest();
  return pairs.filter(([name]) => name === "v1").some(([, value]) =>
    /^[a-f0-9]{64}$/i.test(value || "") &&
    crypto.timingSafeEqual(expected, Buffer.from(value, "hex")));
}

HMAC SHA256 over the timestamp and the raw body. During a key rotation both signatures are sent, so any match passes.

Signature verification →

Replay

terminal
# Fixed the handler? Send the stored event again, byte for byte.
curl -X POST "https://api.shellorbit.com/v1/events/$EVENT_ID/replay" \
  -H "authorization: Bearer $SHELLORBIT_API_KEY"
Response
HTTP/2 202
{"event_id":"evt_01m4d6rgyr4pfks4hy1fbpkz3b","queued":1}

One event, or a filtered range with POST /v1/replays. Replay works for as long as your plan keeps the event.

Replay and recovery →

Send

terminal
# Send your own webhooks through the same pipeline.
curl -X POST "https://api.shellorbit.com/v1/endpoints/ep_example/events" \
  -H "authorization: Bearer $SHELLORBIT_API_KEY" \
  -H "content-type: application/json" \
  -d '{"type":"invoice.paid","data":{"id":"inv_123"}}'
Response
HTTP/2 202
{"id":"evt_01m4d6rhv21wcmh9zs3p3kmp48","received_at":"2026-10-08T09:31:06Z"}

Stored, signed, retried, and replayable like any received event. Your API key is never forwarded.

Sending events →

Localhost

terminal
curl -O https://shellorbit.com/downloads/shellorbit-listen.mjs
export SHELLORBIT_API_KEY=your_read_only_key
node shellorbit-listen.mjs ep_example http://localhost:3000/webhooks
Output
Forwarding new events on ep_example to http://localhost:3000/webhooks. Press Ctrl+C to stop.
evt_01m4d6rgyr4pfks4hy1fbpkz3b checkout.session.completed -> 200 in 41 ms

Real provider traffic on your machine, original headers and body, no tunnel. A read only key is enough.

Local development →

Built around your existing handler

A small change at the edge.
A much clearer event trail.

Point your provider at ShellOrbit and set your application as the destination. Keep your application’s business logic where it belongs.

01Your providerPayments · commerce · code
02ShellOrbitReceive → store → deliver → retry
03Your applicationYour handler. Your business logic.

A practical starting point

Start free.
Grow when your traffic does.

15,000 monthly events and 15 days of history on Hobby. Paid plans add volume, longer retention, and more control.

Find your plan

Start with one provider

Give your next webhook a clear destination.

Create an endpoint, connect your handler, and send a test event.