非常抱歉,您正在使用的浏览器版本过低,无法正常访问我们的网站,请升级浏览器或使用其它浏览器访问,谢谢!
开放接口 · 短信网关

短信网关 API 文档

把企业已授权的短信发送、设备状态与短信收取能力接入自己的业务系统。本页只描述短信网关产品;其他开放能力请返回开发者中心选择。

接口地址:https://crm.xiaocall.cn 接口版本:v1 Token 有效期:7200秒 HTTPS安全传输 · JSON格式

短信网关开放接口

生产可用

企业服务器可通过已授权设备和 SIM 卡发送短信,也可以分页获取设备、全部短信、未读短信和已读短信。每个 AppKey 的未读状态相互独立,不影响企业后台。

生产地址https://crm.xiaocall.cn
鉴权AppKey + 2小时 Token
分页opaque next_cursor

快速接入

文档更新:2026-09-15
1开通产品权限平台为企业分配设备、短信发送和短信读取权限。
2创建应用凭证企业管理员创建 AppKey/AppSecret;AppSecret 仅显示一次。
3获取短期 Token用应用凭证换取7200秒 access_token,提前5分钟更新。
4调用业务接口每次同时携带 X-Access-Token 与 X-App-Key。
不要使用企业网页登录密码调用接口。AppSecret、Token、完整号码和设备标识不得写入代码仓库、普通日志或工单。

通用返回格式

所有接口均返回JSON。HTTP状态码表示请求是否成功,响应体中的code、msg和data用于程序处理。

成功响应

{
  "code": 0,
  "msg": "OK",
  "data": {}
}

失败响应

{
  "code": 400,
  "msg": "invalid_request",
  "data": []
}
字段类型说明
codeinteger0表示成功;失败时通常与HTTP状态码一致
msgstring成功时为OK或accepted;失败时为可供程序判断的错误码
dataobject / array成功时包含业务数据;失败时为空数组

Token 鉴权

POST
/openapi/v1/token
{
  "app_key": "sg_xxxxxxxxxxxxxxxxxxxxxxxx",
  "app_secret": "BASE64_APP_SECRET",
  "grant_type": "client_credentials"
}

成功响应 · HTTP 200

{
  "code": 0,
  "msg": "OK",
  "data": {
    "access_token": "OPAQUE_ACCESS_TOKEN",
    "token_type": "Bearer",
    "expires_in": 7200,
    "expires_at": "2026-09-15T12:00:00Z",
    "app_key": "sg_xxxxxxxxxxxxxxxxxxxxxxxx",
    "scope": "devices:read sms:send sms:read"
  }
}
返回字段类型说明
data.access_tokenstring短期访问Token;不得记录到普通日志
data.token_typestring固定为Bearer
data.expires_ininteger剩余有效秒数,固定7200
data.expires_atstringUTC时区的Token失效时间
data.app_keystring本Token所属AppKey
data.scopestring空格分隔的已授权接口权限

后续业务请求头

X-Access-Token: OPAQUE_ACCESS_TOKEN
X-App-Key: sg_xxxxxxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
Token 固定有效7200秒,不提供 refresh_token。AppSecret 轮换、应用停用或企业接口权限失效后,旧 Token 立即失效。

接口一览

GET

/openapi/v1/health

无副作用验证Token、企业权限和短信运行状态。

POST

/openapi/v1/messages

指定企业短信棒创建任务,平台自动选择该棒当前可发送的SIM。

GET

/openapi/v1/devices

分页获取企业可公开设备及脱敏SIM状态。

GET

/openapi/v1/messages

分页获取全部、未读或已读短信。

GET

/openapi/v1/messages/{id}

获取单条入站或出站短信详情。

POST

/openapi/v1/messages/read

把当前AppKey的入站已读水位推进到指定消息。

检查服务状态

GET
/openapi/v1/health

无副作用检查Token、企业权限和短信下行能力。只有HTTP 200且data.status为ready时,才表示当前应用可以提交短信。

成功响应 · HTTP 200

{
  "code": 0,
  "msg": "OK",
  "data": {
    "api_version": "v1",
    "product": "simgateway_sms",
    "status": "ready",
    "scope": "sms:send",
    "checked_at": "2026-09-15T10:00:00Z"
  }
}
返回字段类型说明
data.api_versionstring当前开放接口版本
data.productstring当前检查的产品标识
data.statusstringready表示可以提交短信任务
data.scopestring本接口验证的权限,固定为sms:send
data.checked_atstringUTC时区的检查时间

发送短信

POST
/openapi/v1/messages
字段类型必填说明
device_codestring是当前企业有效短信棒设备码
recipientstring是短信接收号码
contentstring是平台不限制短信字符数,支持长短信;长内容由短信棒和运营商处理,暂不支持Emoji等特殊字符
client_message_idstring否安全重试时建议传8~128字符稳定编号;省略则平台生成
sim_slotinteger否旧调用方兼容字段;通常省略,由平台自动选择
{
  "device_code": "SG-DEMO-0001",
  "recipient": "19900000002",
  "content": "接口联调测试"
}

首次接受响应 · HTTP 202

{
  "code": 0,
  "msg": "accepted",
  "data": {
    "message_id": "sms_123",
    "client_message_id": "auto_0123456789abcdef0123456789abcdef",
    "status": "queued",
    "device_code": "SG-DEMO-0001",
    "sim_slot": 0,
    "idempotent": false,
    "created_at": "2026-09-15 18:30:00"
  }
}
返回字段类型说明
data.message_idstring平台短信任务ID,用于查询发送结果
data.client_message_idstring调用方传入的幂等编号;省略时返回平台生成的编号
data.statusstring当前任务状态;刚接受时通常为queued
data.device_codestring实际使用的短信棒设备码
data.sim_slotinteger平台在该短信棒上实际选择的SIM卡槽
data.idempotentbooleanfalse为首次创建;true为返回既有幂等任务
data.created_atstring任务创建时间,格式YYYY-MM-DD HH:mm:ss
status可能为queued、sending、sent、delivered、failed、expired或canceled。accepted和queued只表示平台已接受任务,不等于运营商已经送达。
只需指定短信棒、接收号码和短信内容。平台自动选择该棒唯一可发送的SIM并生成client_message_id;如需对超时请求安全重试,调用方应主动传入稳定的client_message_id。销生客平台不按短信长度或分片计费。

获取设备

GET
/openapi/v1/devices?limit=50&cursor=...
参数默认说明
limit50每页1~100条
cursor空上页返回的不透明 next_cursor
device_code空按当前企业设备码精确筛选

成功响应 · HTTP 200

{
  "code": 0,
  "msg": "OK",
  "data": {
    "items": [{
      "device_code": "SG-DEMO-0001",
      "name": "办公室短信棒",
      "online": true,
      "last_seen_at": "2026-09-15 18:29:50",
      "sip_online": true,
      "sim_ready": true,
      "call_active": false,
      "sims": [{
        "sim_slot": 0,
        "phone_masked": "*******0001",
        "carrier": "中国移动",
        "status": "ready",
        "sms_ready": true,
        "updated_at": "2026-09-15 18:29:50"
      }]
    }],
    "next_cursor": null,
    "has_more": false,
    "limit": 50
  }
}
返回字段类型说明
data.itemsarray当前页短信棒数组
data.next_cursorstring / null下一页游标;无下一页时为null
data.has_moreboolean是否还有下一页
data.limitinteger本次请求采用的每页数量
data.items[].device_codestring企业可用于调用接口的短信棒设备码
data.items[].namestring短信棒名称
data.items[].onlineboolean最近5分钟内是否有有效心跳
data.items[].last_seen_atstring / null最近一次心跳时间
data.items[].sip_onlinebooleanSIP是否在线
data.items[].sim_readyboolean设备心跳报告的SIM是否就绪
data.items[].call_activeboolean当前是否存在活动通话
data.items[].simsarray该短信棒的脱敏SIM状态数组
data.items[].sims[].sim_slotintegerSIM卡槽编号
data.items[].sims[].phone_maskedstring只保留末4位的脱敏SIM号码
data.items[].sims[].carrierstring运营商名称
data.items[].sims[].statusstringSIM当前状态,例如ready或absent
data.items[].sims[].sms_readyboolean该SIM当前是否支持并允许发送短信
data.items[].sims[].updated_atstringSIM状态更新时间
需要 devices:read。下一页必须保持相同筛选条件;响应不返回IMEI、完整SIM号码或SIP密码。

获取全部、未读或已读短信

GET
/openapi/v1/messages?read_status=all&limit=50&cursor=...
参数默认说明
read_statusallall、unread或read;未读/已读只适用于入站短信
direction空in或out;out不能与unread/read组合
status空received、sent、delivered、failed等状态
device_code空按企业设备筛选
limit50每页1~100条
cursor空保持其他筛选不变后获取下一页

成功响应 · HTTP 200

{
  "code": 0,
  "msg": "OK",
  "data": {
    "items": [{
      "message_id": "msg_456",
      "direction": "in",
      "status": "received",
      "read_status": "unread",
      "device_code": "SG-DEMO-0001",
      "sim_slot": 0,
      "from": "19900000002",
      "to": "19900000001",
      "content": "收到,谢谢",
      "created_at": "2026-09-15 18:35:00",
      "sent_at": null,
      "received_at": "2026-09-15 18:35:00",
      "error_code": ""
    }],
    "next_cursor": null,
    "has_more": false,
    "limit": 50,
    "read_status": "all",
    "unread_count": 1,
    "read_through_message_id": null
  }
}
返回字段类型说明
data.itemsarray当前页短信对象数组
data.next_cursorstring / null下一页游标;无下一页时为null
data.has_moreboolean是否还有下一页
data.limitinteger本次请求采用的每页数量
data.read_statusstring本次查询采用的已读筛选:all、unread或read
data.unread_countinteger当前筛选设备和状态范围内的入站未读总数
data.read_through_message_idstring / null当前AppKey已确认处理到的最后一条入站短信

短信对象字段

返回字段类型说明
message_idstring短信公开ID;出站为sms_前缀,入站为msg_前缀
directionstringin为接收短信,out为发送短信
statusstring短信状态,例如received、queued、sent、delivered或failed
read_statusstring入站为read/unread;出站固定为not_applicable
device_codestring关联的短信棒设备码
sim_slotinteger实际使用或接收短信的SIM卡槽
fromstring短信发送方号码
tostring短信接收方号码
contentstring短信正文
created_atstring平台记录创建时间
sent_atstring / null发送时间;未发送或入站短信可能为null
received_atstring / null接收时间;出站短信通常为null
error_codestring失败原因代码;无错误时为空字符串
需要 sms:read。列表拉取不会自动标记已读;入站消息返回read/unread,出站消息返回not_applicable。游标与筛选条件绑定,修改条件会返回cursor_invalid。

获取短信详情

GET
/openapi/v1/messages/{message_id}

把列表或发送接口返回的message_id放入路径。出站短信ID以sms_开头,入站短信ID以msg_开头。

成功响应 · HTTP 200

{
  "code": 0,
  "msg": "OK",
  "data": {
    "message": {
      "message_id": "sms_123",
      "direction": "out",
      "status": "sent",
      "read_status": "not_applicable",
      "device_code": "SG-DEMO-0001",
      "sim_slot": 0,
      "from": "19900000001",
      "to": "19900000002",
      "content": "接口联调测试",
      "created_at": "2026-09-15 18:30:00",
      "sent_at": "2026-09-15 18:30:08",
      "received_at": null,
      "error_code": ""
    }
  }
}
返回字段类型说明
data.messageobject单条短信对象,内部字段与上方短信对象字段表一致

确认入站短信已读

POST
/openapi/v1/messages/read
{
  "through_message_id": "msg_456"
}

成功响应 · HTTP 200

{
  "code": 0,
  "msg": "OK",
  "data": {
    "through_message_id": "msg_456",
    "read_at": "2026-09-15 18:40:00",
    "idempotent": false
  }
}
返回字段类型说明
data.through_message_idstring当前AppKey确认处理到的最后一条入站短信ID
data.read_atstring已读水位更新时间
data.idempotentbooleanfalse表示本次推进水位;true表示此前已经处理到该位置或更后

把当前 AppKey 的已读水位推进到指定入站消息,表示该消息及更早入站短信均已处理。重复提交幂等,水位不能回退。

不同AppKey使用独立已读水位,不会互相影响,也不会改变企业后台会话未读数。带sms:read的新AppKey从签发时最新入站短信开始,历史数据仍可用read_status=all分页查询。

常见错误码

HTTPmsg处理
400invalid_request检查JSON字段、类型和Content-Type
400cursor_invalid下一页必须保持原筛选条件,或游标已损坏
400read_status_direction_conflict未读/已读筛选只能用于入站短信
401app_credentials_invalid检查AppKey/AppSecret并重新获取Token
401access_token_invalid检查X-Access-Token和X-App-Key
403scope_denied / ip_denied检查产品权限与调用方出口IP
404device_not_found / message_not_found检查资源是否属于当前企业
409idempotency_conflict同一client_message_id不能提交不同内容
409read_cursor_busy / read_cursor_changed稍后使用同一through_message_id幂等重试
503openapi_disabled / token_store_unavailable联系平台检查产品开关或Token存储