Per-Instance Usage & Delivery Logs (Detail View)#
GET/v1/instances/:instanceId/usage#
Returns per-instance message counters for the last 24 hours. Used by the detail view's "Mensagens" section.
Auth: JWT or API key (any role).
Response 200:
{
"messages_today": 342,
"messages_sent_today": 120,
"messages_received_today": 222,
"delivered_today": 115,
"failed_today": 5
}
| Field | Meaning |
|---|---|
messages_today |
Sent + received in the last 24h. |
messages_sent_today |
Outbound messages in the last 24h. |
messages_received_today |
Inbound messages in the last 24h. |
delivered_today |
Outbound messages that reached status=delivered in the last 24h. |
failed_today |
Outbound messages that reached status=failed in the last 24h. |
GET/v1/webhooks/delivery-logs#
Returns the latest delivery logs across all of the caller's webhooks, optionally filtered by instance_id. Used by the detail view's "Webhook deliveries" section so a caller can inspect deliveries for a specific instance without knowing which webhook fired.
Auth: JWT or API key (any role). Scoped to the caller's company.
Query params:
| Param | Type | Default | Meaning |
|---|---|---|---|
instance_id |
string | — | Restrict to deliveries from webhooks scoped to this instance OR global webhooks. Omit to see all. |
limit |
int | 20 | Page size (max 100). |
page |
int | 1 | Page number (1-based). |
GET/v1/webhooks/instance-events#
Returns the unified events feed for a single instance, aggregated by event_id (one row per event with the latest delivery attempt's state). Powers the Eventos panel on the instance detail Webhooks tab with filter chips for status.
Use this to audit ANY event sent to/from an instance — successful AND failed — without leaving the instance page. Distinct from /v1/webhooks/stuck, which only returns hard-failed events for the cross-instance dashboard widget.
Auth: JWT or API key (any role). Scoped to the caller's company.
Aggregation rule: rows are grouped by event_id, and the LATEST delivery attempt (max log id) determines the row's success, status_code, error_class, etc. The attempts field is the highest attempt number observed for the event.
Query params:
| Param | Type | Default | Meaning |
|---|---|---|---|
instance_id |
string | required | The instance to scope to. Includes deliveries from webhooks scoped to this instance AND global webhooks (no instance_id). 400 INSTANCE_ID_REQUIRED if missing. |
status |
string | all |
Filter mode: all, success (latest attempt 2xx), failure (latest attempt non-2xx), stuck (hard-failed: permanent_4xx + ≥3 attempts). 400 INVALID_STATUS for other values. |
hours |
int | 24 | Window in hours (max 168 = 7 days). Ignored when since is set. |
since |
RFC3339 | — | Explicit lower-bound cutoff. Overrides hours. |
page |
int | 1 | Page number (1-based). |
limit |
int | 50 | Page size (max 200). |
Response 200:
{
"data": [
{
"log_id": 47213,
"webhook_id": 7,
"webhook_url": "https://app.exemplo.com/webhook",
"event_id": "evt-abc-123",
"event_type": "message.received",
"status_code": 200,
"response": "",
"attempts": 2,
"success": true,
"error_class": "",
"is_hard_failed": false,
"has_payload_raw": true,
"created_at": "2026-05-03T10:39:45Z"
}
],
"total": 75,
"page": 1,
"limit": 50
}
Field meanings:
success: latest attempt for the event delivered (HTTP 2xx).is_hard_failed: latest attempt'serror_classispermanent_4xxANDattempts >= 3(event hitSkipRetryand won't auto-recover).has_payload_raw:payload_rawis still on disk soPOST /v1/webhooks/retry-bulkwith thislog_idcan replay the delivery.falsewhen the row passed the 14-day retention.attempts: highest attempt number (e.g.4means up to 4 delivery attempts have been made; for the same event with multiple retries, only ONE row is returned, never four).
GET/v1/webhooks/events#
Returns the unified events feed for the caller's entire company, aggregated by event_id (one row per event with the latest delivery attempt's state). Same shape and aggregation rule as /v1/webhooks/instance-events, but does not require instance_id — it scopes across every webhook of the company.
Powers the Entrega tab on the consolidated webhooks view with filter chips for status (Todos / Sucesso / Falha / Travado).
Auth: JWT or API key (any role). Scoped to the caller's company.
Aggregation rule: identical to instance-events — rows grouped by event_id, latest delivery attempt determines the row state, attempts is the highest attempt number observed.
Query params:
| Param | Type | Default | Meaning |
|---|---|---|---|
status |
string | all |
Filter mode: all, success (latest attempt 2xx), failure (latest attempt non-2xx), stuck (hard-failed: permanent_4xx + ≥3 attempts). 400 INVALID_STATUS for other values. |
hours |
int | 24 | Window in hours (max 168 = 7 days). Ignored when since is set. |
since |
RFC3339 | — | Explicit lower-bound cutoff. Overrides hours. |
page |
int | 1 | Page number (1-based). |
limit |
int | 50 | Page size (max 200). |
Response 200: Same shape as /v1/webhooks/instance-events.
{
"data": [
{
"log_id": 47213,
"webhook_id": 7,
"webhook_url": "https://app.exemplo.com/webhook",
"event_id": "evt-abc-123",
"event_type": "message.received",
"status_code": 200,
"response": "",
"attempts": 2,
"success": true,
"error_class": "",
"is_hard_failed": false,
"has_payload_raw": true,
"created_at": "2026-05-03T10:39:45Z"
}
],
"total": 75,
"page": 1,
"limit": 50
}
When to use which endpoint:
/v1/webhooks/events— company-wide audit; default for the consolidated Entrega tab. Use when answering "como está minha entrega de webhooks no geral?"/v1/webhooks/instance-events— same shape, narrowed to one instance. Use when debugging a single instance./v1/webhooks/stuck— only hard-failed events for the dashboard widget badge / cross-instance triage.
GET/v1/event-deliveries#
Returns every webhook delivery log for um único event_id, enriquecido com a URL do webhook. Usado pelo Event Viewer para mostrar quais webhooks receberam um evento especifico e o status de cada tentativa de entrega.
Auth: JWT ou API key (any role). Tenant-scoped: callers não-superadmin so veem logs cujo webhook pertence a sua empresa. O espelho superadmin e GET /v1/admin/event-deliveries.
Query params:
| Param | Tipo | Obrigatório | Descricao |
|---|---|---|---|
event_id |
string | sim | O evento cujas entregas listar. 400 BAD_REQUEST quando ausente/vazio. |
Resposta 200:
{
"logs": [
{
"id": 47213,
"webhook_id": 7,
"event_id": "evt-abc-123",
"event_type": "message.received",
"payload": "{...}",
"payload_raw": "{...}",
"status_code": 200,
"response": "OK",
"attempt": 1,
"success": true,
"error_class": "",
"created_at": "2026-05-03T10:39:45Z",
"webhook_url": "https://app.exemplo.com/webhook"
}
],
"total": 1
}
Logs são ordenados created_at ASC (tentativa mais antiga primeiro). Um event_id desconhecido retorna {"logs": [], "total": 0} com HTTP 200.
GET/v1/webhooks/instance-metrics#
Aggregate webhook delivery metrics scoped to a single instance over a time window. Powers the StatCards on the instance detail Webhooks tab (/instances/<id>?tab=webhooks).
The aggregation includes deliveries from BOTH webhooks scoped to the instance AND global webhooks (no instance_id) — global webhooks fire for every instance, so their deliveries are legitimately part of the instance's webhook health.
Auth: JWT or API key (any role). Scoped to the caller's company.
Query params:
| Param | Type | Default | Meaning |
|---|---|---|---|
instance_id |
string | required | The instance to scope to. 400 INSTANCE_ID_REQUIRED if missing. |
hours |
int | 24 | Window in hours (max 168 = 7 days). |
Response 200:
{
"instance_id": "f35157b4-46ae-4bdb-8f51-4870bcb5bf9c",
"period_hours": 24,
"total": 1284,
"successes": 1247,
"failures": 37,
"success_rate": 97.12,
"stuck_pending": 3,
"configured_webhooks": 4,
"active_webhooks": 3
}
Field meanings:
total/successes/failures: delivery attempt counts in the window.success_rate: percentage 0-100. Defaults to 100 when there are zero deliveries (no failures = saudável).stuck_pending: distinct event_ids with at least one failure in the window AND no later success row for the same event_id (i.e. wake-up retry hasn't recovered them yet — see lesson #19).configured_webhooks: total webhooks applicable to the instance (scoped + global).active_webhooks: subset ofconfigured_webhookswhereactive=true.
Response 200: { data, total, page, limit }. Each item is a DeliveryLog (same shape as the per-webhook endpoint).
GET/v1/webhooks/metrics#
Per-webhook health metrics scoped to the caller's company over a time window. Powers the Dashboard tab on /webhooks for every authenticated user. Tenant callers see only their own webhooks; superadmin sees ALL webhooks across companies — same handler powers both surfaces.
Auth: JWT or API key (any role with access to /v1/webhooks — owner / admin).
Query params:
| Param | Type | Default | Meaning |
|---|---|---|---|
hours |
int | 24 | Window in hours (max 168 = 7 days). |
Response 200:
{
"period_hours": 24,
"webhooks": [
{
"webhook_id": 21,
"url": "https://meu-crm.example.com/webhook",
"company_id": 9,
"company_name": "Catcher",
"instance_id": "f35157b4-46ae-4bdb-8f51-4870bcb5bf9c",
"instance_name": "Catcher 3",
"total": 1284,
"successes": 1247,
"failures": 37,
"success_rate": 97.12
}
]
}
Field meanings:
- One entry per webhook applicable to the caller — including webhooks with zero deliveries in the window (so the tenant can see ALL their webhooks at a glance, including newly-created ones).
success_rate: 0-100, defaults to 100 when there are zero deliveries.company_name/instance_name: enriched server-side from the master + tenant DBs. May be empty when the row is older than the corresponding entity rename.
GET/v1/webhooks/company-delivery-logs#
Recent delivery logs for the caller's company (or all companies when superadmin), with optional filters. Powers the "Falhas recentes" list on the Dashboard tab. Mirror of /v1/admin/delivery-logs but tenant-scoped.
Auth: JWT or API key (any role with access to /v1/webhooks).
Query params (all optional):
| Param | Type | Default | Meaning |
|---|---|---|---|
success |
bool | — | When set, narrows to delivered (true) or failed (false) attempts. |
event_type |
string | — | Narrows to a specific event type (e.g. message.received). |
webhook_id |
int | — | Narrows to a specific webhook. Tenant callers are rejected (empty result) if the webhook does not belong to their company. |
since |
RFC3339 | now-24h | Earliest created_at cutoff. |
page / limit |
int | 1 / 50 | Pagination. Max limit=100. |
Response 200: { data, total, page, limit }. Each item carries the delivery log fields plus the joined webhook_url, company_id, and company_name (only populated for superadmin callers, since tenants always know their own company).
Tenant-scoping invariant: a tenant caller can never see a delivery log whose webhook belongs to another company. Even an explicit ?webhook_id=X pointing at a foreign webhook returns an empty page (not a 4xx — so the cross-company existence of the webhook isn't leaked).
Webhook detail endpoints (/v1/webhooks/{webhookId})#
Since 2026-05-11 the per-webhook endpoints (GET, PATCH, DELETE, GET /logs, POST /logs/{logId}/retry) accept cross-company access for superadmin callers, mirroring the existing escape hatch on GET /v1/webhooks for the instance detail surface. Regular tenant callers remain scoped to their own company (404 on cross-company IDs).
This unifies the WebhookDetailView at /webhooks/:id so the same URL works for both the tenant (their own webhook) and the superadmin (any webhook on the platform). The dedicated /v1/admin/webhooks/{id} mirror endpoints are still available for legacy callers.