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

# Troubleshooting: webhook endpoint cap and DNS pre-create gates

> Resolve the two deterministic 422 pre-create gates — WEBHOOK_ENDPOINT_CAP_REACHED (tenant endpoint quota) and WEBHOOK_DNS_INVALID (hostname does not resolve) — before POST /webhooks persists anything.

# 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](/troubleshooting/webhook-endpoint-creation).

## Cause class: deterministic vs transient

| Class | Codes | Retry posture |
| - | - | - |
| Deterministic — quota | `WEBHOOK_ENDPOINT_CAP_REACHED` | Never retries. The count only drops when you delete an endpoint, or support raises the cap. |
| Deterministic — create-time DNS | `WEBHOOK_DNS_INVALID` | Retries only after you fix the hostname or its DNS record. A retry with the same URL returns the same 422. |
| Transient — delivery-time | delivery errors after the endpoint exists | Retries are built into the delivery worker with backoff and a dead-letter queue. |

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](/troubleshooting/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:

```json theme={null}
{
  "error": {
    "code": "WEBHOOK_ENDPOINT_CAP_REACHED",
    "status": 422,
    "details": { "limit": 10, "current": 10 }
  }
}
```

### Fix option 1: delete an unused endpoint

1. List your endpoints — either **Developer → Webhooks** in the dashboard or
   the API:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/webhooks" \
  -H "X-API-Key: dv_live_sk_..."
```

2. Pick the endpoint that no longer receives traffic — a retired
   integration, a staging URL, a duplicate pointing at the same handler.
3. Delete it:

```bash theme={null}
curl -X DELETE "https://api.orbit.devotel.io/api/v1/webhooks/{id}" \
  -H "X-API-Key: dv_live_sk_..."
```

4. 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:

```json theme={null}
{
  "error": {
    "code": "WEBHOOK_DNS_INVALID",
    "status": 422,
    "details": { "url": "https://hooks.exmaple.io/inbound", "failure_code": "dns_invalid" }
  }
}
```

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:

```bash theme={null}
nslookup hooks.exmaple.io
dig +short hooks.exmaple.io
```

An empty `dig +short` answer is what Orbit's resolver saw — the create
call cannot succeed until this command returns an address.

2. **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.

3. **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.

4. **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.

5. **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](/troubleshooting/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

| Symptom | Route | Take with you |
| - | - | - |
| You need more than 10 endpoints | Support ticket | Tenant id, the integration per endpoint, `request_id` from the 422 |
| `dig` resolves but Orbit still answers `WEBHOOK_DNS_INVALID` | Support ticket | The hostname, the `request_id` from the 422, your `dig +short` output |
| Creation succeeds; deliveries retry then DLQ | This page does not apply — use [failed webhook deliveries](/troubleshooting/webhook-deliveries) | — |

## See also

* [Troubleshooting: webhook endpoint creation errors](/troubleshooting/webhook-endpoint-creation) —
  the sibling create-time gate (`INVALID_WEBHOOK_URL` — scheme and
  private-range rejections).
* [Troubleshooting: failed webhook deliveries](/troubleshooting/webhook-deliveries) —
  retries, backoff, and the dead-letter queue after creation succeeds.
* [Troubleshooting: webhook signature invalid](/troubleshooting/webhook-signature-invalid) —
  receiver-side verification failures after delivery.
* [Error codes reference](/reference/error-codes) — the raw code table this
  page expands on.
