---
title: "Register a webhook signing key"
method: POST
path: "/api/policy/v1/enterprises/{enterpriseId}/webhooks/keys"
tags: ["Webhook Keys"]
---

# Register a webhook signing key

`POST /api/policy/v1/enterprises/{enterpriseId}/webhooks/keys`

Registers a new webhook signing key for an enterprise. The key can be provided
inline via a JWKS payload or referenced via a JWKS URI.

**Key ID selection:** The `keyId` (derived from the `kid` field in the JWK, or
supplied explicitly for JWKS URI registrations) must be unique within the
enterprise. Once a `keyId` is used — even if the key is later revoked — it is
**permanently tombstoned** and cannot be reused. Plan for this by choosing a
stable, unique `keyId` from the start (e.g. `my-key-v2`).

**Recommended rotation workflow:**
1. Register the new key under a new `keyId` (e.g. `my-key-v2`).
2. Update your service configuration to sign webhooks with the new key.
3. Revoke the old key only after you have confirmed the new key is working.

**Authorization:** Caller must be an admin of the specified enterprise.

## Path parameters

- `enterpriseId` string, required

## Headers

- `X-BitGo-OTP` string, required

## Request body

- RegisterWebhookKeyRequest — Request to register a new webhook signing key.
  - `jwks` object — Inline JWKS payload containing the public key(s). Mutually exclusive with jwksUri. The `kid` field inside the JWK object becomes the `keyId` for this registration. Choose a stable, unique `kid` value (e.g. `my-key-v2`) because once a `keyId` is revoked it is permanently tombstoned and cannot be reused.
    - `keys` object[], required — Array of JWK objects. Exactly one key must be provided.
  - `jwksUri` string — URI pointing to a hosted JWKS endpoint. Mutually exclusive with jwks.
  - `keyId` string — Customer-provided key identifier. Required when registering via `jwksUri` (must match the `kid` in your JWKS endpoint). Optional when registering inline JWKS (derived from the JWK `kid` field if not provided). **Permanent restriction:** Once a `keyId` is registered under an enterprise — even if the key is later revoked — the `keyId` is permanently tombstoned and cannot be reused. Attempting to re-register the same `keyId` returns a 400 error. Choose stable, unique values (e.g. `my-key-v2`) to avoid needing to update secrets and configuration after key rotation.
  - `keyName` string — Human-readable name for the key.

## Response `201`

Key successfully registered.

- RegisterWebhookKeyResponse — Response after successfully registering a webhook signing key.
  - `id` string, uuid, required — Internal UUID of the registered key.
  - `keyId` string, required — The derived key identifier.
  - `algorithm` 'EdDSA' | 'ECDSA', nullable — The signing algorithm (EdDSA or ECDSA). Null for JWKS URI registrations.
  - `jwksUri` string, nullable — The JWKS URI if the key was registered via URI.
  - `status` string, required — Status of the newly registered key.
  - `createdDate` string, date-time, required — When the key was registered.

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `403` — Forbidden
- `409` — Conflict - The request conflicts with the current state of the resource
- `500` — Server Error - Transient error please try again

---

[API](https://skmtc.net/bitgo/apis/bitgo-api.md) · [All operations](https://skmtc.net/bitgo/apis/bitgo-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/bitgo/bitgo-api/revisions/e445c15e5bee/schema)
