用於從您自己的代碼發送的SMS API文檔

一個小型REST API,與工作台使用相同的帳戶、價格和餘額:發送一條訊息或最多5,000個號碼的批次,首先估算成本,跟踪每條訊息並在您的webhook URL上獲取送達事件。

基礎網址: https://sendsmsonline.cc/api/v1

快速開始

  1. 1. 建立金鑰。在工作台中開啟 API 和 webhooks。金鑰在您首次充值後開啟;每個金鑰只顯示一次,因此請複製或將其保存為文字檔。
  2. 2. 檢查成本。將相同內容 POST 到 /costs 以查看收件人、分段和總成本,無需發送。
  3. 3. 發送。將其 POST 到 /sends。回應中包含發送 ID;訊息會立即發送或在 send_at 時發送。
curl https://sendsmsonline.cc/api/v1/sends \
  -H "Authorization: Bearer $SSO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "recipients": [ { "to": "+447700900461", "fields": { "first_name": "Tom" } }, { "to": "+12015550142", "fields": { "first_name": "Ava" } } ], "text": "Hi {{first_name}}, your table is ready at 7:30.", "name": "Friday bookings", "client_ref": "bookings-1107" }'

身份驗證

在 Authorization 標頭中發送您的金鑰:Authorization: Bearer sso_live_...。金鑰為 49 個字元,並以 sso_live_ 開頭。每個帳戶最多 5 個金鑰;在工作台中撤銷一個金鑰,它會立即停止運作。價格表是公開的,不需要金鑰。

錯誤

錯誤使用 HTTP 狀態碼和一個包含穩定代碼及可顯示給用戶的句子的 JSON 主體。當請求失敗時,不會收取任何費用。

HTTP/1.1 402 Payment Required
{ "error": { "code": "insufficient_credit", "message": "Short by $3.20. Add funds to send.", "total": "8.62480", "credit": "5.42000" } }
欄位意義
400請求需要更改。
401缺少、錯誤或已撤銷的金鑰。
402餘額不足以支付總額。
404沒有此發送、訊息、國家或端點。
409傳送已經開始。
429每分鐘超過 240 次請求。

限制

  • 每個金鑰每分鐘 240 次請求,顯示於 X-RateLimit-Limit、X-RateLimit-Remaining 和 X-RateLimit-Reset (Unix 時間戳)
  • 每次請求 5,000 個號碼,每則簡訊 2,000 個字元,每則訊息 10 個分段。
  • 每個帳戶每分鐘最多傳送 300 則訊息。
  • send_at 從 10 分鐘到 30 天後。

價格

GET/api/v1/prices

GET/api/v1/prices/{country}

每個國家每則訊息(一個分段)的價格,以美元顯示,小數點後五位。無需金鑰。

{ "price": { "country": "GB", "name": "United Kingdom", "dial_code": "+44", "price_usd": "0.00868" }, "updated": "2026-11-07" }

帳戶餘額

GET/api/v1/account

{ "account": "SO8K2M4Q7X9TBA", "credit_usd": "41.27660", "currency": "USD" }

估算成本

POST/api/v1/costs

使用與傳送相同的內容,並返回其成本,無需實際傳送或收費。每個收件人的合併文字決定其分段,因此總計是精確的。

{
  "recipients": 2, "segments_min": 1, "segments_max": 1, "encoding": "gsm7", "messages_billed": 2,
  "total_usd": "0.01426", "credit_usd": "41.27660", "enough_credit": true,
  "countries": [ { "country": "GB", "recipients": 1, "price_usd": "0.00868", "subtotal_usd": "0.00868" },
                 { "country": "US", "recipients": 1, "price_usd": "0.00558", "subtotal_usd": "0.00558" } ],
  "dropped": [], "too_long": null
}

建立發送

POST/api/v1/sends

一則簡訊傳送給一個或多個號碼。當傳送被接受時,整個傳送的費用會從餘額中扣除;失敗的訊息會逐一退款。

欄位意義
to號碼需為國際格式 (+447700900461)。使用此格式或收件人。
recipients包含 to 和 fields 的物件,用於合併欄位:{ "to": "+1...", "fields": { "first_name": "Ava" } }。
text訊息最多 2,000 個字元。{{field}} 會根據每個收件人替換;缺少的值會變為空值。
send_at可選的 ISO 8601 時間,帶有偏移量或 Z。若無則立即開始傳送。
name在工作台中顯示的標籤(80 個字元)。
client_ref在 webhooks 中返回的參考(64 個字元)。
opt_out將設定中保存的退訂行添加到文字末尾。
default_country用於沒有國家代碼的號碼的 ISO 代碼。
HTTP/1.1 201 Created
{
  "send": { "id": "CA7Q29XMAB4DFK", "status": "queued", "source": "api", "recipients": 2, "segments_max": 1,
            "encoding": "gsm7", "cost_usd": "0.01426", "refunded_usd": "0.00000", "client_ref": "bookings-1107",
            "send_at": null, "created_at": "2026-11-07T10:12:03.120Z", "started_at": null, "finished_at": null },
  "dropped": [ { "value": "+4412", "code": "too_short", "message": "Too short" } ]
}

無法傳送的號碼列在 dropped 中且不會收費。代碼:no_country_code, too_short, too_long, not_a_number, wrong_length, not_covered, duplicate 和 suppressed(在您的禁止傳送清單中)。

取得或列出發送

GET/api/v1/sends/{id}

GET/api/v1/sends?limit=25&before={id}

單次傳送包括每個訊息狀態的 counts。清單按最新排序;將 next_before 作為 before 傳遞以獲取下一頁。來自工作台的傳送也會顯示在此處,並帶有 source: "web"。

訊息

GET/api/v1/sends/{id}/messages?status=failed&limit=100

GET/api/v1/messages/{id}

{ "message": { "id": "MS3D8RW0K2QJ7N", "send_id": "CA7Q29XMAB4DFK", "to": "+447700900461", "country": "GB",
  "segments": 1, "price_usd": "0.00868", "status": "delivered", "reason": null, "reason_text": null,
  "created_at": "2026-11-07T10:12:03.120Z", "sent_at": "2026-11-07T10:12:04.010Z", "done_at": "2026-11-07T10:12:09.400Z" } }

取消發送

POST/api/v1/sends/{id}/cancel

僅可取消尚未開始的預定傳送。全額費用將返還至您的餘額,且回應包含 refunded_usd。

Webhook

在工作台(API 和 webhooks)中設置一個 https URL。當訊息傳送成功或失敗時,我們會 POST 一個事件,適用於來自 API 和工作台的傳送。在 10 秒內以任何 2xx 狀態回應。失敗的傳送總共會重試 7 次:立即,然後在 1 分鐘、5 分鐘、30 分鐘、1 小時、2 小時和 3 小時後。工作台會顯示每次嘗試的狀態和回應。

POST https://your-server.example/sms-events
X-SSO-Event: message.delivered
X-SSO-Delivery: evt_5a0c9e31d2b7f4a68c
X-SSO-Timestamp: 1794132729
X-SSO-Signature: sha256=8f1c...e42a

{ "id": "evt_5a0c9e31d2b7f4a68c", "event": "message.delivered", "created": "2026-11-07T10:12:09.000Z",
  "data": { "message": { "id": "MS3D8RW0K2QJ7N", "send_id": "CA7Q29XMAB4DFK", "to": "+447700900461", "country": "GB",
  "segments": 1, "price_usd": "0.00868", "status": "delivered", "reason": null, "reason_text": null,
  "client_ref": "bookings-1107", "created_at": "...", "sent_at": "...", "done_at": "..." } } }

簽名是使用您的簽名密鑰(以 sso_whk_ 開頭)對 timestamp + "." + raw body 進行 HMAC-SHA256 計算的結果。在解析前檢查原始內容,拒絕超過 5 分鐘的時間戳,並使用傳送 ID 忽略重複。

import crypto from "node:crypto";

// rawBody: the request body exactly as received (a string), before JSON.parse
export function verify(rawBody, headers, secret) {
  const ts = headers["x-sso-timestamp"];
  const sig = headers["x-sso-signature"] || "";
  const want = "sha256=" + crypto.createHmac("sha256", secret).update(`${ts}.${rawBody}`).digest("hex");
  const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300;
  return fresh && sig.length === want.length && crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(want));
}

事件類型:message.delivered(訊息已送達)、message.failed(傳送失敗),以及透過「發送測試事件」按鈕觸發的test測試事件。

狀態與原因

欄位意義
queued等待離開我們的佇列。
sent已提交至網路,等待傳送報告。大多數報告會在幾分鐘內到達;部分網路可能需要長達 24 小時。
delivered網路確認手機已收到訊息。
failed未送達。費用已退還至您的餘額。
canceled因您取消而未發送。已退款。

失敗原因(reason 欄位):

欄位意義
network_error網路錯誤
absent手機關機或不在服務範圍內
not_in_service號碼已停用
blocked被網路或收件人封鎖
landline固網電話或無法接收簡訊的號碼
content_filter被網路的內容過濾器拒絕
expired已過期:在網路的時間限制前未收到報告
canceled在發送前取消
unknown未知的網路回應

服務檢查位於狀態頁面,API 變更記錄在更新日誌中。

取得您的 API 金鑰

創建帳戶,充值一次,並在工作台中啟用 API 和 webhooks。同一金鑰適用於所有國家。

建立免費帳戶
SMS API 文件:從您的程式碼發送大量簡訊 | SendSMSOnline