Wazo REST API 使用详解
Wazo Platform v26.10 REST API 全解——confd/auth/webhookd/sysconfd 四大服务、User+Line+Extension 绑定实战、Webhook 事件推送、WebSocket 实时事件、ACL 权限模型与 SDK
Wazo REST API 使用详解
目标:完整梳理 Wazo Platform v26.10 的 REST API 体系——认证流程、四大服务 API 矩阵(confd/auth/webhookd/sysconfd)、配置 CRUD 实战示例(User + Line + Extension 绑定完整链路)、事件推送、错误码约定与 ACL 权限模型。所有命令都是真实可执行的 curl 调用,响应 JSON 为结构示例(生产数据会不同)。
一、环境信息
- Wazo Platform 版本:26.10(2026-10-12 发布)
- API 版本:confd 1.1、auth 0.1、webhookd 1.0、sysconfd 1.0
- 基础 URL:
https://<你的 Wazo IP 或域名>/api(通过 Nginx 统一入口) - 官方 OpenAPI 控制台:https://wazo-platform.org/documentation (填入你的 Wazo IP 即可在线调用)
- 本文查询日期:2026-10-27
二、API 总览
2.1 四大 API 服务
Wazo 的 REST API 由四个微服务分别提供,每个服务有独立的端口和 URL 前缀,对外统一经 Nginx 反代到 :443/api/<服务>/ 路径:
| 服务 | Nginx 前缀 | 直接端口 | 职责 |
|---|---|---|---|
| wazo-confd | /api/confd/1.1/ | 127.0.0.1:9486 | PBX 配置 CRUD——用户、分机、中继、IVR、队列、语音信箱、会议 |
| wazo-auth | /api/auth/0.1/ | 127.0.0.1:9497 | 认证鉴权——用户登录、token 生成、ACL 策略、OAuth2 |
| wazo-webhookd | /api/webhookd/1.0/ | 127.0.0.1:9800 | Webhook 管理——事件到 HTTP endpoint 的推送规则 |
| wazo-sysconfd | /api/sysconfd/1.0/ | 127.0.0.1:8668 | 系统管理——网络接口、resolv.conf 等服务器侧配置 |
2.2 confd API 资源矩阵(最核心、最常用)
wazo-confd 是 Wazo 的配置中枢,覆盖 50+ 资源端点:
| 资源 | 方法 | 说明 |
|---|---|---|
/users | GET/POST | 用户(SIP account 上层抽象) |
/users/{uuid} | GET/PUT/DELETE | 单个用户 |
/lines | GET/POST | 物理分机(PJSIP/SCCP 注册端点) |
/extensions | GET/POST | 逻辑分机(短号,如 1001) |
/pjsip | GET/POST | PJSIP trunk / endpoint |
/incalls | GET/POST | 入呼规则(按时间/来向匹配) |
/outcalls | GET/POST | 出呼规则(选择中继组、前缀剥离) |
/trunks | GET/POST | SIP trunk(运营商对接) |
/queues | GET/POST | 呼叫队列(ACD) |
/groups | GET/POST | 静态组(同时振铃) |
/voicemails | GET/POST | 语音信箱 |
/meetings | GET/POST | 会议(MeetMe/BConfBridge) |
/ivr | GET/POST | 自动语音应答 |
/funckeys | GET/POST | 功能键配置 |
/contact_directories | GET/POST | 通讯录 |
/agents | GET/POST | 坐席(Agent) |
/agent-skill | GET/POST | 坐席技能(Skills-based Queue) |
/infos | GET | 系统版本与 UUID(不需要认证但返回有限) |
/cdr | GET | 通话详细记录(只读查询) |
2.3 通用 URL 参数
confd 支持统一的查询过滤参数:
GET /1.1/<resource>?limit=X&offset=Y&order=col&direction=asc|desc&search=keyword
| 参数 | 说明 |
|---|---|
limit | 返回条数上限 |
offset | 跳过前 N 条 |
order | 按某列排序 |
direction | asc 或 desc |
search | 关键字模糊搜索 |
三、认证与首次调用
3.1 认证流程三步曲
[你的应用] → POST /api/auth/0.1/token(带用户密码) → 拿到 token
[你的应用] → 每个请求 Header 带 X-Auth-Token: <token>
[Wazo] → 校验 token + ACL → 返回数据
注意:所有 REST API 都是 HTTPS,Wazo 用自签证书,curl 需加 -k 跳过验证。
3.2 获取 token
方式一:直接 curl(推荐,无需在服务器上装 wazo-auth-cli):
# 把 wazo.example.com 换成你的 Wazo 地址
# rest-api-user / q1w2e3r4 是安装向导里设置的 API 用户
curl -sk -X POST \
-u rest-api-user:q1w2e3r4 \
-H 'Content-Type: application/json' \
-d '{"expiration": 3600}' \
https://wazo.example.com/api/auth/0.1/token | python3 -m json.tool
# 典型响应:
# {
# "data": {
# "expires_at": "2026-10-27T23:50:15+08:00",
# "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NjE2MzIwMTV9.xxxxxxxxxxxxxxxxxxxxxx"
# },
# "application": {
# "name": "rest-api-user",
# "uuid": "b3e8f291-485a-4f0b-bc1d-7e9a2f3c4b5e"
# }
# }
方式二:服务器上用 wazo-auth-cli:
wazo-auth-cli token create \
--auth-user rest-api-user \
--auth-password q1w2e3r4 2>/dev/null
# 输出同上,直接 JSON
3.3 验证 token 并获取系统信息
export TOKEN="从上面复制的 token 值"
# 获取 Wazo 版本
curl -sk -X GET \
-H "X-Auth-Token: ${TOKEN}" \
https://wazo.example.com/api/confd/1.1/infos | python3 -m json.tool
# 响应:
# {
# "wazo_version": "26.10",
# "version": "26.10",
# "uuid": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
# "stat_socket_path": "/var/run/wazo-asterisk/ami/wazo"
# }
3.4 ACL 权限模型
💡 技术拓展:Wazo 的 ACL(Access Control List)和常见 RBAC(Role-Based Access Control)是两套不同的设计——
模型 代表 权限表达 适合场景 RBAC Kubernetes / 大多数 SaaS Role 绑定一组 Permission 角色清晰的场景(admin/operator/user) Wazo ACL Wazo Platform "confd.users.create"、"auth.#"、"websocket"这种点分路径 +#通配微服务细粒度权限,每个服务自己暴露 ACL 路径 Wazo ACL 示例:
"auth.#"→ 拥有所有 auth 端点权限"confd.users.read"→ 只读 confd 的 users 资源"websocket"→ 允许建立 WebSocket 实时事件连接"cdr.#"→ 允许查询 CDR(通话记录)
创建一个"只能读 confd 和查 CDR"的受限 API 用户:
# 1. 创建 ACL 策略(Policy)
curl -sk -X POST \
-H "X-Auth-Token: ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"name": "readonly-ops",
"acl": [
"confd.users.read",
"confd.lines.read",
"confd.extensions.read",
"confd.trunks.read",
"confd.queues.read",
"cdr.#"
]
}' \
https://wazo.example.com/api/auth/0.1/policies | python3 -m json.tool
# → 返回 policy uuid
# 2. 创建 API 用户并绑定 Policy
curl -sk -X POST \
-H "X-Auth-Token: ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"username": "readonly",
"password": "q1w2e3r4",
"purpose": "external_api",
"enabled": true
}' \
https://wazo.example.com/api/auth/0.1/users
# 3. 把 Policy 绑定到用户
curl -sk -X PUT \
-H "X-Auth-Token: ${TOKEN}" \
"https://wazo.example.com/api/auth/0.1/users/<user_uuid>/policies/<policy_uuid>"
四、配置 CRUD 实战
4.1 核心概念:User ↔ Line ↔ Extension 三角绑定
这是理解 Wazo 配置的最关键概念——三者是分离的,需要分别创建再绑定:
User(抽象人 / 账号)
↓ 绑定到
Line(物理 SIP 注册端点)
↓ 绑定到
Extension(逻辑短号,如 1001)
4.2 完整链路:创建一个可用 SIP 分机
Step 1:创建 User
curl -sk -X POST \
-H "X-Auth-Token: ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"firstname": "张三",
"lastname": "技术部",
"username": "zhangsan",
"password": "q1w2e3r4",
"mobile_phone_number": "13800138000",
"email": "zhangsan@example.com"
}' \
https://wazo.example.com/api/confd/1.1/users | python3 -m json.tool
# 响应:
# {
# "id": "7d4b4b2c-2a11-45c5-8b1a-9f8c6a4b3d2e", ← 记下这个 user uuid
# "firstname": "张三",
# "lastname": "技术部",
# ...
# }
Step 2:创建 Extension(逻辑分机号)
curl -sk -X POST \
-H "X-Auth-Token: ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"exten": "1001",
"context": "default",
"type": "user"
}' \
https://wazo.example.com/api/confd/1.1/extensions | python3 -m json.tool
# 响应(节选):
# {
# "id": "4a8e3b1c-...", ← extension uuid
# "exten": "1001",
# ...
# }
Step 3:创建 Line(PJSIP SIP 账号)
curl -sk -X POST \
-H "X-Auth-Token: ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"protocol": "pjsip",
"name": "张三-1001",
"config": {
"username": "zhangsan-1001",
"secret": "q1w2e3r4",
"context": "default",
"transport": "udp",
"codec_prefs": ["ulaw", "alaw", "opus"],
"nat": {"force_rport": true, "rewrite_contact": true}
}
}' \
https://wazo.example.com/api/confd/1.1/lines | python3 -m json.tool
# 响应(节选):
# {
# "id": "c3b9e2f1-...", ← line uuid
# "protocol": "pjsip",
# ...
# }
Step 4:把 Extension 绑定到 Line
# 先记下 extension uuid 和 line uuid
EXTENSION_UUID="从上一步复制"
LINE_UUID="从上一步复制"
curl -sk -X PUT \
-H "X-Auth-Token: ${TOKEN}" \
"https://wazo.example.com/api/confd/1.1/lines/${LINE_UUID}/extension/${EXTENSION_UUID}"
# 返回 HTTP 204 No Content,没 body 是正常的
Step 5:把 Line 绑定到 User
USER_UUID="从 Step 1 复制"
LINE_UUID="从 Step 3 复制"
curl -sk -X PUT \
-H "X-Auth-Token: ${TOKEN}" \
"https://wazo.example.com/api/confd/1.1/users/${USER_UUID}/lines/${LINE_UUID}"
# HTTP 204
Step 6:验证绑定结果
# 列出用户及其所有绑定
curl -sk -H "X-Auth-Token: ${TOKEN}" \
"https://wazo.example.com/api/confd/1.1/users/${USER_UUID}" | python3 -m json.tool
# 响应:
# {
# "id": "7d4b4b2c-...",
# "firstname": "张三",
# "lines": ["c3b9e2f1-..."], ← 已绑定
# "extensions": ["4a8e3b1c-..."], ← 已绑定
# ...
# }
到这一步,话机配置 SIP 账号 zhangsan-1001 / q1w2e3r4 就能注册到 Wazo 了。注意绑定后 Asterisk 配置自动 reload,不需要手动重启。
4.3 创建一个入呼规则(Incall)
入呼规则(Incall)决定"某个 DID 号码呼进来后怎么路由":
curl -sk -X POST \
-H "X-Auth-Token: ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"name": "销售热线",
"extensions": [
{"exten": "5551234", "context": "default"}
],
"destination": {
"type": "queue",
"value": "queue-uuid-xxxxx"
},
"caller_id_mode": "default",
"enabled": true
}' \
https://wazo.example.com/api/confd/1.1/incalls | python3 -m json.tool
4.4 创建一个 SIP Trunk(出呼用)
curl -sk -X POST \
-H "X-Auth-Token: ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"name": "运营商A",
"context": "default",
"protocol": "pjsip",
"config": {
"sip_version": "RFC3261",
"auth": {
"username": "trunk-user",
"password": "trunk-password"
},
"register": {
"sip_server": "sip.carrier-a.com",
"transport": "tcp"
},
"endpoint": {
"outbound_auth": {
"username": "trunk-user",
"password": "trunk-password"
},
"aor": {
"contact": "sip:trunk-user@sip.carrier-a.com"
},
"auth": {
"username": "trunk-user",
"password": "trunk-password"
}
}
}
}' \
https://wazo.example.com/api/confd/1.1/trunks | python3 -m json.tool
4.5 查询 CDR(通话记录)
# 查最近 10 条通话
curl -sk -H "X-Auth-Token: ${TOKEN}" \
"https://wazo.example.com/api/confd/1.1/cdr?limit=10&direction=asc" | python3 -m json.tool
# 响应:
# {
# "total": 1024,
# "items": [
# {
# "id": "1",
# "date": "2026-10-27T14:20:10",
# "duration": 45,
# "type": "internal",
# "source_name": "张三",
# "source_exten": "1001",
# "destination_exten": "1002",
# "destination_name": "李四",
# "answer": "2026-10-27T14:20:12",
# "end": "2026-10-27T14:20:55",
# "recordings": ["2026/10/27/1/call-recording.wav"]
# },
# ...
# ]
# }
五、Webhookd:事件推送
5.1 简介
wazo-webhookd 把 PBX 事件(来电振铃、接通、挂机、录音完成等)推送到你指定的 HTTP endpoint。适合开发 CRM 弹屏、监控告警等集成。
5.2 注册一个 Webhook
curl -sk -X POST \
-H "X-Auth-Token: ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{
"name": "CRM 来电弹屏",
"url": "https://crm.example.com/webhooks/wazo",
"events": [
"call_created",
"call_answered",
"call_ended",
"voicemail_received"
],
"method": "POST",
"body": "form-data",
"verify_certificate": true,
"timeout": 10
}' \
https://wazo.example.com/api/webhookd/1.0/subscriptions | python3 -m json.tool
5.3 支持的事件类型
| 事件 | 说明 |
|---|---|
call_created | 来电振铃时(刚进入拨号计划) |
call_answered | 通话接通 |
call_ended | 通话结束(包含挂机原因) |
call_hangup | 任意一端挂机 |
voicemail_received | 新语音信箱留言 |
meeting_started / meeting_ended | 会议开始 / 结束 |
agent_status | 坐席状态变更(Ready/Busy/DND) |
recording_started / recording_ended | 录音开始 / 结束 |
user_created / user_deleted | 用户变更 |
5.4 推送 Payload 示例(call_ended)
{
"event_name": "call_ended",
"data": {
"call_id": "SIP/trunk-inbound-00000042",
"source_number": "5551234",
"source_name": "外部来电",
"destination_number": "5556789",
"destination_name": "销售热线",
"answer_time": "2026-10-27T14:20:12Z",
"end_time": "2026-10-27T14:20:55Z",
"hangup_cause": "NORMAL_CLEARING",
"duration_seconds": 43
},
"timestamp": "2026-10-27T14:20:55Z"
}
六、WebSocket 实时事件
6.1 建立连接
WebSocket 端点:wss://<Wazo>/ws/?token=<你的 auth token>
# Python 示例
import asyncio, websockets, json
TOKEN = "从 auth 拿到的 token"
URI = f"wss://wazo.example.com/ws/?token={TOKEN}"
async def listen():
async with websockets.connect(URI, ssl=False) as ws:
while True:
msg = await ws.recv()
data = json.loads(msg)
print(f"[{data['wazo_tenant_uuid']}] {data['name']}: {json.dumps(data['data'])}")
asyncio.run(listen())
6.2 事件输出示例
[tenant-uuid-xxx] CallCreated: {"call_id":"SIP/2001-00000012","source":"5551234","destination":"2001"}
[tenant-uuid-xxx] CallAnswered: {"call_id":"SIP/2001-00000012","answered_by":"sip:2001@10.0.0.50"}
[tenant-uuid-xxx] CallEnded: {"call_id":"SIP/2001-00000012","end_time":"2026-10-27T14:30:00Z","duration":120}
[tenant-uuid-xxx] UserStatusUpdate: {"user_uuid":"user-xxx","status":"busy"}
七、REST API 错误码与响应约定
7.1 HTTP 状态码
| 码 | 含义 | 常见场景 |
|---|---|---|
| 200 | 成功 | GET 查询 / PUT 修改 |
| 201 | 创建成功 | POST 创建(响应体含新资源) |
| 204 | 删除或无响应 | PUT/PATCH 成功、DELETE 成功 |
| 400 | 请求参数错误 | body JSON 格式错、必填字段缺失 |
| 401 | 未认证 | token 缺失、过期 |
| 403 | 禁止 | ACL 没有对应权限 |
| 404 | 资源不存在 | uuid 拼错 / 资源已被删除 |
| 412 | 前置条件失败 | User + Line 绑定前 User 必须存在 |
| 500 | 服务器内部错误 | 查 journalctl -u wazo-confd 日志 |
7.2 错误响应格式
confd 返回数组形式(哪怕只有一个错误):
# 示例:创建用户时漏填 必填字段
curl -sk -X POST \
-H "X-Auth-Token: ${TOKEN}" \
-H 'Content-Type: application/json' \
-d '{"firstname":"测试"}' \
https://wazo.example.com/api/confd/1.1/users | python3 -m json.tool
# 响应:
# [
# "Error(s) while validating data",
# "lastname: Missing data for required field",
# "username: Missing data for required field"
# ]
八、分页 / 过滤 / 排序实战
# 分页:第 3 页,每页 50 条
curl -sk -H "X-Auth-Token: ${TOKEN}" \
"https://wazo.example.com/api/confd/1.1/users?limit=50&offset=100" | python3 -m json.tool
# 响应:
# {
# "total": 237, ← 总条数
# "items": [ ... 50 条 ... ]
# }
# 搜索:按分机号或用户名模糊匹配
curl -sk -H "X-Auth-Token: ${TOKEN}" \
"https://wazo.example.com/api/confd/1.1/users?search=zhangsan&limit=10"
# 排序:按创建时间倒序
curl -sk -H "X-Auth-Token: ${TOKEN}" \
"https://wazo.example.com/api/confd/1.1/users?order=created_at&direction=desc&limit=10"
九、常见问题(FAQ)
Q1: curl 报错 "SSL certificate problem: self signed certificate"?
加 -k 跳过验证即可:
curl -sk ... https://wazo.example.com/api/confd/1.1/infos
生产环境建议配 CA 证书或 Let's Encrypt,然后用 --cacert 指定 CA。
Q2: token 过期了怎么办?
Wazo token 默认有效期 3600 秒(1 小时)。过期后所有请求返回 401。两种应对:
- Web 应用:用 WebSocket 监听 token 过期事件(会触发 4003 close frame),自动重新获取
- 服务端脚本:捕获 401 后重新 POST /auth/0.1/token 获取,重试原请求
Q3: 创建 PJSIP Trunk 后注册不上运营商?
排查步骤:
# 1. 先看 wazo-confd 里 trunk 是否创建成功
curl -sk -H "X-Auth-Token: ${TOKEN}" \
"https://wazo.example.com/api/confd/1.1/trunks?search=运营商A"
# 2. 看 Asterisk PJSIP 注册状态
asterisk -rx "pjsip show registrations"
# 应该看到 "Registered";如果是 "Rejected" 或 没记录 → 继续
# 3. 看 Asterisk 日志
tail -50 /var/log/asterisk/full
# 搜 "registration" / "401" / "403" 关键字
# 4. 确认运营商要求的注册方式(IP auth vs 用户名密码)
Q4: confd API 调用返回 403 "forbidden"?
你的 API 用户缺少对应的 ACL。需要:
# 用 root token 给用户加策略
curl -sk -X PUT \
-H "X-Auth-Token: <root_token>" \
"https://wazo.example.com/api/auth/0.1/users/<user_uuid>/policies/<policy_uuid>"
常用 ACL 速查:
| ACL | 允许的操作 |
|---|---|
confd.# | 所有 confd 端点 |
confd.users.create | 创建用户 |
confd.users.read | 只读用户 |
auth.# | 所有 auth 端点 |
websocket | WebSocket 实时事件 |
cdr.# | 查询 CDR |
webhookd.# | 管理 Webhook |
Q5: 有没有 Python SDK 可用?
有——wazo-sdk:
pip install wazo-sdk
基本用法:
from wazo_auth_client import Client as AuthClient
from wazo_confd_client import Client as ConfdClient
# 认证
auth = AuthClient(host="wazo.example.com", verify_certificate=False)
token = auth.token.new(username="rest-api-user", password="q1w2e3r4", expiration=3600)["token"]
# 使用 confd
confd = ConfdClient(host="wazo.example.com", token=token, verify_certificate=False)
users = confd.users.list()
for u in users["items"]:
print(u["firstname"], u["lastname"], u["username"])
十、参考链接
| 链接 | 说明 |
|---|---|
| https://wazo-platform.org/documentation | Wazo 官方 OpenAPI 控制台(填入 IP 后在线调用) |
| https://wazo-platform.org/uc-doc/api_sdk/rest_api/ | REST API 文档总入口 |
| https://wazo-platform.org/uc-doc/api_sdk/rest_api/conventions/ | REST API 约定(状态码、参数格式) |
| https://wazo-platform.org/uc-doc/api_sdk/rest_api/quickstart/ | API 快速入门 |
| https://wazo-platform.org/uc-doc/api_sdk/rest_api/examples | REST API 实战示例(含 curl / Python) |
| https://wazo-platform.org/documentation/console/configuration | confd 在线 Swagger 控制台 |
| https://wazo-platform.org/uc-doc/contributors/network | 各服务端口与网络要求 |
| https://www.quzuo.net/document/6ijNclQUrvYh | 本平台 Wazo Debian 12 安装指南 |
| https://www.quzuo.net/document/wKBUGZqNuuED | 本平台 Wazo 配置参数详解 |