Web - Webhooks

Free Webhook Capture API Endpoint

The free webhook capture API endpoint hands you a throwaway URL, then records the exact HTTP request that a sender delivers to it. No tunnel, no ngrok and no server of your own.

  • No API key
  • Any HTTP method
  • Headers and body
  • 24-hour expiry

Capture a request

POST/webhook_capture

GET/webhook_capture/{capture_id}

https://aisenseapi.com/services/v1

Create a capture session

curl -X POST https://aisenseapi.com/services/v1/webhook_capture
{
  "ok": true,
  "capture_id": "3cdadccf-9ea9-47b3-a221-6e62f63a198d",
  "update_url": "https://aisenseapi.com/services/v1/webhook_capture/3cdadccf-9ea9-47b3-a221-6e62f63a198d/update",
  "read_url": "https://aisenseapi.com/services/v1/webhook_capture/3cdadccf-9ea9-47b3-a221-6e62f63a198d",
  "expire_timestamp": 1787266344,
  "expire_datetime": "2026-08-20T22:52:24+00:00"
}

The POST body stays empty. There is nothing to configure and nothing to sign up for.

Two URLs come back from that one call. Give the update_url to the service you want to inspect. Keep the read_url for yourself. Both addresses carry the same capture ID, so this is the entire setup step.

Save the ID somewhere. The service publishes no listing call and cannot look a capture up any other way, which is also what keeps strangers out of yours.

Send anything to the update URL

Point a sender at the update URL and trigger it. Stripe posts JSON. GitHub posts JSON with a signature header alongside. An older system might send form data or plain text. Everything lands in the same place.

curl -X POST "https://aisenseapi.com/services/v1/webhook_capture/3cdadccf-9ea9-47b3-a221-6e62f63a198d/update" \
  -H "Content-Type: application/json" \
  -H "X-Example-Signature: test-123" \
  -d '{"event":"payment.created","amount":4200}'
{
  "ok": true,
  "capture_id": "3cdadccf-9ea9-47b3-a221-6e62f63a198d",
  "captured_at_timestamp": 1787179950,
  "captured_at_datetime": "2026-08-19T22:52:30Z",
  "request": {
    "method": "POST",
    "uri": "/services/v1/webhook_capture/3cdadccf-9ea9-47b3-a221-6e62f63a198d/update",
    "headers": {
      "host": "aisenseapi.com",
      "user-agent": "curl/7.88.1",
      "accept": "*/*",
      "content-type": "application/json",
      "x-example-signature": "test-123",
      "content-length": "41"
    },
    "client_ip": "203.0.113.10",
    "body": {
      "json": { "event": "payment.created", "amount": 4200 },
      "text": null,
      "base64": null,
      "raw_length": 41
    }
  }
}

Notice that the update call answers with the capture itself. That helps while you are poking at it by hand, because the result appears without a second request.

Read the captured request back

Later, or from a different machine, fetch the capture with a plain GET.

curl https://aisenseapi.com/services/v1/webhook_capture/3cdadccf-9ea9-47b3-a221-6e62f63a198d

The response matches what the update call returned, byte for byte. An unknown or expired capture ID answers with HTTP 404 instead.

One behaviour is worth knowing before you rely on it. Each new request to the update URL replaces the one before it. A capture holds the most recent delivery, never a history. Read a capture before you trigger the next attempt, or the earlier one is gone.

Any method, any body shape

The body arrives reported three ways, and exactly one of them is filled in.

Valid JSON is parsed into body.json. Readable text that is not JSON goes to body.text. Binary content is Base64 encoded into body.base64. The unused slots stay null, so your code can simply branch on whichever one is not null.

curl -X PUT "https://aisenseapi.com/services/v1/webhook_capture/3cdadccf-9ea9-47b3-a221-6e62f63a198d/update" \
  -H "Content-Type: text/plain" \
  -d 'hello from a sender'
"body": {
  "json": null,
  "text": "hello from a sender",
  "base64": null,
  "raw_length": 19
}

PUT, PATCH, DELETE and GET all work the same way. A request carrying no body at all is still a valid capture: the three slots stay null and raw_length reports 0. That alone proves the sender reached you.

What the free webhook capture API endpoint records

Every capture comes back in the same shape.

FieldTypeDescription
capture_idstringThe UUID that appears in both the update URL and the read URL.
captured_at_timestampintegerUnix time at which the request arrived.
captured_at_datetimestringThe same moment as an ISO 8601 timestamp in UTC.
request.methodstringThe inbound HTTP method, such as POST, PUT, PATCH, DELETE or GET.
request.uristringThe path the sender actually requested.
request.headersobjectEvery header received, with lowercase names.
request.client_ipstringThe sender's IP address as the service saw it.
request.body.jsonobjectThe parsed value when the body is valid JSON.
request.body.textstringText content when the body is not JSON.
request.body.base64stringBinary content, encoded so it survives JSON transport.
request.body.raw_lengthintegerByte count of the body as received.

The three steps in order

  1. Create the session

    One POST to /webhook_capture returns the capture ID and the two URLs. Copy them into your notes or a shell variable.

  2. Point the sender at the update URL

    Paste the update URL into the webhook settings of Stripe, GitHub, Shopify, a CI job or your own script. Then fire a real event at it.

  3. Read what arrived

    GET the read URL and compare the headers and body against the provider documentation. Most integration surprises show up right here.

Why this beats a local tunnel

Debugging a webhook usually starts badly. You install a tunnel client, sign in, start a listener, then copy a URL that changes again the next time you run it. Providers only deliver to public HTTPS addresses, so your laptop is never an option on its own.

The free webhook capture API endpoint removes that whole step. The URL is public and served over HTTPS from the moment it exists. Nothing runs on your machine. A colleague on another continent opens the same read URL and sees the same capture.

It also works where a tunnel simply cannot. A CI runner, a serverless function or an AI agent can each be handed a callback URL and inspected afterwards, without any of them holding a port open.

Common uses

Most people reach the free webhook capture API endpoint with nothing but a terminal open. Four patterns come up again and again.

Webhook debugging

Compare what a provider really sends with what its documentation claims.

Integration setup

Capture one real sample before writing any parsing or validation code.

Signature inspection

See which signature headers arrive and how long the raw body actually is.

Agent callbacks

Give an automated process a temporary callback URL and read the result later.

Pairing it with the other web endpoints

A capture answers one question: what did the sender actually send. Other endpoints answer the questions that follow.

Run a payload through the Validation API endpoint once you know its shape. Park a large sample in the Storage API endpoint so a colleague can fetch the exact bytes. Confirm a caller is reachable at all with the Ping API endpoint, and check the address it came from with the Client IP API endpoint.

This service is also the passive half of a pair. Its sibling, the Webhook Action API endpoint, asks a person for a decision rather than recording a machine.

Expiry, security and limits

Treat a capture as readable by anyone holding the link. The service records every header and the complete body, so provider signatures and Authorization tokens end up stored alongside the payload. No key and no account exist here, which means the unguessable read URL is the only thing protecting a capture.

Captures become unreachable 24 hours after the session is created. The expire_timestamp and expire_datetime fields in the create response state exactly when that happens.

The base URL is https://aisenseapi.com/services/v1. Every service on the free public REST APIs hub shares one limit of 5000 requests per IP per 24 hours. A create call, the inbound webhook and your read all count against it, so a full debugging round costs three requests.