# The ingest URL

The webhook URL Webhooker gives every source — which methods and payloads it accepts, every response code it returns, and what is stored in each case.

Source: https://docs.webhooker.eu/receive/ingest/

Every source has one ingest URL. Anything that can make an HTTP request can use
it — no SDK, no handshake, no account on the sender's side.

```
https://app.webhooker.eu/in/6b225n04u5kmyg
```

![Ingest URLs listed on the Sources page](https://docs.webhooker.eu/screenshots/sources-list-light.webp "Each source owns one ingest URL, shown in full on the Sources page.")

## Request format

| Property | Accepted |
| --- | --- |
| Methods | `POST`, `PUT`, `PATCH`, `DELETE` |
| Body | Anything, up to 1 MiB. JSON is parsed for filters; other payloads are stored and forwarded byte for byte. |
| Headers | All of them are stored and available to filters and transformations. |
| Content type | Any. Recorded as sent. |
| Query string | Accepted and ignored. |

There is nothing to sign and no envelope to build: send the provider's payload
exactly as it comes.

```bash
curl -X POST https://app.webhooker.eu/in/6b225n04u5kmyg \
  -H "Content-Type: application/json" \
  -d '{"type":"invoice.paid","amount":4200}'
```

### GET requests

A `GET` never returns event data. It serves a plain information page, so a
teammate who opens the URL in a browser sees an explanation rather than an
error.

One exception: Meta platforms (Facebook, WhatsApp, Instagram) confirm an
endpoint with `GET …?hub.mode=subscribe&hub.challenge=…`. Webhooker echoes
`hub.challenge` back as `text/plain`, which is what those platforms expect, so
the subscription check passes with no configuration.

## Response codes

| Code | Meaning | Stored? |
| --- | --- | --- |
| `200` | Accepted and stored. Delivery starts out of band. | Yes |
| `401` | Inbound verification failed. | Yes, as `failed`, with no deliveries |
| `402` | The workspace used up its monthly event quota. | No |
| `404` | No such token, or the source is in the trash. | No |
| `413` | The payload is over 1 MiB. | No |
| `429` | The source is over its per-minute ingest budget. `Retry-After` says when to come back. | No |
| `500` | Webhooker could not store the event. Safe to retry. | No |

The success body is JSON:

```json
{
  "status": "SUCCESS",
  "message": "Request received successfully.",
  "request_id": "0190a0b1-c2d3-7e4f-8a9b-0c1d2e3f4a5b"
}
```

`request_id` is the event id. Quote it when you need to trace one webhook end to
end.

Providers that require a different status or body can be served one — see
[custom responses](/receive/custom-response/).

## Why 200 and not 202

The answer is sent once the event is durably stored, not once it is delivered.
Delivery happens out of band, with its own retry schedule, so a slow endpoint on
your side never slows down the provider and never causes the provider's own
retries. An accepted event is not lost if your endpoint is down — it waits in
the delivery queue.

## Paused sources

A paused source still answers `200` and still stores every event; deliveries are
suppressed until you resume it. The provider sees healthy responses throughout,
and you replay the backlog when your handler is ready.

## Size and rate limits

Payloads are capped at 1 MiB. Per-minute ingest budgets are per source and
depend on your plan — see [limits](/reference/limits/).
