Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

12 - API Mapping (Webhooks Module)

Exact wire contracts for the Webhooks module. Base path /api/v1 (URI versioning, main.ts); endpoints carry @Permissions decorators (webhooks.controller.ts:22, 28, 34, 40, 46, 53, 59, 66, 73, 79, 86) backed by permissions.constants.ts:89-92 (guards on endpoints not yet wired - AGENTS.md). Tenant-scoped via BaseRepository (base.repository.ts:20-30). Envelopes per 00-shared/07 §2-3. All paths below are prefixed /api/v1/webhooks unless noted.


1. Subscriptions CRUD (webhooks.controller.ts:21-50)

MethodPathPermissionDTO / sourceDescription
POST/api/v1/webhookswebhook.createCreateWebhookDto (create-webhook.dto.ts:11-34)Create subscription; returns full doc incl. plaintext secret
GET/api/v1/webhookswebhook.read-List all, sort createdAt: -1, unpaginated (webhooks.service.ts:35-37)
GET/api/v1/webhooks/:idwebhook.read-Get by id; 404 'Webhook not found' (webhooks.service.ts:39-43)
PATCH/api/v1/webhooks/:idwebhook.updateUpdateWebhookDto (PartialType - all optional, update-webhook.dto.ts:4)Update any subset; 404 if missing (webhooks.service.ts:45-48)
DELETE/api/v1/webhooks/:idwebhook.delete-Soft delete; 200 { message: 'Webhook deleted' } (webhooks.controller.ts:45-50, webhooks.service.ts:50-53)

2. Operations (webhooks.controller.ts:52-90)

MethodPathPermissionSourceDescription
GET/api/v1/webhooks/:id/logswebhook.readwebhooks.service.ts:88-93Delivery attempts, newest first, hard limit 50; no pagination params
POST/api/v1/webhooks/:id/retrywebhook.updatewebhooks.service.ts:95-120Re-queue latest failed attempt (404 'No failed deliveries to retry' if none, :107-108); 200 { message: 'Retry queued' }
POST/api/v1/webhooks/:id/testwebhook.updatewebhooks.service.ts:122-140Enqueue synthetic delivery (eventType: 'WebhookTested', payload: { test: true, webhookId }); 200 { message: 'Test delivery queued' }
GET/api/v1/webhooks/:id/metricswebhook.readwebhooks.service.ts:142-156{ total, success, failed, pending } counts; 404 if webhook missing
POST/api/v1/webhooks/:id/pausewebhook.updatewebhooks.service.ts:158-161setEnabled(false); 200 { message: 'Webhook paused' }
POST/api/v1/webhooks/:id/resumewebhook.updatewebhooks.service.ts:158-161setEnabled(true); 200 { message: 'Webhook resumed' }

3. Delivery wire contract (outbound, server → subscriber)

Worker POST (not a client API, but part of the contract consumers must handle):

FieldValueSource
MethodPOSTwebhook-delivery.worker.ts:73
Content-Typeapplication/json:76
X-Webhook-SignatureHMAC-SHA256 hex of raw body using webhook.secret:77, 103-105
X-Webhook-EventeventType:78
BodyJSON.stringify(payload) (the DomainEvent.payload, domain-event.interface.ts:7):70, 80
TimeoutAbortSignal.timeout(10000) - 10 s:81
Retries3 attempts, exponential backoff 5 s (job options)webhooks.service.ts:80-83
Success2xx → log success with responseCode + response body:84-89

4. Request examples

POST /api/v1/webhooks
{ "name": "SMS Gateway", "url": "https://vendor.example.com/hooks/sms",
  "events": ["AttendanceMarked", "HomeworkSubmitted"],
  "secret": "whsec_9f2c…", "enabled": true }

PATCH /api/v1/webhooks/64f…
{ "events": ["AttendanceMarked", "PaymentCompleted"], "enabled": false }

POST /api/v1/webhooks/64f…/retry        → { "message": "Retry queued" }
POST /api/v1/webhooks/64f…/test         → { "message": "Test delivery queued" }
GET  /api/v1/webhooks/64f…/metrics      → { "data": { "total": 9, "success": 7, "failed": 1, "pending": 1 } }

5. Response shapes

  • List/single/created/updated: { data: <Doc> } (envelope interceptor, 00-shared/07). Webhook doc fields: _id, name, url, events, secret, enabled, lastTriggeredAt?, failureCount, tenantId, isDeleted, version, createdAt, updatedAt (webhook.schema.ts:8-30, base.schema.ts:10-34).
  • Logs: { data: DeliveryLog[] }; fields _id, webhookId, eventType, payload, status, responseCode?, responseBody?, attemptCount, attemptedAt, completedAt? (webhook-delivery-log.schema.ts:7-39).
  • Action endpoints: { message: string }.

6. Error map

CodeMeaningSource
401unauthenticated (JWT guard pending wiring - AGENTS.md)webhooks.controller.ts:21-90
403missing webhook.* permissionpermissions.constants.ts:89-92
400DTO validation (class-validator)create-webhook.dto.ts:11-34
404webhook missingwebhooks.service.ts:41, 46, 51
404retry with no failed deliverywebhooks.service.ts:107-108
500queue enqueue / DB failure-

7. Planned / not yet in source

Path / featureStatusSource
Inbound public webhook receiver(planned)IMPLEMENTATION_PLAN.md:48 ("(webhooks, health)", 30 req/min, 1 min window)
Logs pagination/filtering (?page&limit&status)(planned) - hard cap 50 todaywebhooks.service.ts:88-93
Secret rotation endpoint (generate + rotate in one call)(planned) - PATCH onlywebhooks.controller.ts:39-43
Replay/backfill of missed events(planned) - only latest-failure retrywebhooks.service.ts:95-120
X-Webhook-Timestamp / replay protection(planned) - body-only signaturewebhook-delivery.worker.ts:103-105
Test-series vendor integration via webhooks(planned)IMPLEMENTATION_PLAN.md:856
Event-type registry endpoint (GET /events)(planned) - picker vocabulary is staticevent-queue-map.ts:6-43