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

# Customers and Endpoints

> Manage who you send to: customers identified by your own ids, and endpoints with subscriptions, custom headers, pause and resume, and URL safety checks.

A customer is who you send to. An endpoint is where their webhooks go. Both are managed through the REST API with a `manage`-scoped token, in the dashboard under **Customers**, or by the customers themselves in the [portal](/docs/send/portal). All three surfaces operate on the same objects, so an endpoint a customer adds in the portal is immediately visible to your API and your team.

## Customers

Customers are identified by an `externalId` you choose: your database's account id, an org slug, whatever you already use.

```bash theme={"languages":{"custom":["/languages/repost.json"]}}
curl -X POST https://api.repost.sh/v1/customers/acme \
  -H "Authorization: Bearer $REPOST_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name": "Acme Corp", "metadata": {"plan": "enterprise"}}'
```

Creation is an idempotent upsert. It returns `201` when the customer is new and `200` with the existing customer otherwise, so you can call it from a signup flow without checking first. A customer carries an optional display `name` and free-form `metadata`.

| Operation | Route                                                            |
| --------- | ---------------------------------------------------------------- |
| Upsert    | `POST /v1/customers/{externalId}`                                |
| Get       | `GET /v1/customers/{externalId}`                                 |
| List      | `GET /v1/customers?limit=20&cursor=...`                          |
| Update    | `PATCH /v1/customers/{externalId}`                               |
| Delete    | `DELETE /v1/customers/{externalId}` (also removes its endpoints) |

You don't have to pre-create customers. Creating an endpoint for an unknown `externalId` creates the customer at the same time.

## Endpoints

```bash theme={"languages":{"custom":["/languages/repost.json"]}}
curl -X POST https://api.repost.sh/v1/customers/acme/endpoints \
  -H "Authorization: Bearer $REPOST_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://acme.example.com/webhooks",
    "description": "Production receiver",
    "subscriptions": ["order.created", "order.refunded"],
    "headers": {"x-acme-source": "repost"}
  }'
```

The `201` response contains the endpoint and its `whsec_...` signing secret. The secret is returned only on creation; store it or show it to your customer right away. It remains available later through the [secret routes](/docs/send/signing) and the portal.

| Property        | Meaning                                                                                                                                  |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `url`           | HTTPS destination. Validated for safety, see below.                                                                                      |
| `subscriptions` | Event-type names to deliver, or `["*"]` (the default) for all of them.                                                                   |
| `description`   | Optional label, up to 512 characters.                                                                                                    |
| `headers`       | Custom headers added to every delivery. The `webhook-*`, `content-type`, and `user-agent` headers are reserved and cannot be overridden. |
| `status`        | `ENABLED`, `PAUSED`, or `DISABLED`.                                                                                                      |

The other routes follow the same pattern: `GET /v1/customers/{externalId}/endpoints` lists a customer's endpoints, and `GET`, `PATCH`, and `DELETE /v1/endpoints/{id}` operate on one. Updates apply to pending retries as well, so correcting a mistyped URL also redirects the backlog.

### Pause and resume

```bash theme={"languages":{"custom":["/languages/repost.json"]}}
curl -X POST https://api.repost.sh/v1/endpoints/{id}/pause -H "Authorization: Bearer $REPOST_TOKEN"
curl -X POST https://api.repost.sh/v1/endpoints/{id}/resume -H "Authorization: Bearer $REPOST_TOKEN"
```

Use pause for maintenance windows. Deliveries for a paused endpoint are still created but held, and resume drains the backlog in order. Nothing is lost, and nothing burns retries against a receiver you know is down. Deleting an endpoint behaves differently: its in-flight deliveries fail terminally as `endpoint_gone`.

### URL safety

Endpoint URLs are validated when set and checked again when a connection is opened. `localhost`, `.local` names, and private or reserved IP ranges are rejected with `422`, and DNS answers are re-checked at dial time, so an endpoint cannot be pointed at your internal network. To receive webhooks on a development machine, use a public target such as a Repost [bucket](/docs/buckets/create) forwarded to localhost with the [CLI](/docs/cli/local-forwarding).

## Continue

<Columns cols={3} className="gap-y-4">
  <Card title="Signing" icon="lock" href="/docs/send/signing" cta="Secrets" arrow="true">
    How the endpoint's secret signs deliveries, and how to rotate it.
  </Card>

  <Card title="Delivery & retries" icon="shield-check" href="/docs/send/delivery" cta="Reliability" arrow="true">
    What happens to each endpoint's deliveries, attempt by attempt.
  </Card>

  <Card title="Customer portal" icon="app-window" href="/docs/send/portal" cta="Self-service" arrow="true">
    Let customers manage these endpoints themselves.
  </Card>
</Columns>
