Treceți la conținut

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 - fetch face 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 (+420 sau +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.

javascript
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:

CodificareCaractere în primul segmentCaractere în părțile următoare
GSM-7 (fără diacritice)160153
UCS-2 (cu diacritice)7067

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:

javascript
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.

bash
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.

javascript
// .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:

StatusCodCe înseamnă
400invalid_numberNu este un număr de telefon ceh sau slovac valid.
400invalid_bodyTextul mesajului trebuie să aibă între 1 și 765 de caractere.
400unsupported_countryNumăr din afara CZ/SK, acolo nu trimitem SMS-uri.
400recipient_cannot_receive_smsNumăr fix - SMS-ul nu ar ajunge. Nu se taxează nimic.
402insufficient_creditCreditul 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.
429rate_limitedMai mult de 1 SMS la 2 secunde sau peste 100 de SMS-uri pe zi pe cont.
502send_failedRețeaua telefonică a respins cererea. Creditul nu a fost debitat, încercați din nou.
502send_unknownAm 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:

javascript
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.

Încercați gratuit