> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pubrio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 设置 Webhook

> 配置 webhook 投递目标、验证端点、校验签名和处理负载。

Webhook 是接收 monitor 结果的推荐方式。当 monitor 触发时，Pubrio 会实时向你配置的 URL 发送一个包含 JSON 负载的 POST 请求。

## 前提条件

* 拥有 monitor 访问权限的 Pubrio API 密钥
* 一个可公开访问的 HTTPS 端点（或来自 [usewebhook.com](https://usewebhook.com) 的测试 URL）

<Tip>
  **快速测试：** 使用 [usewebhook.com](https://usewebhook.com) 生成免费的临时 webhook URL。你可以在不部署任何东西的情况下检查每个传入负载。
</Tip>

***

## 步骤 1：创建带有 Webhook 投递目标的 Monitor

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.pubrio.com/monitors/create \
    -H "Content-Type: application/json" \
    -H "pubrio-api-key: YOUR_API_KEY" \
    -d '{
      "name": "My First Monitor",
      "detection_mode": "signal_first",
      "signal_types": ["jobs"],
      "signal_filters": [
        {
          "signal_type": "jobs",
          "filters": {
            "locations": ["US"]
          }
        }
      ],
      "destination_type": "webhook",
      "destination_config": {
        "webhook_url": "https://usewebhook.com/YOUR_WEBHOOK_ID",
        "headers": {
          "X-Custom-Auth": "your-secret-token"
        },
        "body": {
          "pipeline": "my-webhook"
        }
      },
      "max_records_per_trigger": 5,
      "profile_id": 1
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.pubrio.com/monitors/create",
      headers={
          "Content-Type": "application/json",
          "pubrio-api-key": "YOUR_API_KEY"
      },
      json={
          "name": "My First Monitor",
          "detection_mode": "signal_first",
          "signal_types": ["jobs"],
          "signal_filters": [
              {
                  "signal_type": "jobs",
                  "filters": {
                      "locations": ["US"]
                  }
              }
          ],
          "destination_type": "webhook",
          "destination_config": {
              "webhook_url": "https://usewebhook.com/YOUR_WEBHOOK_ID",
              "headers": {
                  "X-Custom-Auth": "your-secret-token"
              },
              "body": {
                  "pipeline": "my-webhook"
              }
          },
          "max_records_per_trigger": 5,
          "profile_id": 1
      }
  )

  print(response.json())
  ```

  ```javascript Node.js theme={null}
  const response = await fetch("https://api.pubrio.com/monitors/create", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "pubrio-api-key": "YOUR_API_KEY"
    },
    body: JSON.stringify({
      name: "My First Monitor",
      detection_mode: "signal_first",
      signal_types: ["jobs"],
      signal_filters: [
        {
          signal_type: "jobs",
          filters: {
            locations: ["US"]
          }
        }
      ],
      destination_type: "webhook",
      destination_config: {
        webhook_url: "https://usewebhook.com/YOUR_WEBHOOK_ID",
        headers: {
          "X-Custom-Auth": "your-secret-token"
        },
        body: {
          pipeline: "my-webhook"
        }
      },
      max_records_per_trigger: 5,
      profile_id: 1
    })
  });

  console.log(await response.json());
  ```
</CodeGroup>

**响应：**

```json theme={null}
{
  "data": {
    "monitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "My First Monitor",
    "detection_mode": "signal_first",
    "destination_type": "webhook",
    "is_active": true,
    "is_paused": false,
    "masked_signature": "7••••••••••••••••8df",
    "created_at": "2026-04-06T10:00:00.000Z",
    "signature": "71a2b3c4-d5e6-f789-0abc-def123456789"
  }
}
```

`headers` 对象会在每次投递时添加自定义 HTTP 请求头（用于身份验证）。`body` 对象会在 webhook 负载的根级别添加自定义字段。

<Tip>
  保存响应中的 `signature` — 你需要它来验证传入的负载。它仅在创建时和通过[签名揭示](/cn/api-reference/endpoint/monitors/signature_reveal)端点返回。
</Tip>

***

## 步骤 2：验证你的 Webhook 连接

使用[验证 Webhook](/cn/api-reference/endpoint/monitors/webhook_validate) 端点测试你的端点是否可达。这会发送一个包含占位数据的**示例负载**——不消耗积分，不获取真实信号。

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.pubrio.com/monitors/webhook/validate \
    -H "Content-Type: application/json" \
    -H "pubrio-api-key: YOUR_API_KEY" \
    -d '{
      "monitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "detection_mode": "signal_first",
      "signal_types": ["jobs"],
      "signal_filters": [
        {
          "signal_type": "jobs",
          "filters": { "locations": ["US"] }
        }
      ],
      "destination_type": "webhook",
      "destination_config": {
        "webhook_url": "https://usewebhook.com/YOUR_WEBHOOK_ID",
        "headers": { "X-Custom-Auth": "your-secret-token" },
        "body": { "pipeline": "my-webhook" }
      },
      "profile_id": 1
    }'
  ```
</CodeGroup>

成功的响应会返回发送的示例请求负载以及你的端点返回的响应——这样你可以在上线前确认连接正常。

***

## 步骤 3：使用真实数据测试

连接验证通过后，使用[处理尝试](/cn/api-reference/endpoint/monitors/process_try)端点触发一次真实运行。这会获取实际信号并投递到你的 webhook——使用 `tried_at` 设置一个近期的过去时间以确保有可用数据：

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.pubrio.com/monitors/process/try \
    -H "Content-Type: application/json" \
    -H "pubrio-api-key: YOUR_API_KEY" \
    -d '{
      "monitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "tried_at": "2026-01-01T00:00:00.000Z",
      "profile_id": 1
    }'
  ```
</CodeGroup>

<Info>
  与 validate 不同，try 端点运行真实扫描并**消耗积分**。使用它来验证真实负载正确到达，并在计划扫描启动前快速预估结果。
</Info>

***

## 步骤 4：验证签名

每个 monitor 都有唯一的签名，用于验证传入的负载确实来自 Pubrio。

<CodeGroup>
  ```bash cURL — 揭示签名 theme={null}
  curl -X POST https://api.pubrio.com/monitors/signature/reveal \
    -H "Content-Type: application/json" \
    -H "pubrio-api-key: YOUR_API_KEY" \
    -d '{
      "monitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "profile_id": 1
    }'
  ```
</CodeGroup>

```json theme={null}
{
  "data": {
    "monitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "signature": "71a2b3c4-d5e6-f789-0abc-def123456789"
  }
}
```

将此签名与传入负载中的 `monitor.monitor_id` 进行比较以验证真实性。

***

## Webhook 负载结构

负载根据 monitor 的 `detection_mode` 而不同：

<Tabs>
  <Tab title="信号优先">
    在 `signal_first` 模式中，负载包含顶层的 `signals` 数组：

    ```json theme={null}
    {
      "monitor": {
        "monitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "name": "My Signal Monitor",
        "detection_mode": "signal_first",
        "signal_types": ["jobs", "news"],
        "signal_filters": [...],
        "company_filters": {...},
        "is_company_enrichment": true,
        "is_people_enrichment": true,
        "people_enrichment_configs": [...]
      },
      "metadata": {
        "total_signals": 3,
        "total_companies": 2,
        "total_people": 5
      },
      "triggered_at": "2026-04-05T20:29:43.832Z",
      "signals": [
        {
          "signal_type": "jobs",
          "signal": {
            "signal_type": "jobs",
            "job_search_id": "...",
            "companies": [
              {
                "domain_search_id": "...",
                "company_name": "...",
                "domain": "...",
                ...
              }
            ],
            ...
          },
          "companies": [
            {
              "domain_search_id": "...",
              "company_name": "...",
              "domain": "...",
              "logo_url": "...",
              "country_code": "...",
              "company_size": 5000,
              "industry": "...",
              "people": [...],
              "emails": [...],
              "phones": [...],
              ...
            }
          ]
        },
        {
          "signal_type": "news",
          "signal": {
            "signal_type": "news",
            "news_search_id": "...",
            "news_id": "...",
            "title": "...",
            "summary": "...",
            "published_at": "...",
            "source": "...",
            "category": "...",
            "companies": [...],
            ...
          },
          "companies": [...],
          ...
        },
        ...
      ],
      "pipeline": "my-webhook"
    }
    ```

    每个信号条目包含信号详情以及关联的已补充公司和人员。
  </Tab>

  <Tab title="公司优先">
    在 `company_first` 模式中，负载包含顶层的 `companies` 数组，其中含有已补充的公司数据和嵌套的信号：

    ```json theme={null}
    {
      "monitor": {
        "monitor_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
        "name": "My Company Monitor",
        "detection_mode": "company_first",
        "signal_types": ["jobs", "news", "advertisements"],
        "signal_filters": [...],
        "company_filters": {...},
        "is_company_enrichment": true,
        "is_people_enrichment": true,
        "people_enrichment_configs": [...]
      },
      "metadata": {
        "total_signals": 4,
        "total_companies": 2,
        "total_people": 8
      },
      "triggered_at": "2026-04-03T17:45:27.228Z",
      "companies": [
        {
          "company_name": "Acme Corp",
          "domain": "acmecorp.com",
          "domain_search_id": "...",
          "country_code": "US",
          "logo_url": "...",
          "linkedin_name": "acmecorp",
          "company_size": 5200,
          "industry": "Enterprise Software",
          "estimated_revenue": 50000000,
          "founded_year": 2010,
          "company_address": "San Francisco, CA",
          "specialties": ["SaaS", "Cloud Computing", ...],
          "linkedin_url": "https://linkedin.com/company/...",
          "locations": ["US"],
          "signals": [
            {
              "signal_type": "news",
              "signal": {
                "news_id": "...",
                "title": "Acme Corp Launches New AI Product",
                "summary": "...",
                "published_at": "2026-04-03T16:35:00.000Z",
                "source": "techcrunch.com",
                "category": "launches",
                "news_category_name": "Product Launch",
                ...
              }
            },
            {
              "signal_type": "jobs",
              "signal": {
                "job_search_id": "...",
                ...
              }
            },
            ...
          ],
          "people": [
            {
              "name": "Jane Smith",
              "title": "VP of Engineering",
              "email": "j.smith@acmecorp.com",
              ...
            },
            ...
          ],
          "emails": ["info@acmecorp.com", ...],
          "phones": ["+14155551234", ...],
          "contacts": [...],
          ...
        },
        ...
      ],
      "pipeline": "my-webhook"
    }
    ```

    数组中的每家公司包含完整的补充档案、所有匹配的信号和补充的人员联系方式。
  </Tab>
</Tabs>

<Note>
  来自 `destination_config` 的自定义 `body` 字段会出现在根级别（例如上面示例中的 `"pipeline": "my-webhook"`）。
</Note>

***

## 电子邮件投递目标

对于偏好电子邮件投递的团队，将 `destination_type` 设置为 `"email"`：

```json theme={null}
{
  "destination_type": "email",
  "destination_config": {
    "email": "alerts@your-company.com"
  }
}
```

<Info>
  Pubrio 为代理商和团队提供白标邮件投递支持。[联系我们](https://pubrio.com/en/get-in-touch)了解自定义发件人域名和品牌。
</Info>

***

## 故障排除

<AccordionGroup>
  <Accordion title="Webhook 未接收到负载">
    * 确认你的端点是可公开访问的（不在防火墙或 VPN 后面）
    * 确保它返回 `200` 状态码——其他状态码会被视为失败
    * 使用[验证 Webhook](/cn/api-reference/endpoint/monitors/webhook_validate) 端点测试连通性
    * 检查[统计日志](/cn/api-reference/endpoint/monitors/statistics_logs)中的错误信息和响应码
  </Accordion>

  <Accordion title="Monitor 在失败后暂停">
    如果你的 webhook 持续返回非 200 状态码，monitor 在达到 `max_failure_trigger` 次连续失败后会暂停。修复问题后通过[更新 Monitor](/cn/api-reference/endpoint/monitors/update) 重新激活。
  </Accordion>

  <Accordion title="重复负载">
    如果投递失败且配置了重试，你可能会多次收到相同的负载。使用 `triggered_at` 或日志 ID 在你端进行去重。
  </Accordion>

  <Accordion title="负载过大">
    减小 `max_records_per_trigger` 以限制每次投递的记录数。你也可以缩小筛选范围以减少匹配的信号量。
  </Accordion>
</AccordionGroup>
