Documentazione API SMS per l'invio dal tuo codice

Una piccola API REST sullo stesso account, prezzi e credito dell'area di lavoro: invia un messaggio o un batch di fino a 5,000 numeri, stima prima il costo, segui ogni messaggio e ricevi eventi di consegna al tuo URL webhook.

URL di base: https://sendsmsonline.cc/api/v1

Guida rapida

  1. 1. Crea una chiave. Nell'area di lavoro apri API e webhook. Le chiavi si sbloccano dopo il primo ricarica accreditata; ogni chiave viene mostrata una sola volta, quindi copiala o salvala come file di testo.
  2. 2. Verifica il costo. Invia lo stesso corpo con POST a /costs per vedere i destinatari, i segmenti e il totale senza inviare.
  3. 3. Invia. Invia con POST a /sends. La risposta contiene l'ID dell'invio; i messaggi partono subito o all'ora 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" }'

Autenticazione

Invia la tua chiave nell'header Authorization: Authorization: Bearer sso_live_.... Le chiavi sono lunghe 49 caratteri e iniziano con sso_live_. Fino a 5 chiavi per account; revocane una nell'area di lavoro e smetterà di funzionare immediatamente. La lista prezzi è pubblica e non richiede una chiave.

Errori

Gli errori utilizzano codici di stato HTTP e un corpo JSON con un codice stabile e una frase che puoi mostrare a una persona. Non viene addebitato nulla quando una richiesta fallisce.

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" } }
CampoSignificato
400La richiesta necessita di una modifica.
401Chiave mancante, errata o revocata.
402Credito insufficiente per il totale.
404Invio, messaggio, paese o endpoint non trovato.
409L'invio è già iniziato.
429Più di 240 richieste in un minuto.

Limiti

  • 240 richieste al minuto per chiave, mostrate in X-RateLimit-Limit, X-RateLimit-Remaining e X-RateLimit-Reset (secondi unix).
  • 5,000 numeri per richiesta, 2,000 caratteri per testo, 10 segmenti per messaggio.
  • I messaggi partono fino a 300 al minuto per account.
  • send_at da 10 minuti a 30 giorni in anticipo.

Prezzi

GET/api/v1/prices

GET/api/v1/prices/{country}

Il prezzo per messaggio (un segmento) per ogni paese, in USD con 5 decimali. Nessuna chiave necessaria.

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

Credito dell'account

GET/api/v1/account

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

Stima un costo

POST/api/v1/costs

Prende lo stesso corpo di un invio e restituisce il costo, senza inviare o addebitare. Il testo unito di ciascun destinatario decide i suoi segmenti, quindi il totale è esatto.

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

Crea un invio

POST/api/v1/sends

Un testo a uno o più numeri. Il credito per l'intero invio viene prelevato quando viene accettato; i messaggi falliti vengono rimborsati uno per uno.

CampoSignificato
toNumeri in formato internazionale (+447700900461). Usa questo o destinatari.
recipientsOggetti con to e fields, per i campi di unione: { "to": "+1...", "fields": { "first_name": "Ava" } }.
textIl messaggio, fino a 2,000 caratteri. {{field}} viene sostituito per destinatario; i valori mancanti diventano vuoti.
send_atOra ISO 8601 opzionale con offset o Z. Senza di essa, l'invio inizia immediatamente.
nameEtichetta opzionale mostrata nell'area di lavoro (80 caratteri).
client_refRiferimento opzionale restituito nei webhook (64 caratteri).
opt_outAggiunge la riga di rinuncia salvata nelle Impostazioni alla fine del testo.
default_countryCodice ISO utilizzato per i numeri scritti senza un prefisso internazionale.
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" } ]
}

I numeri che non possono essere inviati sono elencati in dropped e mai addebitati. Codici: no_country_code, too_short, too_long, not_a_number, wrong_length, not_covered, duplicate e suppressed (nella tua lista di non invio).

Ottieni o elenca gli invii

GET/api/v1/sends/{id}

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

Un singolo invio include counts per stato del messaggio. Le liste sono ordinate dal più recente; passa next_before come before per la pagina successiva. Gli invii dall'area di lavoro appaiono qui, con source: "web".

Messaggi

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

Annulla un invio

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

Solo gli invii programmati che non sono iniziati possono essere annullati. Il costo totale viene restituito al tuo credito e la risposta include refunded_usd.

Webhook

Imposta un URL https nell'area di lavoro (API e webhook). Inviiamo un evento POST quando un messaggio viene consegnato o fallisce, sia per gli invii dall'API che dall'area di lavoro. Rispondi con qualsiasi stato 2xx entro 10 secondi. Le consegne fallite vengono ritentate fino a 7 volte in totale: subito, poi dopo 1 minuto, 5 minuti, 30 minuti, 1 ora, 2 ore e 3 ore. L'area di lavoro mostra ogni tentativo con il suo stato e risposta.

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

La firma è HMAC-SHA256 di timestamp + "." + raw body con il tuo segreto di firma (inizia con sso_whk_). Controllala sul corpo grezzo prima di analizzarlo, rifiuta timestamp più vecchi di 5 minuti e usa l'id di consegna per ignorare le ripetizioni.

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

Eventi: message.delivered, message.failed, e test dal pulsante Invia evento di test.

Stati e motivi

CampoSignificato
queuedIn attesa di lasciare la nostra coda.
sentConsegnato alla rete, in attesa del report di consegna. La maggior parte dei report arriva entro pochi minuti; alcune reti possono impiegare fino a 24 ore.
deliveredLa rete ha confermato che il telefono lo ha ricevuto.
failedNon consegnato. Il prezzo è stato rimborsato sul tuo credito.
canceledNon inviato perché hai annullato. Rimborsato.

Motivi di fallimento (il campo reason):

CampoSignificato
network_errorErrore di rete
absentTelefono spento o fuori copertura
not_in_serviceNumero non in servizio
blockedBloccato dalla rete o dal destinatario
landlineNumero fisso o numero che non può ricevere SMS
content_filterRifiutato dal filtro contenuti della rete
expiredScaduto: nessun report prima del limite di tempo della rete
canceledAnnullato prima dell'invio
unknownRisposta di rete sconosciuta

I controlli del servizio sono nella pagina di stato e le modifiche API nel changelog.

Ottieni la tua chiave API

Crea un account, aggiungi fondi una volta e apri API e webhook nello spazio di lavoro. La stessa chiave funziona per ogni paese.

Crea un account gratuito
Documentazione API SMS: Invia SMS di massa dal tuo codice | SendSMSOnline