短信API发送示例:Python、Node.js、PHP与cURL
用API发送短信的Python、Node.js、PHP和cURL示例:单条与批量发送、Unicode与阿拉伯语、分段计数、送达状态Webhook以及错误处理,开发者可直接复制使用。
作者: OmniChannels.ai Editorial Team · 审阅: BroadNet Messaging Solutions Team
集成
简短回答
使用OmniChannels.ai API发送短信,需向https://api.broadnet.me/sms/sendSms发起带身份验证的POST请求,JSON请求体包含senderId、destinationNumber、message和messageType。GSM-7文本使用TEXT,阿拉伯语或emoji使用UNICODE。返回200时,响应体是纯文本的消息ID,最终送达状态稍后会推送到您的Webhook。
本页内容
要点速览
- POST /sms/sendSms需要四个字段:senderId、destinationNumber、message和messageType;响应体是纯文本的消息ID,而不是JSON。
- 阿拉伯语、emoji或任何GSM-7之外的字符,都要把messageType设为UNICODE;出现一个此类字符,整条消息就变成Unicode,每个分段也随之缩短。
- POST /sms/identify可在发送前统计字符数和分段数,让您预测一条消息会占用多少分段。
- 送达是异步的:返回200仅表示已接受,DELIVERED、FAILED或REJECTED稍后会推送到您的Webhook。
- 该API没有幂等键,所以请在发送前先记录每次发送,超时后检查状态,而不是重发。
本指南面向需要从应用发送短信、并希望获得Python、Node.js、PHP或cURL可用代码的开发者。内容涵盖单条发送、Unicode和阿拉伯语、分段计数、批量上传、送达状态Webhook和错误处理,仅使用我们短信API参考和OpenAPI规范中的端点和字段。
如何用API发送短信?
向/sms/sendSms发起带身份验证的POST请求,请求体为JSON。响应为200 OK,消息ID以纯文本形式返回。
| 项目 | 值 |
|---|---|
| 基础URL | https://api.broadnet.me(无/v1前缀) |
| 端点 | POST /sms/sendSms |
| 鉴权 | Authorization: Bearer $BROADNET_TOKEN |
| 内容类型 | application/json |
| 必填字段 | senderId、destinationNumber、message、messageType |
测试凭证在提交简短的访问申请后发放,测试发送只发往您自己已验证的号码。目前没有即时自助注册。请参阅快速入门。
curl -X POST https://api.broadnet.me/sms/sendSms \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"senderId": "OmniDemo",
"destinationNumber": "447700900123",
"message": "Your OmniDemo code is 482913",
"messageType": "TEXT"
}'
// Node.js 18+(内置fetch)
const res = await fetch("https://api.broadnet.me/sms/sendSms", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BROADNET_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
senderId: "OmniDemo",
destinationNumber: "447700900123",
message: "Your OmniDemo code is 482913",
messageType: "TEXT",
}),
});
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
const messageId = await res.text(); // 纯文本的消息ID
import os
import requests
r = requests.post(
"https://api.broadnet.me/sms/sendSms",
headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
json={
"senderId": "OmniDemo",
"destinationNumber": "447700900123",
"message": "Your OmniDemo code is 482913",
"messageType": "TEXT",
},
timeout=15,
)
r.raise_for_status()
message_id = r.text # 纯文本的消息ID,不是JSON
<?php
$payload = json_encode([
"senderId" => "OmniDemo",
"destinationNumber" => "447700900123",
"message" => "Your OmniDemo code is 482913",
"messageType" => "TEXT",
]);
$ch = curl_init("https://api.broadnet.me/sms/sendSms");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("BROADNET_TOKEN"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => $payload,
]);
$messageId = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
echo $status . " " . $messageId . PHP_EOL;
成功的响应体如下所示:
2603121407537573731
请把这个ID与您自己的记录(如订单或登录尝试)一起保存。之后就靠它来匹配送达状态。
手机号码应当使用什么格式?
使用国家区号加国内号码,仅含数字。格式遵循ITU-T E.164国际编号计划,但不带加号。
| 输入 | 是否有效 | 原因 |
|---|---|---|
447700900123 |
有效 | 国家区号44加国内号码 |
+44 7700 900123 |
无效 | 请去掉加号和空格 |
07700900123 |
无效 | 请把前导0替换为国家区号 |
请在数据库中以E.164格式(+447700900123)存储号码,并在构造请求时去掉+。我们的免费手机号码格式化工具可以帮助快速检查。
如何发送阿拉伯语、emoji或其他Unicode文本?
将messageType设为UNICODE。任何GSM-7字母表之外的字符,例如阿拉伯字母、emoji、弯引号或破折号,都会让整条消息切换为Unicode。
r = requests.post(
"https://api.broadnet.me/sms/sendSms",
headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
json={
"senderId": "OmniDemo",
"destinationNumber": "971500000000",
"message": "رمز التحقق الخاص بك هو 482913",
"messageType": "UNICODE",
"campaignName": "login-otp",
},
timeout=15,
)
在PHP中,调用json_encode时请使用JSON_UNESCAPED_UNICODE。编码决定分段大小,这是3GPP TS 23.040对短信的定义:
messageType |
单条短信 | 拆分时每段 | 适用场景 |
|---|---|---|---|
TEXT |
160个字符 | 153个字符 | 仅使用GSM-7字母表的文本 |
UNICODE |
70个字符 | 67个字符 | 阿拉伯语、西里尔字母、中文、emoji |
大多数运营商按分段计费,所以较长的阿拉伯语消息比同样长度的拉丁字母消息更贵。请阅读我们的Unicode与阿拉伯语短信指南,并试用短信字符计数器。
发送前如何统计分段数?
使用消息调用POST /sms/identify。它会返回检测到的编码、字符数、分段数和每段上限。
curl -X POST https://api.broadnet.me/sms/identify \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "message": "Your OmniDemo code is 482913" }'
{
"message": "Your OmniDemo code is 482913",
"messageType": "TEXT",
"smscount": 1,
"charCount": 28,
"charLimit": 160
}
您可以把smsParts(来自smscount)、charCount和charLimit传入发送请求。GSM-7文本在响应中可能被标记为GSM-7;发送时请使用TEXT。
如何发送给大量号码?
使用POST /sms/sendbulk,这是一个multipart/form-data请求,包含一个收件人文件和一个设置的JSON字符串。
curl -X POST https://api.broadnet.me/sms/sendbulk \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-F destinationNumberFile=@recipients.csv \
-F 'bulkRequest={"senderId":"OmniDemo","message":"Your statement is ready in the app.","messageType":"TEXT","campaignName":"oct-statements","allowDuplicate":false}'
import json
import os
import requests
bulk_request = {
"senderId": "OmniDemo",
"message": "Your statement is ready in the app.",
"messageType": "TEXT",
"campaignName": "oct-statements",
"allowDuplicate": False,
}
with open("recipients.csv", "rb") as f:
r = requests.post(
"https://api.broadnet.me/sms/sendbulk",
headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
files={"destinationNumberFile": ("recipients.csv", f, "text/csv")},
data={"bulkRequest": json.dumps(bulk_request)},
timeout=60,
)
print(r.json())
响应中包含bulkSessionId和一个带有total、validCount、invalidCount和duplicate的bulkListInfo对象。请把bulkSessionId与营销活动一起存储。任务可以通过参考文档中的端点列出、暂停、恢复和中止。您也可以在大批量发送之前,用POST /sms/lookup检查号码;请参阅我们的HLR查询指南。
如何接收送达状态?
送达状态会推送到您账户上配置的Webhook URL。一条消息依次经过SUBMITTED和SENT到达DELIVERED,或者以FAILED或REJECTED结束。您把公开的HTTPS URL提供给我们的团队即可,转售商可以为每个子账户设置一个Webhook。
负载字段因渠道而异,API规范也没有定义单一的Webhook结构,所以请先记录原始请求体,再根据您账户上的真实事件映射字段。一个最简接收端只需保存事件并迅速确认:
import express from "express";
const app = express();
app.post("/webhooks/omnichannels", express.json(), async (req, res) => {
await saveStatusEvent(req.body); // 您自己的存储;异步处理
res.sendStatus(200); // 尽快确认
});
app.listen(3000);
请让处理具备幂等性,因为同一状态可能到达两次,并且绝不要让迟到的SENT覆盖已存储的DELIVERED。如果您的端点曾经宕机,POST /sms/resendDlr可以按日期范围重新推送回执:
curl -X POST https://api.broadnet.me/sms/resendDlr \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-10-09",
"endDate": "2026-10-10",
"senderId": "OmniDemo",
"messageStatus": "DELIVERED"
}'
更多内容请阅读Webhook指南和消息送达状态详解。
如何处理错误并避免重复发送?
先处理HTTP状态,再看错误响应体。只对网络错误、429和5xx重试。
| 状态码 | 含义 | 操作 |
|---|---|---|
200 |
已接受 | 保存ID |
400 |
校验错误或缺少字段 | 修正请求 |
401 / 403 |
token错误或操作不被允许 | 修正;不要重试 |
429 |
超出速率限制 | 等待Retry-After |
500、503、504 |
服务端或上游故障 | 采用退避和抖动重试 |
API抛出的错误使用包含status、error、message、errorCode和requestUri五个字段的JSON响应体。文档中记载的REST默认限制为持续每秒200个请求;您账户的具体限制会随凭证一并确认。
该API不接受幂等键。一个请求可能成功但响应丢失,盲目重试就会发送两次。请在调用之前,先以您自己的操作ID为键写入一条待处理行,保存返回的消息ID,并在超时后先检查Webhook状态,再决定是否重发。批量发送时,请把allowDuplicate设为false。详情见错误与限制。
实战示例:区域应用的登录验证码
“Souq Rafiq”(虚构)是阿联酋的一家零售商,通过短信发送登录验证码。
- 认证服务生成六位验证码,存储带五分钟有效期的哈希,并写入一条
pending发送记录。 - 它调用
/sms/sendSms,阿拉伯语用户使用messageType=UNICODE,英语用户使用TEXT。 - 返回
200时,保存消息ID。 - Webhook处理程序把该记录标记为
DELIVERED、FAILED或REJECTED。 - 如果短暂等待后状态仍不是
DELIVERED,应用会提供重发选项,并在配置的情况下提供另一个渠道。请参阅渠道回退。 - 按号码和按IP限制验证码请求频率,可防止滥用;请参阅短信泵送防范。
常见错误有哪些?
- **对发送响应调用
r.json()。**它是纯文本。 - **字段名错误。**请使用
senderId、destinationNumber和message;to、from或text等字段不属于该端点。 - 号码中带有加号和前导零。
- 阿拉伯语**忘记使用
UNICODE,**导致文本乱码。 - **未注册的发件人ID。**有些国家会封堵或替换它们;请查看目的地的发件人ID规则,并让我们来办理注册。
- 把
200当作已送达。 - **把token放在移动应用或浏览器中,**任何人都能提取。
- **局限:**本指南展示的是常见请求。定时发送格式等可选字段,请与我们的团队确认。
OmniChannels.ai 如何提供帮助
OmniChannels.ai通过BroadNet的运营商直连发送A2P短信,支持双向短信、发件人ID、Unicode和阿拉伯语、HLR查询,并提供用于大批量的SMPP 3.4。位于https://api.broadnet.me的REST API使用Bearer token,同时覆盖WhatsApp、RCS和其他渠道,送达状态统一为一种Webhook格式。我们的团队与您一起准备发件人ID注册。请查看短信API参考或短信渠道。
常见问题
如何用Python发送短信?
使用requests库向https://api.broadnet.me/sms/sendSms POST JSON,带上Authorization: Bearer请求头以及senderId、destinationNumber、message和messageType字段。请从环境变量读取token。返回200时响应体是纯文本的消息ID,所以请使用r.text,而不是r.json()。
短信API要求什么样的手机号码格式?
国家区号加国内号码,仅含数字,不带加号、00前缀、空格或前导零。例如447700900123有效,而+44 7700 900123和07700900123无效。请在自己的数据库中以E.164格式存储号码,并在构造请求时去掉加号。
如何通过API发送阿拉伯语短信?
将messageType设为UNICODE,并以UTF-8在message字段中发送阿拉伯语文本。Unicode消息在单个分段中容纳70个字符,拆分后每段67个,而GSM-7分别为160和153个。请在真实手机上测试,并先调用/sms/identify查看分段数。
如何获取送达报告?
状态会推送到您账户上配置的Webhook URL。消息依次经过SUBMITTED和SENT,最终到达DELIVERED、FAILED或REJECTED。您的端点应保存原始事件、快速返回2xx并异步处理。如果错过了事件,POST /sms/resendDlr可以按日期范围重新推送送达回执。
如何一次向很多号码发送短信?
使用POST /sms/sendbulk,这是一个multipart请求,包含destinationNumberFile(CSV或TXT)和一个装有senderId、message和messageType的bulkRequest JSON字符串。响应会报告有效、无效和重复的号码数量,并返回一个bulkSessionId,您可以将其与营销活动一起存储。
需要注册发件人ID吗?
在许多国家需要。有些国家要求已获批的字母数字发件人ID,另一些则需要监管机构或模板标识符,API通过peId和templateId等可选字段接受它们。要求因国家而异,请查看目的地的发件人ID页面,我们的团队也可以与您一起办理注册。
资料来源
继续阅读
更多指南集成
WhatsApp消息API发送示例:cURL、Node、Python、PHP
如何用API发送WhatsApp消息:提供可运行的cURL、Node.js、Python和PHP示例,涵盖模板消息与会话消息、送达状态跟踪以及常见错误处理,方便开发者快速接入。
10 分钟阅读
集成
如何选择消息 API:CTO 选型清单
如何选择消息 API:面向 CTO 的选型清单,涵盖渠道覆盖、线路质量、Webhook、安全、限流、重试、SMPP、MCP、合规与定价,并提供加权评分表和冒烟测试方法,帮助出海企业用实测数据做出可向财务和安全团队交代的决策。
13 分钟阅读
短信与验证码
如何选择短信群发服务商:12 项检查清单
如何选择短信群发服务商:从线路、送达报告、发送方 ID 协助、计费模式、支持和合规等 12 项检查入手,并在签约前执行付费测试方案。
10 分钟阅读
