Base URL: https://api.emithq.com
Authentication: Authorization: Bearer emhq_your_key
All :appId and :epId params accept either UUID or user-defined uid.
All API requests require a Bearer token. Use your emhq_ API key.
/api/v1/auth/keys201Create a new API key (requires org:admin role via Clerk session)
{ "name": "production-key" }{ "data": { "id": "...", "key": "emhq_...", "name": "production-key" } }/api/v1/auth/keys200List active API keys (metadata only, no key values)
{ "data": [{ "id": "...", "name": "...", "lastUsedAt": "..." }] }/api/v1/auth/keys/:keyId200Revoke an API key (soft-delete)
{ "data": { "id": "...", "revoked": true } }Send webhook events for delivery to all matching endpoints.
/api/v1/app/:appId/msg202Send a webhook event. Persisted before queueing. Returns 202.
{ "eventType": "invoice.paid", "payload": { ... }, "eventId": "evt_unique" }{ "data": { "id": "msg_...", "eventType": "invoice.paid", "createdAt": "..." } }/api/v1/app/:appId/msg200List messages with optional filters: eventType, since, until. Cursor-paginated.
{ "data": [...], "iterator": "cursor", "done": false }/api/v1/app/:appId/msg/:msgId200Get a single message with all delivery attempts.
{ "data": { "id": "...", "payload": {...}, "attempts": [...] } }CRUD for webhook delivery destinations. Each endpoint has its own signing secret.
/api/v1/app/:appId/endpoint201Create an endpoint. Signing secret returned once.
{ "url": "https://example.com/hook", "eventTypeFilter": ["invoice.paid"] }{ "data": { "id": "...", "signingSecret": "whsec_...", ... } }/api/v1/app/:appId/endpoint200List endpoints. Cursor-paginated. Excludes soft-deleted.
{ "data": [...], "iterator": "cursor", "done": false }/api/v1/app/:appId/endpoint/:epId200Get a single endpoint. Signing secret is masked.
/api/v1/app/:appId/endpoint/:epId200Update an endpoint. Setting disabled:false re-enables and resets circuit breaker.
{ "url": "https://new-url.com/hook", "disabled": false }/api/v1/app/:appId/endpoint/:epId200Soft-delete an endpoint.
{ "data": { "id": "...", "deleted": true } }/api/v1/app/:appId/endpoint/:epId/test200Send a test webhook to verify endpoint connectivity.
{ "data": { "success": true, "statusCode": 200, "responseTimeMs": 42 } }Retry failed deliveries and manage the dead-letter queue.
/api/v1/app/:appId/msg/:msgId/retry200Replay all failed/exhausted delivery attempts for a message.
{ "data": { "replayed": 2, "attempts": [...] } }/api/v1/app/:appId/msg/:msgId/attempt/:attemptId/retry200Replay a single delivery attempt.
{ "data": { "attemptId": "...", "jobId": "..." } }/api/v1/app/:appId/dlq200List exhausted delivery attempts (dead-letter queue). Cursor-paginated.
{ "data": [...], "iterator": "cursor", "done": false }Read-only endpoints for monitoring and observability.
/api/v1/app/:appId/stats200Overview stats: events today, success rate, active endpoints, pending retries.
{ "data": { "eventsToday": 142, "successRate": 98.5, "activeEndpoints": 5, "pendingRetries": 3 } }/api/v1/app/:appId/endpoint-health200Per-endpoint health: success rate, avg latency, failure count, last delivery.
{ "data": [{ "url": "...", "successRate": 99.1, "avgLatencyMs": 142, ... }] }Test payload transformations without persisting anything.
/api/v1/transform/preview200Preview a transformation rule against a sample payload.
{ "payload": { ... }, "rules": [{ "sourcePath": "$.data.email", "targetField": "email" }] }{ "data": { "original": { ... }, "transformed": { "email": "..." } } }