Odesílání SMS integrujete do své aplikace za pár minut. Jednoduché HTTP/JSON API: jeden POST odešle zprávu, GET vrátí stav doručení. Autentizace přes API klíč, žádné SDK ani závislosti — stačí HTTP klient, který váš jazyk už má.
Jeden HTTP požadavek a SMS je venku. Žádné SDK, žádné závislosti:
curl -X POST https://www.topsms.cz/api/sms/send \
-H "Authorization: Bearer <clientId>:<secret>" \
-H "Content-Type: application/json" \
-d '{"to":"+420600000000","text":"Vas overovaci kod je 482910","from":"MojeFirma"}'
API je čisté HTTP/JSON přes HTTPS. Produkční základ (base URL) je https://www.topsms.cz. Nepotřebujete žádnou knihovnu ani SDK — postačí HTTP klient, který už máte (curl, Guzzle, requests, fetch).
Autentizace probíhá přes API klíč v hlavičce Authorization. Klíč tvoří dvojice clientId a secret, kterou vygenerujete v dashboardu v sekci API přístup (secret se ukládá jen jako hash, takže si ho při vytvoření uschovejte):
Authorization: Bearer <clientId>:<secret> Content-Type: application/json
Ke každému klíči patří oprávnění (scope) — send pro odesílání a read pro čtení stavu — a volitelně IP whitelist, kterým klíč omezíte na konkrétní adresy vašeho serveru.
POST https://www.topsms.cz/api/sms/send — vyžaduje scope send.
Tělo požadavku (JSON):
| Pole | Povinné | Popis |
|---|---|---|
to | ano | Telefonní číslo v mezinárodním formátu (např. +420600000000). Podporujeme více než 200 zemí a území — cena dle destinace, viz ceník. |
text | ano | Text zprávy v UTF-8. Diakritika přepne kódování na Unicode (70/67 znaků na část) — části i cenu spočítá kalkulačka délky SMS. |
from | ne | Jméno odesílatele (Sender ID), max 11 znaků. Musí jít o schválené Sender ID vašeho účtu; bez uvedení se použije výchozí „TopSMS". |
Text se odešle přesně tak, jak ho pošlete — proměnné typu {jmeno} API nenahrazuje. Personalizaci (proměnné, oslovení, hodnoty z CSV) provádí kampaňový modul v dashboardu; při odesílání přes API doplní hodnoty vaše aplikace před voláním.
Požadavek:
POST /api/sms/send
{
"to": "+420600000000",
"text": "Vas overovaci kod je 482910",
"from": "MojeFirma"
}
Úspěšná odpověď (HTTP 200):
{
"ok": true,
"id": "cmp7a1b2c3...",
"externalId": "a1b2c3d4",
"to": "+420600000000",
"from": "MojeFirma",
"smsCount": 1,
"price": 0.9,
"status": "sent"
}
id je interní identifikátor zprávy (použijete pro dotaz na stav), externalId je ID u operátora, smsCount je počet účtovaných částí a price je cena v Kč, která se v ten moment odečte z kreditu.
POST https://www.topsms.cz/api/sms/send-bulk — vyžaduje scope send. Až 500 příjemců na jeden požadavek.
Stejný text více příjemcům:
POST /api/sms/send-bulk
{
"to": ["+420600000000", "+420600000001"],
"text": "Zitra mame zavreno.",
"from": "MojeFirma"
}
Nebo jiný text pro každého příjemce — personalizaci si připraví vaše aplikace:
POST /api/sms/send-bulk
{
"messages": [
{ "to": "+420600000000", "text": "Pavle, faktura 2026001 je po splatnosti." },
{ "to": "+420600000001", "text": "Karlo, faktura 2026002 je po splatnosti." }
],
"from": "MojeFirma"
}
Odpověď obsahuje výsledek pro každého příjemce zvlášť ve stejném pořadí, v jakém jste je poslali:
{
"ok": true,
"total": 2,
"accepted": 1,
"rejected": 1,
"price": 0.98,
"results": [
{ "to": "+420600000000", "status": "sent", "id": "cmp7a1b2...", "externalId": "a1b2c3d4", "price": 0.98, "error": null },
{ "to": "+420600000001", "status": "failed", "id": null, "externalId": null, "price": 0, "error": "Invalid phone number. Use international format (+420…)." }
]
}
Účtují se pouze zprávy se stavem sent. Neplatná čísla, čísla na blacklistu a zprávy odmítnuté operátorem se nestrhávají z kreditu. Kredit se kontroluje na celou dávku předem — pokud nestačí, nepošle se nic a vrátíme kód 402.
Stav doručení jednotlivých zpráv zjistíte přes id stejně jako u jednotlivého odeslání, nebo je dostanete push webhookem.
Velké dávky běží asynchronně. Nad 50 příjemců (nebo když pošlete "async": true) API odpoví hned 202 Accepted s jobId, kredit se strhne předem a odesílání zajistí naše fronta během sekund až minut. Průběh zjistíte přes GET /api/sms/jobs/{jobId} (scope read): stav queued / running / done / failed, čítače sent / failed / queued a výsledky po zprávách (?results=0 vrátí jen čítače). Zprávy odmítnuté bránou se na kredit vrátí automaticky, doručenky chodí webhookem stejně jako u synchronního odeslání.
HTTP/1.1 202 Accepted
{
"ok": true,
"queued": true,
"jobId": "cmuk6llct0003yqlx8ke6rdt6",
"statusUrl": "https://www.topsms.cz/api/sms/jobs/cmuk6llct0003yqlx8ke6rdt6",
"total": 120, "accepted": 118, "rejected": 2, "price": 115.64,
"results": [ { "to": "+420600000000", "status": "queued", "id": "cmuk...", "price": 0.98, "error": null }, ... ]
}
Do /api/sms/send i /api/sms/send-bulk přidejte pole send_at a zpráva odejde v zadaný čas. Hodí se na připomínky termínů, ranní rozesílky nebo zprávy mimo noční klid.
{
"to": "+420601234567",
"text": "Pripominame zitrejsi termin v 10:00.",
"send_at": "2026-10-01T09:00:00+02:00"
}
Odpověď je 202 se stavem scheduled a jobId:
{ "ok": true, "scheduled": true, "id": "cmv...", "jobId": "cmw...", "status": "scheduled",
"sendAt": "2026-10-01T07:00:00.000Z", "price": 0.98,
"statusUrl": "https://www.topsms.cz/api/sms/jobs/cmw..." }
+02:00 nebo Z), případně Unix timestamp. Nejvýš 30 dní dopředu; čas do 1 minuty od teď se odešle hned.GET /api/sms/jobs/{jobId}.DELETE /api/sms/jobs/{jobId} (scope send) zruší naplánované odeslání nebo dávku ve frontě, která se ještě nezačala odesílat. Cena se vrátí na kredit. Když už se odesílá, vrátí 409 s code: "not_cancellable".Při výpadku sítě nevíte, jestli požadavek prošel. Pošlete ho znovu se stejnou hlavičkou Idempotency-Key a SMS neodejde dvakrát: dostanete původní odpověď s hlavičkou Idempotent-Replayed: true.
curl -X POST https://www.topsms.cz/api/sms/send \
-H "Authorization: Bearer CLIENT_ID:SECRET" \
-H "Idempotency-Key: 5f0c7a1e-9d2b-4c55-8f7e-2b1d3c4e5a6f" \
-H "Content-Type: application/json" \
-d '{"to": "+420601234567", "text": "Objednavka 1234 odeslana."}'
/api/sms/send, /api/sms/send-bulk a /api/verify/send. Klíč je libovolný řetězec do 255 znaků (doporučujeme UUID nebo ID objednávky), platí 24 hodin a je vázaný na váš API klíč.422 (idempotency_mismatch); pokud původní požadavek ještě běží, 409 (idempotency_in_progress).401, 402, 403, 429 a 5xx se neukládají, takže po odstranění příčiny můžete se stejným klíčem zkusit znovu.Při vytváření API klíče v dashboardu zaškrtněte Testovací klíč. Takový klíč nic neodešle ani neúčtuje, ale vrací stejné odpovědi jako ostrý (navíc "test": true) a za 2 až 4 sekundy změní stav zprávy a pošle doručenku na webhook s "test": true. Stav zjistíte i přes /api/sms/status/{id}.
0000 simulují selhání (neplatné číslo), 0001 expiraci, ostatní doručeníprice ukazuje, kolik by zpráva stála, kredit se neměníV dashboardu v sekci API přístup u každého klíče otevřete Log a webhook: uvidíte posledních 100 volání (čas, endpoint, stavový kód, chyba, tělo požadavku) a pokusy o doručení webhooků včetně odpovědi vašeho serveru. Tamtéž nastavíte nebo změníte webhook URL a pošlete testovací webhook. Log se uchovává 30 dní, secret ani hlavička Authorization se neukládají.
Pro přihlášení, registraci nebo potvrzení akcí: POST /api/verify/send pošle kód, POST /api/verify/check ho ověří. Kód generujeme a hlídáme my (platnost, 5 pokusů, limity na číslo). Podrobnosti a příklady na stránce Verify API.
POST /api/verify/send
{ "to": "+420601234567", "brand": "MojeFirma" }
→ { "ok": true, "id": "cmv...", "status": "pending", "expiresAt": "...", "price": 0.98 }
POST /api/verify/check
{ "id": "cmv...", "code": "482913" }
→ { "valid": true, "status": "approved" }
GET https://www.topsms.cz/api/sms/status/{id} — vyžaduje scope read.
Do {id} dosaďte buď interní id, nebo externalId z odpovědi na odeslání. Delivery report od operátora dorazí asynchronně (typicky do několika sekund až minut) a stav se pak aktualizuje. Doporučený postup je krátký polling — po odeslání se čas od času zeptejte na stav.
{
"id": "cmp7a1b2c3...",
"externalId": "a1b2c3d4",
"to": "+420600000000",
"from": "MojeFirma",
"status": "delivered",
"price": 0.9,
"carrier": "T-Mobile CZ",
"createdAt": "2026-08-10T09:12:00.000Z",
"deliveredAt": "2026-08-10T09:12:03.000Z",
"failedAt": null,
"errorMessage": null,
"errorCode": null
}
Hodnoty pole status:
queued — ve frontě nebo čeká na naplánovaný čas odeslánísent — přijato a předáno operátorovidelivered — doručeno na telefon (viz deliveredAt)failed — nedoručeno (důvod v errorMessage a errorCode, čas v failedAt)expired — vypršela platnost, operátor zprávu nedoručilDůvod nedoručení v poli errorCode (stejné pole je i ve webhooku a ve výsledcích dávky):
expired | Vypršela platnost, telefon byl po celou dobu vypnutý nebo mimo signál. Můžete zkusit poslat později. |
undelivered | Operátor zprávu vrátil jako nedoručitelnou: číslo neexistuje, není aktivní nebo telefon SMS nepřijímá. Některé zahraniční sítě takto vracejí i dočasně nedostupný telefon (vypnutý, bez signálu) místo čekání; u důležitých zpráv doporučujeme po několika minutách zopakovat odeslání se stejným Idempotency-Key rozšířeným o číslo pokusu. |
rejected | Operátor zprávu odmítl (blokace SMS od firem u příjemce, odesílatel nebo obsah). Neznamená špatné číslo. |
deleted | Operátor zprávu před doručením zrušil. |
unknown | Operátor nevrátil výsledek doručení. |
repeated_failure | Na stejné číslo selhalo doručení nejméně potřetí za 90 dní. Číslo pravděpodobně neexistuje, doporučujeme ho vyřadit ze seznamu. |
not_sent | Zprávu se nepodařilo předat operátorovi, cena byla vrácena na kredit. |
Nechcete polling? U API klíče si v dashboardu nastavte webhook URL — při doručení, selhání či expiraci zprávy pošleme HTTP POST:
{
"event": "sms.status",
"id": "cmp7a1b2c3...",
"externalId": "a1b2c3d4",
"to": "+420600000000",
"from": "MojeFirma",
"status": "delivered",
"price": 0.9,
"deliveredAt": "2026-09-07T09:12:03.000Z",
"failedAt": null,
"errorMessage": null,
"errorCode": null,
"sentAt": "2026-09-07T09:12:04.100Z"
}
Podpis: hlavička X-TopSMS-Signature: sha256=HMAC-SHA256(body, webhookSecret) — secret zobrazíme při vytvoření klíče s webhook URL. Doručování: 3 pokusy (ihned, +30 s, +2 min), timeout 5 s, očekáváme HTTP 2xx. Detaily: Webhooky.
Nechcete volat API sami? Většinu běžných napojení máme hotovou nebo ji zvládnete bez programování:
POST /api/sms/send s hlavičkou Authorization: Bearer clientId:secret, viz příklady níže.Přehled všech napojení a jejich stavu je na stránce Pluginy a integrace.
PHP: composer require topsms/topsms-php — github.com/topsms-ghb/topsms-php (odeslání, stav, kredit i ověření webhook podpisu). Strojově čitelný popis API pro import do Postman/Insomnia: OpenAPI specifikace.
GET https://www.topsms.cz/api/credit — vyžaduje scope read.
Vrací aktuální zůstatek v Kč a vaši cenu za SMS. Hodí se pro automatické hlídání kreditu — např. upozornění ve vašem systému, když zůstatek klesne pod týdenní spotřebu.
{
"ok": true,
"credit": 1482.96,
"currency": "CZK",
"smsPrice": 0.98
}
Chyba vždy vrací JSON { "error": "popis" } s odpovídajícím HTTP kódem. Endpointy Verify API přidávají i strojový "code" (například rate_limited, cooldown, insufficient_credit, invalid_number, not_found), podle kterého chybu snadno obsloužíte v kódu.
| HTTP | Význam |
|---|---|
202 | Není chyba: hromadná dávka nad 50 příjemců (nebo s "async": true) byla přijata do fronty, průběh přes GET /api/sms/jobs/{jobId}. |
400 | Chybí to nebo text, neplatné číslo, nebo je číslo na blacklistu (odhlášený kontakt). |
401 | Chybějící nebo neplatná autentizace (zkontrolujte formát Bearer clientId:secret). |
402 | Nedostatečný kredit na účtu. |
403 | Účet není aktivní/schválený, IP mimo whitelist, klíč nemá potřebný scope, nebo neschválené Sender ID v poli from. |
404 | Zpráva nenalezena (u dotazu na stav). |
409 | Konflikt: požadavek se stejným Idempotency-Key ještě běží, nebo úlohu už nejde zrušit (not_cancellable). |
422 | Idempotency-Key už byl použit s jiným požadavkem (idempotency_mismatch). |
429 | Překročen rate limit klíče, nebo u Verify API víc než 5 kódů na jedno číslo za hodinu (rate_limited) či další kód dřív než za 30 s (cooldown, pole retryAfter v sekundách). |
502 | Chyba na straně operátora při doručování. |
Cena se počítá podle počtu částí zprávy (segmentů). Limit na jednu SMS závisí na tom, jestli text obsahuje diakritiku:
Odpověď na odeslání vrací smsCount (počet účtovaných částí) i price (cena v Kč dle vašeho tarifu), takže cenu znáte hned. Detail počítání najdete v článku Kolik znaků má SMS.
Ve všech příkladech nahraďte CLIENT_ID:SECRET svým klíčem.
curl
curl -X POST https://www.topsms.cz/api/sms/send \
-H "Authorization: Bearer CLIENT_ID:SECRET" \
-H "Content-Type: application/json" \
-d '{"to":"+420600000000","text":"Ahoj","from":"MojeFirma"}'
PHP (cURL)
$ch = curl_init('https://www.topsms.cz/api/sms/send');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer CLIENT_ID:SECRET',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'to' => '+420600000000',
'text' => 'Ahoj z PHP',
'from' => 'MojeFirma',
]),
]);
$response = curl_exec($ch);
echo $response;
Python (requests)
import requests
r = requests.post(
"https://www.topsms.cz/api/sms/send",
headers={"Authorization": "Bearer CLIENT_ID:SECRET"},
json={"to": "+420600000000", "text": "Ahoj z Pythonu", "from": "MojeFirma"},
)
print(r.json())
Node.js (fetch)
const res = await fetch("https://www.topsms.cz/api/sms/send", {
method: "POST",
headers: {
"Authorization": "Bearer CLIENT_ID:SECRET",
"Content-Type": "application/json",
},
body: JSON.stringify({ to: "+420600000000", text: "Ahoj z Node", from: "MojeFirma" }),
})
console.log(await res.json())
from). Operátoři schvalují nové odesílatele hromadně několikrát měsíčně (počítejte s 1–2 týdny), jednorázový poplatek 500 Kč. API přijme jen schválené Sender ID vašeho účtu (nebo výchozí „TopSMS") — neschválené jméno vrátí 403. Detail na stránce Vlastní Sender ID.send/read, IP whitelist, webhook URL, log volání a revokace. Testovací klíč (zaškrtnete při vytvoření) nic neodesílá ani neúčtuje.Vyzkoušejte TopSMS zdarma. 10 SMS na začátek, bez závazků, bez kreditní karty.