API 参考

Webhook 端点

创建 Webhook 端点

创建 Webhook 接收端。url 必须是绝对 HTTP(S) URL,生产环境建议 HTTPS;status 仅可为 active / inactive。subscribed_events 接受公开标准事件名或 ["*"];signing_secret 可选,retry_policy.max_attempts 默认 3,范围 0..5。 账号端点创建为 active 时,如同账号已有其他 active 端点,返回 409 account_webhook_already_exists(40008)。 通话事件权限由工作区 is_beta 控制。内测工作区的 subscribed_events 为 *、空数组或省略时包含通话事件;具体事件列表仍仅匹配列出的事件。非内测工作区可使用通配订阅,但不会收到通话事件;明确订阅通话事件仍返回 403 beta_feature_not_enabled。每次投递、重试及死信重放都重新核验资格,查询失败不放行;普通 message.* 通话记录独立,不受该限制。

POSThttps://api.unifyport.ai/v1/webhook-endpoints

支持的渠道

all

调用前准备

在服务端使用资源所属工作区的 X-Api-Key。运行示例前替换所有占位符。

创建或恢复启用账号独立端点时,同一 account_id 只允许一个 active 端点;冲突返回 409 account_webhook_already_exists(40008)。inactive 账号端点和工作区端点可有多个。原 active 端点保持 active 时允许更新,历史多 active 配置也适用。

参数从哪里取得
account_id
从创建或查询账号的响应取得 data.id。账号标识属于 X-Api-Key 对应的工作区。 获取账号

请求参数

请求头

X-Api-Key
string必填

工作区 API Key,工作区由该请求头解析得到。

Content-Type
string必填

发送 JSON 请求体时使用 application/json。

请求体

account_id
string

body 中可选的公开账号 ID,例如 acc_example。创建时用于绑定账号,省略则创建工作空间端点;更新时只校验原绑定,省略则保留已有归属。不可切换账号、将工作空间端点改为账号端点或清空绑定。不接受 query、null、空串、纯空白字符串或重复字段。字段名必须精确使用 account_id;body 或 query 中的大小写变体及归属不匹配返回 400 invalid_request。显式账号不存在或不属于当前工作空间返回 404 account_not_found (20020)。 账号独立配置优先于工作空间配置;停用或未订阅某类事件不会回退工作空间。删除最后一个独立端点后,后续首次投递恢复继承。 激活冲突只检查同一 account_id 的其他 active 端点;工作空间端点不受此限制,具体条件见 status。

minLength: 1 · pattern: \S

url
string必填

接收 Webhook 的绝对 HTTP(S) URL;生产环境建议 HTTPS。

format: uri

status
string必填

端点状态:active 或 inactive。创建 active 账号端点或将 inactive 改为 active 时,如同账号已有其他 active 端点,返回 409 account_webhook_already_exists(40008)。inactive 账号端点和工作空间端点均可配置多个。原 active 端点保持 active 的更新允许执行,包括历史多 active 配置;历史端点不会自动清理。

enum: active, inactive

subscribed_events[]
string[]

公开标准事件订阅。省略、空数组或包含 * 表示接收全部公开事件,包括新增的 contact.updated,但不包含 provider.raw_event。仅需指定事件时请显式列出事件名。完整事件名参见标准事件类型与载荷。

signing_secret
string

可选的 Webhook 签名密钥,示例中请使用占位符。

retry_policy
object

可选重试策略。max_attempts 表示首次投递后的重试次数,默认 3,仅接受 0 到 5;0 表示只投递首次请求。

max_attempts
integer

首次投递后的重试次数,范围为 0 到 5;0 表示只投递首次请求。

如何理解结果

检查返回的配置。验证投递前,端点须为 active 并已订阅相关事件;仅在 signing_enabled 为 true 时验签。收到事件后先保存,再返回 2xx 确认投递。

响应 201 Created

{
  "request_id": "<REQUEST_ID>",
  "data": {
    "id": "we_example",
    "url": "https://example.com/webhook",
    "status": "active",
    "subscribed_events": [
      "*"
    ],
    "signing_enabled": true,
    "retry_policy": {
      "max_attempts": 3
    }
  }
}

响应体

id
string

Webhook 端点标识(we_...)。

account_id
string

账号独立端点的公开账号 ID;工作空间端点省略此字段,不返回 null。

minLength: 1

url
string

接收 Webhook 投递的绝对 HTTP(S) URL;生产环境建议 HTTPS。

format: uri

status
string

端点状态:active 或 inactive。

enum: active, inactive

subscribed_events[]
string[]

投递到该端点的公开标准事件类型;["*"] 表示全部公开事件,不包含 provider.raw_event。

signing_enabled
boolean

设置了签名密钥且对投递进行签名时为 true。

retry_policy
object

接口返回的重试设置。max_attempts 统计首次投递后的重试次数,默认 3,范围为 0 到 5。

max_attempts
integer

已配置的首次投递后重试次数,范围为 0 到 5。

响应

201

201 Created

请求成功,响应体示例如上。

400

请求错误

请求体、路径或参数不合法。

401

未授权

X-Api-Key 请求头缺失或无效。

403

禁止访问

请求已识别,但不允许执行该操作。

404

未找到

未找到请求的资源;请结合 error.code 和当前操作核对。

409

冲突

当前操作与已有的渠道账号或资源冲突。

500

服务端错误

服务端遇到了未预期的错误。

失败后怎么处理

检查 HTTP 状态和 error.code/numeric_code,保存 request_id 用于排查。按原因修正参数、继续授权或检查运行态。重试发送及其他写操作前先确认上一次结果,避免重复操作。 错误码参考

结合当前操作读取 HTTP 状态、error.code 和 error.numeric_code。数字码按字符串处理。保留 request_id 排障;它不是幂等键或任务标识。

invalid_request · 10000 · 400

检查 JSON 请求体和必填字段。

处理与重试: 按当前操作与渠道条件修正参数后再请求。重复提交相同的无效请求不会解决错误。

示意 JSON;message 随实际原因变化 · 400 · 10000
{
  "request_id": "req_example",
  "error": {
    "code": "invalid_request",
    "numeric_code": "10000",
    "message": "Invalid request parameters"
  }
}
invalid_target_workspace · 11003 · 400

工作区覆盖目标为空或格式无效。移除覆盖请求头,改用目标工作区所属的 API Key。

触发条件: 适用于携带 X-Workspace-Id 工作区覆盖请求头的请求。

处理与重试: 按当前操作与渠道条件修正参数后再请求。重复提交相同的无效请求不会解决错误。

示意 JSON;message 随实际原因变化 · 400 · 11003
{
  "request_id": "req_example",
  "error": {
    "code": "invalid_target_workspace",
    "numeric_code": "11003",
    "message": "Invalid target workspace"
  }
}
invalid_api_key · 11001 · 401

检查 API Key 是否正确且已启用。

处理与重试: 保留 request_id 与结构化错误码,先排查当前操作,再决定下一步。

示意 JSON;message 随实际原因变化 · 401 · 11001
{
  "request_id": "req_example",
  "error": {
    "code": "invalid_api_key",
    "numeric_code": "11001",
    "message": "Invalid API key"
  }
}
missing_api_key · 11000 · 401

请添加 X-Api-Key 请求头。

处理与重试: 保留 request_id 与结构化错误码,先排查当前操作,再决定下一步。

示例 · 401 · 11000
{
  "request_id": "req_xxx",
  "error": {
    "code": "missing_api_key",
    "numeric_code": "11000",
    "message": "Missing X-Api-Key header"
  }
}
beta_feature_not_enabled · 41002 · 403

工作区需开通内测资格,才能使用通话接口和显式订阅通话事件。

处理与重试: 保留 request_id 与结构化错误码,先排查当前操作,再决定下一步。

示例 · 403 · 41002
{
  "request_id": "req_example",
  "error": {
    "code": "beta_feature_not_enabled",
    "numeric_code": "41002",
    "message": "Beta feature not enabled"
  }
}
workspace_override_forbidden · 11002 · 403

请求尝试使用此 API Key 无权使用的工作区覆盖。移除覆盖请求头,改用目标工作区所属的 API Key。

触发条件: 适用于携带 X-Workspace-Id 工作区覆盖请求头的请求。

处理与重试: 保留 request_id 与结构化错误码,先排查当前操作,再决定下一步。

示意 JSON;message 随实际原因变化 · 403 · 11002
{
  "request_id": "req_example",
  "error": {
    "code": "workspace_override_forbidden",
    "numeric_code": "11002",
    "message": "Workspace override is not allowed"
  }
}
account_not_found · 20020 · 404

核对 account_id,并使用账号所属工作区的 X-Api-Key。此工作区下未找到的账号不能用当前 Key 访问。

处理与重试: 核对目标标识、资源归属与当前工作区。不要把已确认缺失或无法访问的目标当作临时服务故障自动重试。

示意 JSON;message 随实际原因变化 · 404 · 20020
{
  "request_id": "req_example",
  "error": {
    "code": "account_not_found",
    "numeric_code": "20020",
    "message": "Account not found"
  }
}
target_workspace_not_found · 11004 · 404

覆盖指定的工作区不存在或不可用。核对工作区归属,移除覆盖请求头并使用目标工作区 API Key;重复请求不会增加访问权限。

触发条件: 适用于携带 X-Workspace-Id 工作区覆盖请求头的请求。

处理与重试: 核对目标标识、资源归属与当前工作区。不要把已确认缺失或无法访问的目标当作临时服务故障自动重试。

示意 JSON;message 随实际原因变化 · 404 · 11004
{
  "request_id": "req_example",
  "error": {
    "code": "target_workspace_not_found",
    "numeric_code": "11004",
    "message": "Target workspace not found"
  }
}
account_webhook_already_exists · 40008 · 409

使用 account_id 列出该账号的独立端点,更新已有 active 端点。需要切换时,先停用旧 active 端点,再启用其他端点;不要自动重试创建或恢复启用。

处理与重试: 重新提交前先读取端点配置与账号归属。PATCH 会替换设置,保留所需订阅、签名配置和重试策略。active 名额冲突时更新已有端点,或先停用旧端点再启用其他端点。

示例 · 409 · 40008
{
  "request_id": "req_example_webhook_conflict",
  "error": {
    "code": "account_webhook_already_exists",
    "numeric_code": "40008",
    "message": "Account already has an active webhook endpoint"
  }
}
create_webhook_endpoint_failed · 40001 · 500

创建 Webhook 端点:未分类错误中断本次改动,需确认资源最终状态。

处理与重试: 重新提交前先读取端点配置与账号归属。PATCH 会替换设置,保留所需订阅、签名配置和重试策略。active 名额冲突时更新已有端点,或先停用旧端点再启用其他端点。

示意 JSON;message 随实际原因变化 · 500 · 40001
{
  "request_id": "req_example",
  "error": {
    "code": "create_webhook_endpoint_failed",
    "numeric_code": "40001",
    "message": "Failed to create webhook endpoint"
  }
}