Skip to main content

Troubleshooting: webhook endpoint cap and DNS pre-create gates

POST /api/v1/webhooks runs two checks before it resolves the URL’s safety profile or writes a row: the per-tenant endpoint quota and a DNS resolution of the hostname. Both reject with 422, both are deterministic — the same request gets the same answer until you change something — and neither creates an endpoint. Match the code, apply the fix, and re-submit. Do not retry unchanged requests against either gate. For the third creation-time code (INVALID_WEBHOOK_URL — blocked schemes, loopback, private ranges), see Troubleshooting: webhook endpoint creation errors.

Cause class: deterministic vs transient

Both codes on this page fire on the create path only. A hostname that resolved at create time but starts failing later is a delivery-time problem, handled by retries and the DLQ — not this page. See Troubleshooting: failed webhook deliveries.

WEBHOOK_ENDPOINT_CAP_REACHED — your tenant is at 10 endpoints

Each tenant can register up to 10 webhook endpoints. The cap exists so a runaway integration cannot fan out thousands of delivery jobs per event. When the 11th create call lands, the API answers 422:

Fix option 1: delete an unused endpoint

  1. List your endpoints — either Developer → Webhooks in the dashboard or the API:
  1. Pick the endpoint that no longer receives traffic — a retired integration, a staging URL, a duplicate pointing at the same handler.
  2. Delete it:
  1. Re-submit the create call. It succeeds as soon as the count drops below 10.

Fix option 2: request a quota lift from support

If all ten endpoints serve live integrations, write to support with:
  • Your tenant id (Dashboard → Settings → Organization).
  • The integrations each existing endpoint serves — one per integration is the expected pattern.
  • The request_id from the 422 response’s error.meta block — quote the rejection envelope so support can pull the exact refused call.
A lift is an out-of-band operation against your tenant, not a self-serve setting, so one request covers your whole plan: name the ceiling you are aiming for, not the next single endpoint.

What not to do

  • Do not retry the same create call. The rejection is deterministic; the count does not change by itself.
  • Do not delete and recreate in a loop to rotate endpoint ids. Endpoint ids are stable for a reason — signature verification and the DLQ key off them.
  • Do not work around the cap by stacking multiple event streams on one endpoint’s URL path. One endpoint can subscribe to all event types; use the events array on the endpoints you already have.

WEBHOOK_DNS_INVALID — the hostname does not resolve

Before persisting an endpoint, Orbit resolves the URL’s hostname against public DNS. If the resolver returns NXDOMAIN (no such name), NODATA (name exists, no A/AAAA record), or SERVFAIL (the authoritative server failed), creation stops with 422:
The same gate runs when you change the URL on an existing endpoint with PATCH /api/v1/webhooks/{id}, with the same code.

Recovery ladder

  1. Resolve the hostname yourself. From any shell, check what public resolvers see:
An empty dig +short answer is what Orbit’s resolver saw — the create call cannot succeed until this command returns an address.
  1. Fix the typo. The most common cause is a mangled hostname — a swapped TLD (.com where your domain is .io), a dropped character, or a transposed pair. Compare the URL string in your create call against the record in your registrar character by character.
  2. Confirm the record in your registrar or DNS provider. If the hostname is spelled right, the record itself may be missing: no A or AAAA for the host, or the zone moved providers and this record was not recreated. Add or repair the record at your DNS provider.
  3. Wait out propagation if you just created the record. New records are visible once your provider’s TTL expires. Retry the create call after dig +short returns the address.
  4. Re-create the endpoint. Only re-submit POST /api/v1/webhooks once step 1 succeeds from your shell — at that point Orbit’s resolver sees the same answer.

Pre-create DNS failure vs delivery-time DNS failure

This code fires only on the create/update path. It never appears in delivery logs. Once an endpoint exists, deliveries whose hostname stops resolving are retried by the delivery worker with backoff and eventually land in the dead-letter queue — a different symptom with a different fix. Do not treat a delivery-time DNS flake as a reason to re-create the endpoint; the endpoint is not the broken part. Delivery-time failures are covered in Troubleshooting: failed webhook deliveries.

What not to do

  • Do not retry the create call against a hostname your own resolver cannot answer. The gate is deterministic — it fails the same way until public DNS answers.
  • Do not bypass the gate with a raw IP address. Literal IPs from private ranges are rejected under INVALID_WEBHOOK_URL, and public IPs without a hostname still fail HTTPS certificate checks downstream. Give the receiver a real hostname.
  • Do not treat NXDOMAIN as a reason to escalate. Check the spelling and the registrar first; escalate only when dig returns an address but Orbit still rejects with WEBHOOK_DNS_INVALID — quote the request_id from the response in that case.

Escalate when the fix is not in your hands

See also