Trimiterea de SMS prin API în 10 minute cu Node.js
September 2, 2026 · 6 minute de citit · Actualizat la October 9, 2026
Pentru a trimite un SMS din Node.js este suficientă o singură cerere POST către https://volai.cz/v1/messages, cu antetul Authorization: Bearer vk_... și cu corpul JSON {to, body}. Node 20 are fetch încorporat, deci nu este nevoie de niciun pachet suplimentar. Un exemplu funcțional se află chiar sub acest paragraf, împreună cu tratarea erorilor și cu idempotența, pentru ca o defecțiune de rețea să nu trimită același mesaj de două ori.
De ce veți avea nevoie
- Node.js 18 sau mai nou -
fetchface parte din biblioteca standard încă de la această versiune; recomandăm linia LTS întreținută în prezent (24, la data de 2 septembrie 2026). - Un cont volai și o cheie API din portal (Setări -> API și MCP), de forma
vk_.... - Cel puțin o reîncărcare a creditului. SMS-urile funcționează abia după prima reîncărcare, creditul de bun venit nu acoperă trimiterea lor - cu el puteți încerca apeluri, dar nu mesaje text.
- Numărul de telefon al destinatarului din Cehia sau din Slovacia (
+420sau+421) - în alte țări nu trimitem SMS-uri. - Un număr de telefon propriu NU este necesar. Mesajele pleacă sub numele comun
SMSinfo- operatorii din rețelele cehe acceptă doar nume aprobate, așa că la un expeditor comun nu puteți seta un nume propriu de expeditor, iar la SMSinfo destinatarul nu poate răspunde. De aceea, identitatea dvs. trebuie scrisă în textul mesajului, ca în exemplul de mai jos. Dacă răspunsul trebuie să fie posibil, trimiteți mesajul de pe propriul număr de mobil (un supliment, vezi nota de mai jos).
Trimiterea primului SMS
Cererea are nevoie doar de două câmpuri: to (numărul destinatarului) și body (textul mesajului). Răspunsul returnează id-ul mesajului, status, prețul în bani (priceHal) și numărul de segmente (segments) - la ambele revenim imediat.
const response = await fetch("https://volai.cz/v1/messages", {
method: "POST",
headers: {
Authorization: "Bearer vk_CHEIA_DVS",
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "+420777123456",
body: "Salut de la volai! - Aplicația mea",
}),
});
if (!response.ok) {
const { error } = await response.json();
throw new Error("volai " + error.code + ": " + error.message);
}
const message = await response.json();
console.log(message);
// { id: "msg_7c1f9a2e", status: "sent", priceHal: 136, segments: 1 }Cât costă un SMS și ce sunt segmentele?
Un SMS dintr-un singur segment costă 1,36 kr fără TVA (preț valabil la 2 septembrie 2026). Câte segmente ocupă un mesaj depinde de faptul dacă are diacritice - operatorii numără SMS-urile după standardul GSM 03.38:
| Codificare | Caractere în primul segment | Caractere în părțile următoare |
|---|---|---|
| GSM-7 (fără diacritice) | 160 | 153 |
| UCS-2 (cu diacritice) | 70 | 67 |
Este suficient UN SINGUR caracter din afara alfabetului de bază GSM-7 - în mod tipic o diacritică românească sau cehă (ă â î ș ț, ě š č ř ž ý á í ů) - și întregul mesaj trece pe UCS-2, chiar dacă în text există o singură literă de acest fel. Sfat: pentru a fi sigur că mesajul încape într-un singur segment, scrieți fără diacritice.
Exemplu: mesaj cu diacritice, de peste 70 de caractere
Acest mesaj are peste 120 de caractere și conține diacritice, deci este numărat ca UCS-2 (limita de 67 de caractere pe segment la un mesaj în mai multe părți) - rezultă 2 segmente, adică 2,72 kr, nu 1,36 kr:
await fetch("https://volai.cz/v1/messages", {
method: "POST",
headers: {
Authorization: "Bearer vk_CHEIA_DVS",
"Content-Type": "application/json",
},
body: JSON.stringify({
to: "+420777123456",
body: "Vă reamintim programarea de mâine, ora 10:00 - dacă nu vă convine, răspundeți vă rugăm la acest mesaj și vom găsi un alt termen.",
}),
});
// -> { id: "msg_9a3f1c7d", status: "sent", priceHal: 272, segments: 2 }Idempotență: reluarea în siguranță a cererii
Merită să adăugați antetul Idempotency-Key cu un șir propriu oarecare, de exemplu identificatorul comenzii. Dacă o cerere se încheie cu eroare din cauza unei defecțiuni de rețea, iar workflow-ul o reia cu ACELAȘI antet, volai returnează răspunsul salvat de la prima încercare și nu trimite mesajul a doua oară - cheia este valabilă 24 de ore.
curl -X POST https://volai.cz/v1/messages \
-H "Authorization: Bearer vk_CHEIA_DVS" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: comanda-4471" \
-d '{"to": "+420777123456", "body": "Comanda dvs. nr. 4471 a fost primită."}'Manipularea în siguranță a cheii API
Cheia API (vk_...) are aceeași greutate ca o parolă - oricine o cunoaște poate trimite mesaje în numele dvs. și poate cheltui creditul din contul dvs. De aceea nu o scrieți niciodată în codul sursă care ajunge în repozitoriu. Locul ei este într-o variabilă de mediu (process.env.VOLAI_API_KEY în Node.js) sau în managerul de secrete folosit de găzduirea dvs.
// .env.local (nu îl adăugați niciodată în repozitoriu)
// VOLAI_API_KEY=vk_cheia_dvs
const response = await fetch("https://volai.cz/v1/messages", {
method: "POST",
headers: {
Authorization: "Bearer " + process.env.VOLAI_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ to, body }),
});Endpoint-ul trebuie apelat întotdeauna de pe server, nu din browser - oricine ar putea citi cheia în instrumentele pentru dezvoltatori ale browserului și ar începe să trimită propriile mesaje din contul dvs. Dacă cheia se scurge (de exemplu printr-un commit accidental), generați în portal una nouă și revocați-o pe cea veche - valoarea veche încetează să funcționeze imediat.
Mai întâi un test sigur
Înainte de a conecta trimiterea de SMS-uri la un proces real (de exemplu la confirmarea comenzii), merită să trimiteți primele mesaje pe propriul număr de telefon. Veți vedea exact ce va vedea clientul - cum arată expeditorul SMSinfo, cât durează livrarea și dacă diacriticele sunt numărate așa cum vă așteptați. Abia apoi înlocuiți to cu numărul real al clientului.
Ce faceți când API-ul returnează o eroare?
Un răspuns cu eroare are întotdeauna forma {error: {code, message}} și un status HTTP care depinde de tipul erorii:
| Status | Cod | Ce înseamnă |
|---|---|---|
| 400 | invalid_number | Nu este un număr de telefon ceh sau slovac valid. |
| 400 | invalid_body | Textul mesajului trebuie să aibă între 1 și 765 de caractere. |
| 400 | unsupported_country | Număr din afara CZ/SK, acolo nu trimitem SMS-uri. |
| 400 | recipient_cannot_receive_sms | Număr fix - SMS-ul nu ar ajunge. Nu se taxează nimic. |
| 402 | insufficient_credit | Creditul nu acoperă prețul tuturor segmentelor mesajului sau contul nu a fost încă reîncărcat - SMS-urile funcționează abia după prima reîncărcare, creditul de bun venit nu acoperă trimiterea lor. |
| 429 | rate_limited | Mai mult de 1 SMS la 2 secunde sau peste 100 de SMS-uri pe zi pe cont. |
| 502 | send_failed | Rețeaua telefonică a respins cererea. Creditul nu a fost debitat, încercați din nou. |
| 502 | send_unknown | Am predat mesajul rețelei, dar confirmarea nu a sosit - se taxează, vă rugăm să nu îl retrimiteți orbește. |
Ce stări poate avea un mesaj?
Câmpul status din listă (GET /v1/messages) și din detaliul unui singur mesaj poate avea cinci valori: pending (salvat, încă se trimite), sent (operatorul a confirmat trimiterea), failed (operatorul a respins - nu se taxează), unknown (confirmarea livrării nu a sosit, de obicei din cauza depășirii timpului de către operator - se taxează totuși la prețul întreg, fiindcă mesajul poate să fi ajuns) și received (doar la mesajele primite, adică cu direction=in; mesajele trimise nu îl au).
Fiecare mesaj poartă și câmpul direction (out la cele trimise, in la cele primite), smsNumber (numărul de pe care a plecat mesajul sau pe care a sosit; la mesajele trimise sub numele comun SMSinfo este null) și deliveryStatus (delivered sau undelivered, confirmarea de livrare de la operator; apare doar la SMS-urile trimise de pe un număr de mobil, la celelalte mesaje este null).
Cum trimiteți mai multe SMS-uri deodată?
Limita permite cel mult un SMS la două secunde pe cont și cel mult 100 de SMS-uri pe zi. La trimiterea în masă (de exemplu a mementourilor pentru programări) este mai simplu să faceți o scurtă pauză între cereri decât să interceptați rate_limited și să reîncercați:
const message = "Vă reamintim termenul de mâine - Aplicația mea";
for (const to of recipients) {
const response = await fetch("https://volai.cz/v1/messages", {
method: "POST",
headers: {
Authorization: "Bearer vk_CHEIA_DVS",
"Content-Type": "application/json",
},
body: JSON.stringify({ to, body: message }),
});
if (!response.ok) {
const { error } = await response.json();
console.error("volai " + to + ": " + error.code);
}
// Limita este de cel mult 1 SMS la 2 secunde pe cont - o scurtă pauză între
// cereri este mai simplă decât tratarea rate_limited și reîncercarea.
await new Promise((resolve) => setTimeout(resolve, 2100));
}SMS-urile pot fi primite pe două tipuri de numere
Numerele vocale volai nu primesc SMS-uri, așa că un răspuns la un mesaj trimis sub numele comun SMSinfo nu apare nicăieri. Pentru a primi SMS-uri și a le trimite de pe propriul număr, alegeți suplimentul număr de mobil: un număr ceh doar pentru SMS-uri, fără apeluri, 290 kr la 30 de zile fără TVA. Sau comandați numărul: număr pentru apeluri și SMS - un număr fix din Praga, pe care se primesc apeluri și SMS-uri, 49 kr la 30 de zile fără TVA (taxa se percepe abia după activare, care durează de obicei până la 1 zi lucrătoare). În ambele cazuri, SMS-urile primite sunt incluse în preț. Mesajele primite le puteți citi în GET /v1/messages?direction=in, în instrumentul MCP list_messages sau în webhook-ul message.received, iar noi le păstrăm 90 de zile; trimiterea de pe un număr de mobil costă 1,90 kr pe segment, de pe numărul: număr pentru apeluri și SMS 2,50 kr pe segment, și este posibilă doar către numere cehe. Un SMS de pe un număr se trimite prin câmpul fromNumber din POST /v1/messages (numărul se ia din GET /v1/sms-numbers sau din GET /v1/voice-sms-numbers). Limita zilnică de trimitere de pe un număr este de 20 de SMS-uri pe cont în primele 30 de zile de la cumpărarea numărului, apoi de 50. Pe un cont pot exista cel mult două numere SMS și le puteți cumpăra abia după prima reîncărcare a creditului; la fel este și cu numerele: număr pentru apeluri și SMS - cel mult două pe cont, iar comandarea lor este posibilă abia după prima reîncărcare. Nu garantăm coduri de verificare de la servicii (bănci, Google și altele asemenea), numerele servesc la comunicarea cu oamenii, iar recepția am verificat-o în rețeaua O2. Detaliile se află în secțiunile Numere SMS și Numere: număr pentru apeluri și SMS din documentația API. Când Twilio este alegerea mai bună pentru primirea de SMS-uri, descrie comparația dintre Twilio și volai.
Pe scurt: un singur POST /v1/messages cu câmpurile to și body trimite un SMS, antetul Idempotency-Key protejează workflow-ul de dubla trimitere la reluarea cererii, iar prețul se calculează pe segmente, în funcție de faptul dacă textul conține diacritice. Păstrați cheia în afara repozitoriului, iar primul mesaj trimiteți-l către dvs. înșivă.
Mai departe
Documentația completă a API-ului REST (numere, apeluri, webhook-uri, agenți) se află la adresa /docs/api. Doriți să aflați imediat când volai predă mesajul operatorului, fără să interogați GET /v1/messages? Vă puteți abona la evenimentul message.sent - acesta confirmă doar preluarea de către operator, nu livrarea pe telefon (la mesajele trimise sub numele comun volai nu vede acest lucru, vezi mai sus; mesajele trimise de pe un număr de mobil propriu au confirmare de livrare) - vezi documentația webhook-urilor. Iar dacă pe lângă SMS-uri aveți nevoie și de un număr de telefon care preia singur apelurile, merită să consultați pagina Recepționer AI.
Încercați volai - primii 50 kr sunt din partea noastră
Creați un cont într-un minut și aveți imediat în cont un credit de pornire pentru apeluri și număr - SMS puteți trimite după prima reîncărcare.
Pașii următori
Articole conexe
Cinci întrebări înainte de a alege un recepționer AI
Preț, pornire în 5 minute, redirecționarea numărului la O2/T-Mobile/Vodafone, numere slovace și TVA - cinci răspunsuri direct din prețurile și setările volai.
Cum sunați un client dintr-un workflow n8n
Sunați un client direct din n8n: nod HTTP Request către API-ul REST volai, datele din workflow în promptul agentului și rezultatul apelului înapoi prin webhook.
Cum îi dați lui Claude Code un număr de telefon prin MCP
Instalați volai în Claude Code cu o comandă, dați-i un număr de telefon și lăsați-l să sune și să trimită SMS dintr-un prompt - fără cod, fără documentație API.