Web - Webhooks

Free Webhook Capture API Endpoint

Create a temporary URL, receive one HTTP request and read it from another process. Long polling and an optional completion callback remove the need for a fast polling loop.

  • No API key
  • Any HTTP method
  • Wait up to 25s
  • 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",
  "status": "pending",
  "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",
  "wait_url": "https://aisenseapi.com/services/v1/webhook_capture/3cdadccf-9ea9-47b3-a221-6e62f63a198d/wait/25",
  "expire_timestamp": 1787266344,
  "expire_datetime": "2026-08-20T22:52:24+00:00"
}

The body may be empty. You can also send {"notify_url":"https://example.com/done"}. That public URL receives one small signal after the first request is captured. The signal contains the capture ID, status, result URL and timestamp. It does not contain the captured request.

Give the update_url to the sender. Use read_url for an immediate read or wait_url to wait for a result. Save the ID because the service has no listing call.

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 or wait for the request

A plain GET returns immediately. A pending capture has status: "pending". Add /wait/25 to wait for up to 25 seconds.

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

The waiting response adds waited_seconds and wait_reason. It returns early when the request arrives. Use another wait call if it times out.

The first request to the update URL wins. Retries return the stored first request and cannot replace it or send another completion signal. An unknown ID returns HTTP 404. An expired capture returns HTTP 410.

Any method, one bounded body

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 request body is limited to 256 KB.

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 three URLs.

  2. Point the sender at the update URL

    Paste the update URL into the sender and fire one event.

  3. Read what arrived

    GET the read URL, or use the wait URL when your process can hold a request open for up to 25 seconds.

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.