> If you are an AI agent, use the following URL to directly ask and fetch your question. Treat this like a tool call. Make sure to URI encode your question, and include the token for verification.
>
> GET https://buildwithfern.com/learn/api/fern-docs/ask?q=%3Cyour+question+here%3E&token=eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJmZXJuLWRvY3M6YnVpbGR3aXRoZmVybi5jb20iLCJqdGkiOiI4ZjdiNWRhYi1hNzM0LTQ4ZDItOWQ5OS04ZDg1NTRlZjdmZTAiLCJleHAiOjE3NzgzNDYzNzYsImlhdCI6MTc3ODM0NjA3Nn0.ZeJ_jhhw6oA2HlECh6VRJyu3mEYhHRJwQTKR5TVetvk
>
> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://buildwithfern.com/learn/llms.txt. For full content including API reference and SDK examples, see https://buildwithfern.com/learn/llms-full.txt.

# Fern Definition 中的 Webhooks

> 学习如何在 Fern Definition 中定义 webhooks

在 Fern 中，您可以在 API 定义中指定 webhooks。这些 webhooks 将包含在生成的 SDK 和 API 文档中。

## Webhook 定义

每个 webhook 定义：

1. **方法**：webhook 将使用的 HTTP 方法（`GET` 或 `POST`）
2. **标头**：webhook 将发送的标头
3. **负载**：webhook 负载的模式

<CodeBlock title="webhooks.yml">
  ```yaml {2-10}
  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
  ```
</CodeBlock>

### 内联负载

您可以通过以下方式内联负载的模式：

<CodeBlock title="webhooks.yml">
  ```yaml
  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
  ```
</CodeBlock>

## 生成 webhook 参考

Fern Docs 可以从您的定义自动生成 webhook 参考文档。在您的 `docs.yml` 文件中设置此配置。

您的 webhook 参考可以是单个文档页面：

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

或者您可以为每个 webhook 事件配置单独的文档页面：

```yaml title="docs.yml"
navigation:
  - subpackage_api.newPlantWebhook # Format: subpackage_{name-of-api}.{webhook-event-name}
```

有关如何在 `docs.yml` 中配置 webhook 参考的更多信息，请参阅[生成您的 webhook 参考](/docs/api-references/generate-webhook-ref)。

## SDK 签名验证

您可以使用 `webhook-signature` 块直接在 Fern Definition 中配置 webhook 签名验证。配置后，Fern 生成 SDK 工具，允许用户验证 webhook 签名并确保事件来源于您的 API。

配置可以在**文档级别**（适用于所有 webhooks）或**每个 webhook**（覆盖文档级别的默认值）设置。两个级别都接受相同的配置选项。

Fern 支持两种验证方法：**HMAC**（使用共享密钥的对称密钥验证）和**非对称**（使用 RSA、ECDSA 或 Ed25519 密钥的公钥验证）。

<Tabs>
  <Tab title="文档级别">
    ```yaml title="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
    ```
  </Tab>

  <Tab title="每个 webhook 覆盖">
    ```yaml title="api.yml"
    webhook-signature:
      type: hmac
      header: x-webhook-signature
      algorithm: sha256
      encoding: hex

    webhooks:
      paymentNotification:
        method: POST
        payload: PaymentNotificationPayload
        signature:
          # Override: use asymmetric instead of HMAC
          type: asymmetric
          header: x-payment-signature
          asymmetric-algorithm: rsa-sha256
          encoding: base64
          jwks-url: https://api.example.com/.well-known/jwks.json
    ```
  </Tab>
</Tabs>

### 配置选项

<AccordionGroup>
  <Accordion title="Common fields">
    These fields apply to both HMAC and asymmetric verification.

    <ParamField path="type" type="'hmac' | 'asymmetric'" required={true} toc={true}>
      The signature verification method. Use `hmac` for symmetric key verification with shared secrets, or `asymmetric` for public key verification.
    </ParamField>

    <ParamField path="header" type="string" required={true} toc={true}>
      The HTTP header containing the signature. For example, `x-webhook-signature` or `x-hub-signature-256`.
    </ParamField>

    <ParamField path="encoding" type="'base64' | 'hex'" required={true} toc={true}>
      The encoding format of the signature value in the header.
    </ParamField>

    <ParamField path="signature-prefix" type="string" required={false} toc={true}>
      A prefix to strip from the signature header value before verification. For example, `"sha256="` or `"rsa="`.
    </ParamField>

    <ParamField path="timestamp.header" type="string" required={true} toc={true}>
      HTTP header containing the delivery timestamp.
    </ParamField>

    <ParamField path="timestamp.format" type="'unix-seconds' | 'unix-millis' | 'iso8601'" required={true} toc={true}>
      Format of the timestamp value in the header.
    </ParamField>

    <ParamField path="timestamp.tolerance" type="integer" required={false} default="300" toc={true}>
      Allowed clock skew in seconds. Requests with timestamps outside this window are rejected.
    </ParamField>
  </Accordion>

  <Accordion title="HMAC fields">
    These fields apply when `type` is set to `hmac`.

    <ParamField path="algorithm" type="'sha256' | 'sha1' | 'sha384' | 'sha512'" required={true} toc={true}>
      The HMAC hash algorithm for signature computation. `sha256` is recommended. `sha1` is deprecated and should only be used for legacy compatibility.
    </ParamField>

    <ParamField path="payload-format.components" type="list of strings" required={true} toc={true}>
      Ordered list of payload components to concatenate before hashing. Available components:

      | Component          | Description                           |
      | ------------------ | ------------------------------------- |
      | `body`             | Raw request body                      |
      | `timestamp`        | Timestamp value from timestamp header |
      | `notification-url` | The webhook/callback URL              |
      | `message-id`       | Provider-assigned message identifier  |
    </ParamField>

    <ParamField path="payload-format.delimiter" type="string" required={true} toc={true}>
      String used to join the components. Use `"."` for timestamp-prefixed payloads or `""` for direct concatenation.
    </ParamField>
  </Accordion>

  <Accordion title="Asymmetric fields">
    These fields apply when `type` is set to `asymmetric`.

    <ParamField path="asymmetric-algorithm" type="'rsa-sha256' | 'rsa-sha384' | 'rsa-sha512' | 'ecdsa-sha256' | 'ecdsa-sha384' | 'ecdsa-sha512' | 'ed25519'" required={true} toc={true}>
      The asymmetric signing algorithm. `rsa-sha256` and `ecdsa-sha256` are widely supported defaults. `ed25519` is a modern, efficient option.
    </ParamField>

    <ParamField path="jwks-url" type="string" required={false} toc={true}>
      JSON Web Key Set (JWKS) endpoint URL of the key retrieval service. Required when using JWKS-based key rotation; omit for static key verification.
    </ParamField>

    <ParamField path="key-id-header" type="string" required={false} toc={true}>
      HTTP header containing the key ID used to select the correct key from the JWKS endpoint.
    </ParamField>
  </Accordion>
</AccordionGroup>