Dokumentasi API SMS untuk menghantar dari kod anda sendiri

API REST kecil pada akaun yang sama, harga dan kredit seperti ruang kerja: hantar mesej atau kelompok sehingga 5,000 nombor, anggarkan kos terlebih dahulu, ikuti setiap mesej dan dapatkan event penghantaran di URL webhook anda.

URL Asas: https://sendsmsonline.cc/api/v1

Mulakan cepat

  1. 1. Buat kunci. Dalam ruang kerja, buka API dan webhook. Kunci akan dibuka selepas top-up pertama anda dikreditkan; setiap kunci hanya ditunjukkan sekali, jadi salin atau simpan sebagai fail teks.
  2. 2. Semak kos. POST badan yang sama ke /costs untuk melihat penerima, segmen dan jumlah tanpa menghantar.
  3. 3. Hantar. POST ke /sends. Jawapan mengandungi ID penghantaran; mesej akan dihantar serta-merta atau pada 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" }'

Pengesahan

Hantar kunci anda dalam header Pengesahan: Authorization: Bearer sso_live_.... Kunci terdiri daripada 49 aksara dan bermula dengan sso_live_. Sehingga 5 kunci setiap akaun; batalkan satu dalam ruang kerja dan ia akan berhenti berfungsi serta-merta. Senarai harga adalah awam dan tidak memerlukan kunci.

Ralat

Ralat menggunakan kod status HTTP dan badan JSON dengan kod stabil dan ayat yang boleh anda tunjukkan kepada seseorang. Tiada bayaran dikenakan apabila permintaan gagal.

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" } }
MedanMaksud
400Permintaan memerlukan perubahan.
401Kunci hilang, salah atau dibatalkan.
402Kredit tidak mencukupi untuk jumlah tersebut.
404Tiada penghantaran, mesej, negara atau titik akhir seperti itu.
409Penghantaran telah bermula.
429Lebih daripada 240 permintaan dalam seminit.

Had

  • 240 permintaan seminit setiap kunci, ditunjukkan dalam X-RateLimit-Limit, X-RateLimit-Remaining dan X-RateLimit-Reset (saat unix).
  • 5,000 nombor setiap permintaan, 2,000 aksara setiap teks, 10 segmen setiap mesej.
  • Mesej keluar sehingga 300 seminit setiap akaun.
  • send_at dari 10 minit hingga 30 hari ke hadapan.

Harga

GET/api/v1/prices

GET/api/v1/prices/{country}

Harga setiap mesej (satu segmen) untuk setiap negara, dalam USD dengan 5 perpuluhan. Tiada kunci diperlukan.

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

Kredit akaun

GET/api/v1/account

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

Anggar kos

POST/api/v1/costs

Mengambil badan yang sama seperti penghantaran dan mengembalikan kosnya, tanpa menghantar atau mengecaj. Teks gabungan setiap penerima menentukan segmennya, jadi jumlahnya tepat.

{
  "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
}

Buat penghantaran

POST/api/v1/sends

Satu teks kepada satu atau banyak nombor. Kredit untuk keseluruhan penghantaran diambil apabila ia diterima; mesej yang gagal dibayar balik satu demi satu.

MedanMaksud
toNombor dalam format antarabangsa (+447700900461). Gunakan ini atau penerima.
recipientsObjek dengan to dan fields, untuk medan gabungan: { "to": "+1...", "fields": { "first_name": "Ava" } }.
textMesej, sehingga 2,000 aksara. {{field}} digantikan setiap penerima; nilai yang hilang menjadi kosong.
send_atMasa ISO 8601 pilihan dengan offset atau Z. Tanpanya, penghantaran bermula serta-merta.
nameLabel pilihan yang ditunjukkan dalam ruang kerja (80 aksara).
client_refRujukan pilihan yang dikembalikan dalam webhooks (64 aksara).
opt_outMenambahkan baris opt-out yang disimpan dalam Tetapan ke hujung teks.
default_countryKod ISO digunakan untuk nombor yang ditulis tanpa kod negara.
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" } ]
}

Nombor yang tidak dapat dihantar disenaraikan dalam dropped dan tidak pernah dicaj. Kod: no_country_code, too_short, too_long, not_a_number, wrong_length, not_covered, duplicate dan suppressed (dalam senarai jangan hantar anda).

Dapatkan atau senaraikan penghantaran

GET/api/v1/sends/{id}

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

Satu penghantaran termasuk counts setiap status mesej. Senarai adalah yang terbaru dahulu; lulus next_before sebagai before untuk halaman seterusnya. Penghantaran dari ruang kerja juga muncul di sini, dengan source: "web".

Mesej

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" } }

Batal penghantaran

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

Hanya penghantaran yang dijadualkan yang belum bermula boleh dibatalkan. Kos penuh dikembalikan ke kredit anda dan jawapan termasuk refunded_usd.

Webhook

Tetapkan URL https dalam ruang kerja (API dan webhooks). Kami POST satu peristiwa apabila mesej dihantar atau gagal, untuk penghantaran dari API dan ruang kerja. Jawab dengan sebarang status 2xx dalam 10 saat. Penghantaran yang gagal dicuba semula sehingga 7 kali: serta-merta, kemudian selepas 1 minit, 5 minit, 30 minit, 1 jam, 2 jam dan 3 jam. Ruang kerja menunjukkan setiap percubaan dengan status dan jawapannya.

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": "..." } } }

Tandatangan adalah HMAC-SHA256 dari timestamp + "." + raw body dengan rahsia tandatangan anda (ia bermula dengan sso_whk_). Periksanya pada badan mentah sebelum menguraikan, tolak cap masa yang lebih lama daripada 5 minit, dan gunakan id penghantaran untuk mengabaikan ulangan.

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));
}

Peristiwa: message.delivered, message.failed, dan test dari butang Hantar peristiwa ujian.

Status dan sebab

MedanMaksud
queuedMenunggu untuk meninggalkan barisan kami.
sentDihantar ke rangkaian, menunggu laporan penghantaran. Kebanyakan laporan tiba dalam beberapa minit; sesetengah rangkaian mengambil masa sehingga 24 jam.
deliveredRangkaian mengesahkan telefon telah menerimanya.
failedTidak dihantar. Harga telah dikembalikan ke saldo anda.
canceledTidak dihantar kerana anda membatalkan. Dikembalikan.

Sebab kegagalan (medan reason):

MedanMaksud
network_errorRalat rangkaian
absentTelefon dimatikan atau di luar liputan
not_in_serviceNombor tidak berkhidmat
blockedDisekat oleh rangkaian atau penerima
landlineTalian tetap atau nombor yang tidak boleh menerima SMS
content_filterDitolak oleh penapis kandungan rangkaian
expiredTamat tempoh: tiada laporan sebelum had masa rangkaian
canceledDibatalkan sebelum dihantar
unknownTindak balas rangkaian tidak diketahui

Semakan perkhidmatan terdapat di halaman status dan perubahan API dalam changelog.

Dapatkan kunci API anda

Buat akaun, tambah dana sekali dan buka API serta webhook dalam ruang kerja. Kunci yang sama berfungsi untuk setiap negara.

Buat akaun percuma
Dokumentasi API SMS: Hantar SMS Pukal dari Kod Anda | SendSMSOnline