---
title: "Rotate webhook secret"
method: POST
path: "/companies/{company}/webhook-endpoints/{webhook_endpoint}/rotate-secret"
tags: ["Webhooks"]
---

# Rotate webhook secret

`POST /companies/{company}/webhook-endpoints/{webhook_endpoint}/rotate-secret`

## Request

- Base URL: `https://api.factuarea.com/v1`
- URL: `https://api.factuarea.com/v1/companies/{company}/webhook-endpoints/{webhook_endpoint}/rotate-secret`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Rotate the signing secret of a webhook endpoint; the new secret is returned once.
- The previous secret stays valid for 24 hours (`previous_secret_valid_until`).
- Rotating again within five minutes returns 422 `business_rule_violation` (subcode `webhook_secret_recently_rotated`); nothing changes.

## Path parameters

- `company` string, uuid, required
- `webhook_endpoint` string, uuid, required

## Headers

- `Idempotency-Key` string, required
- `Factuarea-Version` string, date

## Response `200`

- object
  - `data` WebhookEndpointWithSecret, required: A WebhookEndpoint returned once at creation or after secret rotation. Includes the plain-text signing secret.
    - `id` string, required
    - `object` 'webhook_endpoint', required
    - `url` string, uri, required: HTTPS callback URL.
    - `description` string, nullable, required
    - `enabled_events` string[], required: List of event types this endpoint subscribes to. `invoice.sent` is a deprecated alias of `invoice.issued` (same instant, same `data.object`): it is still accepted so existing endpoints keep working, but new integrations should subscribe to `invoice.issued`.
    - `status` string, required: Status of the endpoint: `active` (it receives deliveries), `degraded` (every delivery of the last 24 hours failed: deliveries are paused until a `ping` succeeds) or `disabled` (turned off by you: it receives none).
    - `ip_allowlist` string[], nullable, required: List of allowed source IPs.
    - `delivery_success_rate_24h` number, nullable, required
    - `last_delivery_at` string, date-time, nullable, required
    - `last_failure_at` string, date-time, nullable, required
    - `previous_secret_valid_until` string, date-time, nullable, required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `api_version` string, nullable, required: Payload version (date-based, e.g. `2026-10-01`) pinned for the events delivered to this endpoint. An endpoint created without an explicit `api_version` is pinned at creation (`2026-10-01` when the effective REST version of the request is `2026-10-01` or later, `2026-05-22` otherwise). `null` only remains if it was cleared explicitly, and then the payload version of the default REST version (currently `2026-05-22`) applies, never the latest one. An endpoint pinned to a payload version before `2026-10-01` receives invoices in the previous vocabulary: `status: sent` for an issued invoice, `sent_at` equal to the issuance instant, and no `issued_at`, `is_sent` or `sent_via`.
    - `metadata` Metadata, nullable, required: A free map of up to 50 key→value pairs for storing arbitrary structured data (values are strings up to 500 characters). Unlike `custom_fields` — an ordered list of typed `{field, value}` pairs with display semantics, present on the six document resources — `metadata` is an unordered map for opaque integration data; a document may carry both. The master resources (Client, Supplier) have no `custom_fields`, so their `metadata` doubles as the custom-fields store. **Reserved keys (read-only).** When the system auto-issues an invoice from a payment correlation (Stripe/GoCardless/MONEI), it writes `stripe_subscription_id`, `stripe_invoice_id`, `billing_reason`, `period_start` and `period_end` into that invoice metadata automatically. Do not set or overwrite them by hand — the platform owns them and a manual value may be replaced when the correlation runs.
    - `custom_headers` CustomHeaders, required: Custom HTTP headers (string → string) added to every delivery request for a webhook endpoint. Max 20 entries, each value ≤ 1024 chars. Header names are normalized to Title-Case. Reserved names (`Host`, `Content-Type`, `Factuarea-Signature`, `X-Forwarded-*`, …) are rejected. Empty object when none are set. Never put secrets here — values are returned verbatim by the API.
    - `timeout_seconds` integer, nullable, required: HTTP request timeout in seconds applied when delivering to this endpoint (1–30). `null` means the system default applies.
    - `degraded_since` string, date-time, nullable, required: Timestamp since which the endpoint is considered degraded (sustained delivery failures). `null` when healthy.
    - `secret` string, nullable, required: Signing secret, returned only at creation or after rotation. `null` only in an idempotent replay of that creation or rotation, because the secret is never stored.

## Other responses

- `400`: `parameter_unknown` with `subcode` `retired_active_profile_header`: the retired `X-Active-Profile` header was sent; the company goes in the path. `parameter_invalid_format` on `Factuarea-Version`: the header is not a `YYYY-MM-DD` date. `unsupported_api_version`: the `Factuarea-Version` date is not a supported version.
- `401`: Missing or invalid API key.
- `403`: The request is authenticated but not allowed: the API key lacks the required scope (`insufficient_scope`), the plan does not include the public API or this feature (`addon_not_active`, `feature_not_available_in_plan`), or the module is not available with a test key (`module_not_available_in_sandbox`).
- `404`: The requested resource does not exist or belongs to another company.
- `422`: Validation failed. The `error.param` field identifies which input is invalid.
- `429`: Rate limit exceeded. Retry after the duration in `Retry-After`.
- `500`: Unexpected server error.

---

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