Webhook receiver service built with NestJS. Receives, stores, and retrieves webhooks from external services.
Follow these steps to run the project:
- Clone the repository
- Install dependencies by running
yarn - Create .env file and copy the content from .env.example
- Run the project by running
yarn dev - Call endpoints with API key (see below).
- Use
yarn testto run test in spec file - use
yarn test:e2eto run e2e test
Authentication: All webhook endpoints require an API key. Set API_KEY in .env (see .env.example). Send the key in one of two ways:
- Header:
x-api-key: <your-api-key> - Header:
Authorization: Bearer <your-api-key>
Rate limit & body size: Applied in main.ts. Rate limit: max RATE_LIMIT_MAX requests per RATE_LIMIT_WINDOW_MS (default 100 per 60s); response 429 when exceeded. Body size: JSON/urlencoded limited to BODY_SIZE_LIMIT (default 1mb); response 413 when exceeded. Set in .env: RATE_LIMIT_WINDOW_MS, RATE_LIMIT_MAX, BODY_SIZE_LIMIT.
Endpoints (all require API key):
| Method | Path | Description |
|---|---|---|
| POST | /webhooks | Create a webhook (body: source, event, optional payload) |
| GET | /webhooks | List all webhooks |
| GET | /webhooks/:id | Get a webhook by ID |
| PATCH (NEW) | /webhooks/:id | Update a webhook (body: optional source, event, payload) |
Improvements and fixes applied to the original sample code:
- NestJS and structure: Service implemented with NestJS; controller and service logic are separated for maintainability and testability.
- Webhook ID: Replaced
Math.random().toString(36)withrandomUUID()(crypto) to avoid ID collisions. - GET /webhooks/:id: Service now throws
NotFoundExceptionwhen webhook is not found instead of using raw Expressres. - PATCH /webhooks/:id – update webhook: New endpoint to update an existing webhook by ID. Body uses
UpdateWebhookDto; all fields (source,event,payload) are optional (partial update). Returns the updated webhook or 404 if not found. Note: Added to support editing webhook data after creation. - Input validation: Request body is validated via DTO (
CreateWebhookDto,UpdateWebhookDto) with class-validator;ValidationPipeis enabled globally. Create:sourceandeventrequired,payloadoptional. Update: all fields optional. - Error handling: Global
ErrorHandlerInterceptornormalizes error responses (statusCode, message, error). Removed ineffective Express error middleware. - Authentication:
ApiKeyGuardapplied globally; requests must send a valid API key viax-api-keyheader orAuthorization: Bearer <key>. Key is configured viaAPI_KEYin.env. - Rate limit & body size limit: In
main.ts,express-rate-limitlimits requests per window (env:RATE_LIMIT_WINDOW_MS,RATE_LIMIT_MAX); body parser usesBODY_SIZE_LIMIT(env, default1mb) to reject oversized payloads and reduce DoS risk. - Tests: Unit tests for
AppController(create, getAll, getById, update; including 404 cases) with mockedAppService. E2E tests for POST/GET/PATCH webhooks (with API key), 404 for update, and 401 when key is missing.