> ## Documentation Index
> Fetch the complete documentation index at: https://www.courier.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Inbound Webhooks

> Receive events from external systems at a Courier-generated URL. Register a webhook, post JSON to it, and use the events that arrive to start journeys.

Your systems send events to Courier. Courier gives you a URL, and you point your webhooks at it. Each event that arrives is parsed and made available to the rest of the platform, most commonly as a [Webhook trigger](/docs/platform/journeys/invocation#webhook) on a journey.

Use one when a third-party system can send an HTTP request but can't call the Courier API directly. For the opposite direction, where Courier notifies your systems about message and template activity, see [Outbound Webhooks](/docs/platform/workspaces/outbound-webhooks).

## Register an Inbound Webhook

1. Go to [Settings > Webhooks](https://app.courier.com/settings/webhooks), under **Developers**, and find the **Inbound Webhooks** section.
2. Click **Add**, then give the webhook a name and description.
3. Save. Courier generates a unique URL and shows it in the URL column, in the form `https://api.courier.com/inbound/webhook/<token>`.

The name is permanent. You select the webhook by name wherever you consume its events, and its events are tied to that name, so pick something you'll recognize later.

## Send Events

Point the source system at the generated URL and `POST` your JSON. No API key or auth header is needed. The URL itself carries a signed token that identifies your workspace.

<Warning>Treat the webhook URL as a secret. Anyone who has it can send events into your workspace. If it leaks, delete the webhook and create a new one to get a fresh URL.</Warning>

```bash theme={null}
curl -X POST https://api.courier.com/inbound/webhook/YOUR_WEBHOOK_TOKEN \
  -H "Content-Type: application/json" \
  -d '{
    "event": "order-shipped",
    "userId": "user_123",
    "properties": {
      "order_id": "ORD-9042",
      "carrier": "UPS"
    }
  }'
```

Send real traffic before you build against the webhook. Courier learns the event names and payload shape from events it has actually received, so event pickers and variable hints stay empty until at least one event arrives.

## Payload Handling

Courier accepts any payload up to 6 MB.

| Payload       | What Courier does                                                                  |
| ------------- | ---------------------------------------------------------------------------------- |
| JSON object   | Parses it and exposes the fields as data                                           |
| JSON array    | Unpacks it and treats each object in the array as its own event                    |
| Anything else | Keeps the whole payload as a string on a `raw` field, and names the event `custom` |

Courier answers `202` once it accepts the request. A `404` means the URL is wrong or no longer exists, in which case create a new webhook and repoint your system at the new URL.

### Reserved Fields

Courier reads two fields out of a JSON payload if they're present.

| Field    | Purpose                                                                                                                                                                |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event`  | The event name, used to pick which events start a workflow. Must be a string. If the payload has no `event` field, Courier names the event `custom`.                   |
| `userId` | Identifies the recipient. Courier resolves the [user](/docs/platform/users/users-overview) from it and loads their profile data. A string or a number, coerced to a string. |

<Warning>The `userId` has to match an existing Courier user. Without a recipient there's nothing to send to, so the event won't start a journey.</Warning>

Every other field is yours. Courier passes them through as data on whatever consumes the event.

## Use the Events

Point a journey's [Webhook trigger](/docs/platform/journeys/invocation#webhook) at the webhook by name. Optionally narrow it to a single `event` name, or leave it open to start on any event from that source. Payload fields become variables on the journey run.
