Skip to content

Admin

Manage application configurations, including webhook URLs, API keys, and rate limits. Admin endpoints are authenticated separately from app endpoints using a server-level admin API key.

All admin endpoints require the X-Admin-API-Key header. This key is set via the ADMIN_API_KEY environment variable on the gateway server. Validation uses constant-time comparison to prevent timing attacks.

HeaderDescription
X-Admin-API-KeyServer-level admin API key. Required for all admin endpoints.

Authentication errors

StatusCondition
503ADMIN_API_KEY environment variable not set. Admin endpoints are disabled.
401Missing X-Admin-API-Key header or invalid key.

POST /admin/apps/{app_id}

Create or update an application’s configuration including webhook URL, API key, and rate limits. If the app already exists, its configuration is overwritten.

Path parameters

ParameterDescriptionValidations
app_idApplication identifier.Alphanumeric, underscore, hyphen only. Max 64 chars. Regex ^[a-zA-Z0-9_-]+$.

Request body

FieldTypeRequiredDescriptionValidations
webhook_urlstringoptionalWebhook delivery URL. Empty string disables webhooks.Valid HTTP/HTTPS URL. HTTPS required unless ALLOW_HTTP_WEBHOOKS=true. Must not resolve to private/loopback IPs unless ALLOW_LOCALHOST_WEBHOOKS=true.
api_keystringoptionalAPI key for this app’s authentication via X-API-Key.If provided, at least 16 chars, only printable non-space characters.
rate_limitintegeroptionalMax requests per minute. 0 uses the default (100).≥ 0. Max 10000.
eventsstring[]optionalWhitelist of event names to deliver. Omit or send an empty array to receive all events.Each value must be a canonical event name (see Webhooks overview).

Response — 200 OK

{
"success": true,
"app_id": "my-app",
"webhook_url": "https://your-app.com/webhooks",
"rate_limit": 200
}
Terminal window
curl -X POST https://gateway.example.com/admin/apps/my-app \
-H "X-Admin-API-Key: your-admin-key" \
-H "Content-Type: application/json" \
-d '{"webhook_url": "https://your-app.com/webhooks", "api_key": "sk_live_abc123", "rate_limit": 200}'

Triggered webhooks — none. This is an administrative endpoint.

GET /admin/apps/{app_id}

Retrieve an application’s full configuration including webhook URL, API key, and rate limits.

Response — 200 OK

{
"success": true,
"app_id": "my-app",
"webhook_url": "https://your-app.com/webhooks",
"api_key": "sk_live_abc123",
"rate_limit": 200
}

Error — 404 Not Found

{
"success": false,
"app_id": "my-app",
"error": "App not found"
}

Triggered webhooks — none. This is a read-only endpoint.

DELETE /admin/apps/{app_id}

Delete an application’s configuration. The app must exist or a 404 is returned. Active sessions belonging to this app are not affected — they will fail authentication on subsequent requests.

Response — 200 OK

{
"success": true,
"app_id": "my-app"
}

Triggered webhooks — none. This is an administrative endpoint.

GET /admin/health

Admin-authenticated health check. Returns service status and current UTC timestamp.

{
"status": "ok",
"timestamp": "2026-03-21T12:00:00Z"
}

GET /admin/recent-errors

Return the most recent server-side error events for ops debugging. Each entry contains a timestamp, trace correlation, request location, status code, the affected app, and a sanitized error message.

{
"total": 1,
"errors": [
{
"timestamp": "2026-05-06T12:00:00Z",
"trace_id": "abcd-1234",
"method": "POST",
"path": "/api/v1/dial",
"pattern": "/api/v1/dial",
"status_code": 503,
"app_id": "my-app",
"error": "no outbound capacity"
}
]
}

Manage the allow-list of caller IDs your app may present on outbound dials. Only numbers on the list are accepted as from in POST /api/v1/dial.

Replace allow-listPUT /admin/apps/{app_id}/cids

Replace the caller-ID allow-list for the app. The request body is a bare JSON array of caller-ID strings (Israeli domestic format), e.g. ["527121102", "747713001"]. Returns 200 with the resulting list.

Today’s behaviour: the handler appends to the existing set (it does not delete entries missing from the request). True replace semantics are tracked as a future improvement; until then, callers needing a hard replace should also call DELETE /admin/apps/{app_id}/cids/{number} for each removal.

Get allow-listGET /admin/apps/{app_id}/cids

Return the current allow-list for the app.

Remove a caller IDDELETE /admin/apps/{app_id}/cids/{number}

Remove a single caller ID from the allow-list. Returns 200 on success, 404 if either app or number is unknown.

GET /metrics

Prometheus exposition-format metrics. Intended for ops scraping and alerting; not part of the consumer API contract. No authentication is enforced at the gateway level — protect this endpoint at the network layer (e.g. Kubernetes NetworkPolicy or ingress allow-list).

When creating or updating an app, the webhook_url is validated against SSRF attacks:

  • Must be a valid URL with http or https scheme.
  • HTTPS is required in production. Set ALLOW_HTTP_WEBHOOKS=true to allow HTTP in development.
  • Must not resolve to private IP ranges (10/8, 172.16/12, 192.168/16) or loopback addresses.
  • Set ALLOW_LOCALHOST_WEBHOOKS=true to allow localhost/loopback in development.
  • An empty string is allowed and disables webhooks for the app.

See the Rate limits guide for cooldown windows and 429 retry semantics.

StatusCondition
400Invalid app_id format, invalid JSON payload, or invalid webhook_url.
401Missing or invalid X-Admin-API-Key.
404App not found (for GET and DELETE).
500Internal error saving, retrieving, or deleting app config.
503ADMIN_API_KEY not configured, or Redis not available.