How to Send SMS With an API From a Website
A practical developer walkthrough of how to send SMS with an API from a website: where the token lives, the send request and its parameters, delivery status, webhooks, and the pitfalls to avoid.
If you want to know how to send SMS with an API from a website, the short answer is this: your site makes an HTTP request to a messaging gateway, passes an authentication token and the message details, and the gateway does the actual sending while returning a message id you can track. Nothing on your web server sends the text directly. Your code just describes what to send and to whom, then a paired phone or a linked WhatsApp account carries it out. This guide walks through the concept, the exact request and its parameters, where the token comes from in SharkSMS, the difference between sending through an Android gateway and WhatsApp, how to follow delivery status, and the mistakes that trip up most first integrations.
If you would rather see the product side first, the SharkSMS SMS API page lays out the endpoints, authentication, and permissions in one place. The rest of this article is the practical how-to behind it.
What "sending SMS with an API" actually means
An SMS API is a small contract between your website and a messaging platform, spoken over plain HTTP. Your application builds a request that names the recipient and the message, adds a secret token so the platform knows who is asking, and sends it to a specific URL called an endpoint. The platform validates the request, queues the message, and answers with a structured response, almost always in JSON. This is the same request-and-response pattern that powers most of the modern web. If HTTP methods are new to you, Mozilla's reference on the POST method is a clear primer, and the Fetch API documentation covers how a browser or Node script issues one.
The important mental shift is that the API call is a request to send, not proof of delivery. Your code hands the message to the platform, the platform hands it to a phone or a WhatsApp account, and only later does a status come back describing what happened. Treating the initial "queued" response as a guarantee is the single most common misunderstanding, and we return to it below.
The two ways SharkSMS sends: Android gateway or WhatsApp
Before you write any code, decide which channel carries the message, because it changes the parameters you send.
The first route is a paired Android phone acting as an SMS gateway. You install the gateway app on an Android handset, pair it to your account, and the phone sends real SMS through its own SIM plan. Your API call names that device, and the platform wakes it to send. The Android SMS gateway page shows how pairing and per-send SIM selection work, and our guide to using an Android phone as an SMS gateway covers the setup end to end.
The second route is a linked WhatsApp account. Instead of a SIM sending an SMS, a connected WhatsApp account sends a WhatsApp message to a recipient or a group. The endpoint and parameters differ, but the shape of the request is the same: a token, a recipient, and a message.
A third option exists for accounts that top up credits and route through a third-party gateway, selected with a gateway parameter instead of a device. For a website that owns a phone and a SIM, the paired-device route is usually the most direct, so the walkthrough below uses it.

Where your API token comes from
Every request must prove who is sending it. In SharkSMS that proof is an API key, and it travels in the request as a parameter named secret. You create the key inside the dashboard under Tools, in the API keys section. When you create a key you give it a name and choose its permissions, which are individual scopes such as sms_send for sending SMS, wa_send for WhatsApp, and read scopes like get_sms_sent for looking up the status of a message you already sent. A key only works for the scopes you granted it, so a send-only key cannot read your contacts, and a read-only key cannot send. Grant the least it needs.
Treat the key like a password. Keep it in server-side configuration or an environment variable, never in front-end JavaScript that ships to the browser, and never hard-coded in a public repository. If a key leaks, delete it in the dashboard and issue a new one. Your account also needs an active subscription whose plan includes the SMS service, otherwise the send endpoint refuses the request even with a valid key.
Making your first send request
To send an SMS through a paired Android device, your website sends an HTTP request to the send endpoint. The path is /api/send/sms on your SharkSMS installation, and the request carries these fields:
- secret - your API key.
- mode - set to
devicesto send through your own paired phone, orcreditsto route through a credit-based gateway. - phone - the recipient number in full international format, for example a leading country code as defined by the ITU E.164 standard. Invalid numbers are rejected before anything is queued.
- message - the text body. It must respect the minimum and maximum length your platform is configured for.
- device - the id of the paired device that should send, required in
devicesmode. - sim - optional,
1or2, to pick a SIM slot on a dual-SIM phone. It defaults to the first slot. - priority - optional integer to push a message ahead in the queue.
A minimal request from a command line looks like this:
curl -X POST https://your-site.example/api/send/sms \
-d secret=YOUR_API_KEY \
-d mode=devices \
-d device=YOUR_DEVICE_ID \
-d phone=+15551234567 \
-d message="Your order is ready for pickup."
The same call from a website using the Fetch API stays just as small:
const body = new URLSearchParams({
secret: process.env.SHARKSMS_KEY,
mode: "devices",
device: "YOUR_DEVICE_ID",
phone: "+15551234567",
message: "Your order is ready for pickup."
});
const res = await fetch("https://your-site.example/api/send/sms", {
method: "POST",
body
});
const data = await res.json();
Keep the sending call on your server, triggered by a real event such as a confirmed order or a verified appointment, rather than exposing it to the browser where the key would be visible.

Reading the response
SharkSMS answers with a JSON object that always has the same three fields: a numeric status, a human-readable message, and a data object. A successful send returns something like this:
{
"status": 200,
"message": "Message has been queued for sending!",
"data": { "messageId": 4192 }
}
Store that messageId. It is the handle you use later to look up what happened to this specific message. When something is wrong, the status field carries a different code and the message explains it: 400 for missing or invalid parameters and bad phone numbers, 401 for an invalid key, 403 when the key lacks the scope or the plan lacks the service, 404 when the named device does not exist, and 500 for a server-side problem. Read the status in the body rather than assuming the HTTP layer alone tells you the outcome, and log the full response while you are building the integration so failures are easy to diagnose.
Tracking delivery status
Because the send response only confirms the message was queued, you follow up to learn the real outcome. SharkSMS exposes a lookup at /api/get/sms.message. You pass your secret, the id from the earlier messageId, and a type of sent. The response returns the message details and a status that moves through a small set of values: queued when it is waiting, pending once it has been handed off, sent when the phone reports it went out, and failed if it could not be delivered. A status_code from the device is included for deeper diagnosis. Reading a message status requires the get_sms_sent scope on the key, so grant it when you create the key you will use for status checks.
A sensible pattern is to send, record the messageId against the order or booking in your own database, then check the status a short while later rather than in a tight loop. Use the result to decide whether a person on your team should follow up. Do not turn a sent status into a guaranteed-delivery promise to the customer; it is useful operational information, not a contract.
Receiving inbound messages with webhooks
Polling suits outbound status, but for messages that arrive at your number you want to be told, not to keep asking. SharkSMS supports webhooks for this. In the dashboard you register a webhook with a name, a URL on your own site, and the events it should fire on, chosen from sms, whatsapp, and ussd. When a matching event happens, the platform sends an HTTP request to your URL so your application can react in real time, for example logging an inbound reply or triggering an automated response. This keeps two-way conversations moving without constant polling. Point the webhook at an endpoint that responds quickly and validates what it receives before acting on it.

Sending through WhatsApp instead
If your audience is on WhatsApp, the request shape barely changes. The endpoint is /api/send/whatsapp, and instead of a device you name a linked account. You pass your secret, the account id of a connected WhatsApp number, a recipient (a phone number, or a group id ending in @g.us), and the message. An optional type defaults to text and can also carry media or a document. The account must be connected and your plan must include the WhatsApp service, otherwise the call is refused in the same way as SMS. The response follows the same status, message, and data structure, so the code you wrote to read an SMS response works here with little change.
Common pitfalls to avoid
A handful of mistakes account for most failed first integrations.
- Exposing the key in the browser. Anything sent from front-end JavaScript is visible to anyone who opens developer tools. Keep the send call and the key on your server.
- Treating "queued" as "delivered." The send response confirms acceptance, not arrival. Store the
messageIdand check the status separately. - Sending national-format numbers. Provide numbers in international E.164 format so the platform can validate and route them; malformed numbers are rejected up front.
- Ignoring the status field in the body. The app returns rich detail in the JSON
statusandmessage. Read them instead of guessing from the transport layer. - Over-scoping the key. Grant only the permissions the integration needs. A leaked send-only key is far less damaging than a leaked all-access one.
- Forgetting the phone is real. An Android gateway sends at the pace of a handset on a network. Space out large batches and keep the sending phone online and excluded from battery optimization, as our gateway guide explains.
Putting it together
Sending SMS from a website with an API comes down to four repeatable steps: create a scoped key under Tools, post the recipient and message to the send endpoint with that key, read the returned messageId, and check the status or listen on a webhook to learn what happened. The same pattern covers a paired Android phone and a linked WhatsApp account, differing only in the endpoint and one or two parameters. From there you can wire messaging into whatever real event matters on your site, whether that is an order confirmation, an appointment reminder, or a verification code. The use cases page shows where teams put this to work, and the SMS API page is the reference to keep open while you build.
Ready to send your first message from code? Create a SharkSMS account, pair a phone, generate an API key, and post a test to a number you control. When you need the full endpoint list, the SMS API documentation has it.

Comments
No comments yet. Be the first.
Sign in to comment
Comments come from SharkSMS accounts, so you always know who you are reading. Creating one is free and takes a minute.