Skip to navigation

Webhooks in the Fern Definition

View as Markdown

Fern Definition isn’t recommended for new customers and Fern isn’t accepting feature requests for this format. It remains supported for existing users.

In Fern, you can specify webhooks in your API definition. The webhooks will be included in both the generated SDKs and the API documentation.

Webhook definition

Each webhook defines:

  1. Method: The HTTP Method that the webhook will use (either GET or POST)
  2. Headers: The headers that the webhook will send
  3. Payload: The schema of the webhook payload
webhooks.yml
webhooks:
paymentNotification:
display-name: Payment Notification
docs: Receive a notification when a payment changes status
method: POST
headers:
X-Signature-Primary:
type: string
docs: An HMAC signature of the payload
payload: PaymentNotificationPayload
types:
PaymentNotificationPayload:
discriminant: notificationType
union:
queued: QueuedPaymentNotification
processing: ProcessingPaymentNotification
completed: CompletedPaymentNotification

Inlined payloads

You can inline the schema of the payload by doing the following:

webhooks.yml
webhooks:
paymentNotification:
display-name: Payment Notification
docs: Receive a notification when a payment changes status
method: POST
headers:
X-Signature-Primary:
type: string
docs: An HMAC signature of the payload
payload:
name: PaymentNotificationPayload
properties:
id:
type: string
docs: The notification id
amount: double
currency: Currency

Generate webhook reference

Fern Docs can automatically generate your webhook reference documentation from your definition. Set this up in your docs.yml file.

Your webhook reference can be a single documentation page:

docs.yml
navigation:
- api: Webhook Reference # Display name for this page
api-name: webhooks-v1 # Directory containing webhook definition

Or you can configure individual documentation pages per webhook event:

docs.yml
navigation:
- subpackage_api.newPlantWebhook # Format: subpackage_{name-of-api}.{webhook-event-name}

For more information on how to configure your webhook reference in docs.yml, see Generate your webhook reference.

SDK signature verification

Enterprise feature for SDKs

Using this feature in generated SDKs requires the Enterprise plan. To get started, reach out to support@buildwithfern.com.

You can configure webhook signature verification directly in your Fern Definition using the webhook-signature block. When configured, Fern generates SDK utilities that allow users to verify webhook signatures and ensure events originate from your API.

Configuration can be set at the document level (applies to all webhooks) or per-webhook (overrides the document-level default). Both levels accept the same configuration options.

Fern supports two verification methods: HMAC (symmetric key verification using shared secrets) and Asymmetric (public key verification using RSA, ECDSA, or Ed25519 keys).

api.yml
webhook-signature:
type: hmac
header: x-webhook-signature
algorithm: sha256
encoding: hex
webhooks:
userCreated:
method: POST
payload: UserCreatedPayload
# Inherits document-level signature config
orderCompleted:
method: POST
payload: OrderCompletedPayload
# Inherits document-level signature config

Configuration options

These fields apply to both HMAC and asymmetric verification.

type
'hmac' | 'asymmetric'Required

The signature verification method. Use hmac for symmetric key verification with shared secrets, or asymmetric for public key verification.

stringRequired

The HTTP header containing the signature. For example, x-webhook-signature or x-hub-signature-256.

encoding
'base64' | 'hex'Defaults to base64

The encoding format of the signature value in the header.

signature-prefix
string

A prefix to strip from the signature header value before verification. For example, "sha256=" or "rsa=".

timestamp.header
string

HTTP header containing the delivery timestamp. Required when timestamp is configured.

timestamp.format
'unix-seconds' | 'unix-millis' | 'iso8601'Defaults to unix-seconds

Format of the timestamp value in the header.

timestamp.tolerance
integerDefaults to 300

Allowed clock skew in seconds. Requests with timestamps outside this window are rejected.

These fields apply when type is set to hmac.

algorithm
'sha256' | 'sha1' | 'sha384' | 'sha512'Defaults to sha256

The HMAC hash algorithm for signature computation. sha256 is recommended. sha1 is deprecated and should only be used for legacy compatibility.

payload-format.components
list of strings

Ordered list of payload components to concatenate before hashing. When omitted, only the raw request body is signed. Available components:

ComponentDescription
bodyRaw request body
timestampTimestamp value from timestamp header
notification-urlThe webhook/callback URL
message-idProvider-assigned message identifier
payload-format.delimiter
string

String used to join the components. Use "." for timestamp-prefixed payloads or "" for direct concatenation. Required when payload-format.components is set.

body-hash-binding.algorithm
'sha256' | 'sha1' | 'sha384' | 'sha512'Required

Hash algorithm applied to the raw request body. Independent of algorithm, which applies to the signature itself. Set body-hash-binding when the provider transmits a hash of the body alongside a signature computed over the notification URL.

body-hash-binding.encoding
'base64' | 'hex'Defaults to base64

Encoding of the transmitted body hash.

body-hash-binding.location.type
'query-parameter'Required

Where the body hash is transmitted. Query parameters on the notification URL are the only supported location.

body-hash-binding.location.name
stringRequired

Name of the query parameter carrying the body hash.

These fields apply when type is set to asymmetric.

asymmetric-algorithm
'rsa-sha256' | 'rsa-sha384' | 'rsa-sha512' | 'ecdsa-sha256' | 'ecdsa-sha384' | 'ecdsa-sha512' | 'ed25519'Required

The asymmetric signing algorithm. rsa-sha256 and ecdsa-sha256 are widely supported defaults. ed25519 is a modern, efficient option.

payload-format.components
list of strings

Ordered list of payload components to concatenate before signing. When omitted, only the raw request body is signed. Available components:

ComponentDescription
bodyRaw request body
timestampTimestamp value from timestamp header
notification-urlThe webhook/callback URL
message-idProvider-assigned message identifier
Without timestamp in the components list, the timestamp.tolerance check can’t protect against replay attacks because the timestamp is unauthenticated. Include timestamp to ensure replay protection.
payload-format.delimiter
string

String used to join the components. Use "." for timestamp-prefixed payloads or "" for direct concatenation. Required when payload-format.components is set.

jwks-url
string

JSON Web Key Set (JWKS) endpoint URL of the key retrieval service. Required when using JWKS-based key rotation; omit for static key verification.

key-id-header
string

HTTP header containing the key ID used to select the correct key from the JWKS endpoint.