---
title: "Add a webhook endpoint"
method: POST
path: "/v1/webhook-endpoints"
tags: ["Events"]
---

# Add a webhook endpoint

`POST /v1/webhook-endpoints`

## Request

- Base URL: `https://api.recruitmcp.com`
- URL: `https://api.recruitmcp.com/v1/webhook-endpoints`
- Auth: one of:
  - HTTP bearer
  - OAuth 2 (authorization code, authorization URL `https://recruitmcp.com/oauth/authorize`, token URL `https://recruitmcp.com/oauth/token`, scopes: `account:manage`)

Up to 10 per account. The URL must be public https; private, loopback, and link-local addresses are refused, the address is checked again on every delivery, and redirects are not followed. Each delivery is a POST with the event as JSON and a X-RecruitMCP-Signature header: t=<unix seconds>,v1=<hex HMAC-SHA256 of "<t>.<exact request body>" with the endpoint secret>. Reject a delivery whose t is more than five minutes old. Failed deliveries are retried with backoff for about a day; use the event id to ignore duplicates.

Scope: `account:manage`. Acts on the account; keys bound to a customer are refused.

## Headers

- `Idempotency-Key` string
- `RecruitMCP-Version` '2026-10-13'

## Request body

- WebhookEndpointInput
  - `url` string: Public https URL. Private and loopback addresses are refused.
  - `events` string[]: Default ["*"].
  - `customer_id` string, nullable
  - `description` string, nullable
  - `status` 'enabled' | 'disabled'

## Response `201`

Created. The signing secret is shown once.

- WebhookEndpointCreated
  - `id` string, required
  - `object` 'webhook_endpoint', required
  - `url` string, required
  - `events` string[], required: Event types, or ["*"] for all.
  - `customer_id` string, nullable: Only events from this customer.
  - `description` string, nullable
  - `status` 'enabled' | 'disabled', required
  - `secret_hint` string: Start of the signing secret, to tell secrets apart.
  - `created_at` string, date-time
  - `updated_at` string, date-time
  - `secret` string, required: Signing secret. Shown on create and rotate only.

## Other responses

- `400`: `invalid_request` (do not retry): A field is missing or has a value this endpoint does not accept. `unsupported_version` (do not retry): RecruitMCP-Version is not a supported version.
- `401`: `unauthorized` (do not retry): Missing bearer API key.
- `403`: `forbidden` (do not retry): This route acts on the account. Keys bound to a customer cannot use it. `insufficient_scope` (do not retry): This key does not include the scope this endpoint requires.
- `409`: `conflict` (do not retry): The resource is in a state that refuses this change.
- `429`: `rate_limited` (retry): Per-key rate limit exceeded.

## Changes

- **2026-10-20** `ad27b35513a6`: 5 warning
  - added the new `approval_forced` enum value to the `error/code` response property for the response status `400`
  - added the new `approval_forced` enum value to the `error/code` response property for the response status `401`
  - added the new `approval_forced` enum value to the `error/code` response property for the response status `403`
  - added the new `approval_forced` enum value to the `error/code` response property for the response status `409`
  - …1 more

[Operation history](https://skmtc.dev/recruitmcp/apis/recruitmcp-api/changes/v1/webhook-endpoints/post.md)

---

[API](https://skmtc.dev/recruitmcp/apis/recruitmcp-api.md) · [All operations](https://skmtc.dev/recruitmcp/apis/recruitmcp-api/llms.txt) · [OpenAPI document](https://skmtc.dev/recruitmcp/apis/recruitmcp-api/revisions/ad27b35513a6?raw)
