Customers & 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. 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.

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.

OperationRoute
UpsertPOST /v1/customers/{externalId}
GetGET /v1/customers/{externalId}
ListGET /v1/customers?limit=20&cursor=...
UpdatePATCH /v1/customers/{externalId}
DeleteDELETE /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

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 and the portal.

PropertyMeaning
urlHTTPS destination. Validated for safety, see below.
subscriptionsEvent-type names to deliver, or ["*"] (the default) for all of them.
descriptionOptional label, up to 512 characters.
headersCustom headers added to every delivery. The webhook-*, content-type, and user-agent headers are reserved and cannot be overridden.
statusENABLED, 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

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 forwarded to localhost with the CLI.

Continue