Every REST request carries your account's access token in an Authorization: Bearer header. The same token works for every channel, and a missing or invalid token is rejected with HTTP 401.
How authentication works#
| Item | Detail |
|---|---|
| Scheme | HTTP Bearer token |
| Header | Authorization: Bearer <your token> |
| Scope | One token per account. It acts with that account's permissions, sender IDs and balance. |
| Issued by | Our team, with your test or production credentials. A permanent key is issued by your account admin or master account. |
| Token endpoint | None. The API has no call that exchanges a username and password for a token. |
| Transport | HTTPS only. Keep certificate verification on. |
cURL
curl -X POST https://api.broadnet.me/sms/identify \
-H "Authorization: Bearer $BROADNET_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "message": "Hello from OmniDemo" }'Node.js
const res = await fetch("https://api.broadnet.me/sms/identify", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.BROADNET_TOKEN}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ message: "Hello from OmniDemo" }),
});
console.log(res.status, await res.json());Python
import os
import requests
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['BROADNET_TOKEN']}"
r = session.post(
"https://api.broadnet.me/sms/identify",
json={"message": "Hello from OmniDemo"},
timeout=15,
)
print(r.status_code, r.json())PHP
<?php
$ch = curl_init("https://api.broadnet.me/sms/identify");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . getenv("BROADNET_TOKEN"),
"Content-Type: application/json",
],
CURLOPT_POSTFIELDS => json_encode(["message" => "Hello from OmniDemo"]),
]);
echo curl_exec($ch);
curl_close($ch);Store the token safely#
The token is a send credential: anyone who holds it can send messages and spend your balance.
- Keep it in a secrets manager or an environment variable on your servers.
- Never put it in source control, mobile apps, browser JavaScript, logs or support tickets.
- Call the API from your backend only. If a web or mobile client needs to trigger a message, have it call your server, which then calls the API.
- Give each environment (development, staging, production) its own credentials where your account allows it, so a leak in one does not expose the others.
- Resellers: keep credentials separate per customer sub-account so that revoking one never affects another.
Rotate or revoke a token#
There is no self-service rotation endpoint in the API. To rotate a token, or to revoke one that may have leaked, contact your account admin or our support team. They revoke the old key and issue a new one.
A safe rotation sequence:
- Request a new token and add it to your secrets store next to the old one.
- Deploy the new token to every service that calls the API.
- Confirm that traffic succeeds with the new token, for example by watching for
401responses. - Ask for the old token to be revoked.
For AI agents connected through MCP, use temporary keys while you experiment. See MCP server.
What a 401 looks like#
A missing or invalid token is rejected at the API gateway, before the request reaches the API. The response is 401 Unauthorized with a two-field JSON body:
401 Unauthorized
{
"error": "Unauthorized",
"message": "Missing Authorization token"
}Errors raised by the API itself (for example a 400 validation error) use a different, five-field body. A 403 means the token is valid but not allowed to call that operation. Both are covered in Errors and limits.
Do not retry a 401 or 403. Fix the token or ask us to enable the operation, then send again.
IP allow-listing#
REST API access is controlled by the Bearer token. IP allow-listing applies to SMPP binds: the source IPs for each bind are agreed and allow-listed when we provision it. See SMPP.
OAuth for Facebook Pages and Instagram#
OAuth is used for one thing only: connecting your Facebook Page or Instagram professional account so the platform can message on its behalf. Your API calls still use the Bearer token.
| Channel | Endpoint | What it returns |
|---|---|---|
| Messenger | POST /messenger/oauth/generate-link |
An encrypted onboarding link to connect a Facebook Page |
POST /instagram/oauth/generate-link |
An encrypted onboarding link to connect an Instagram account | |
POST /whatsapp/generate-link |
An encrypted Meta Embedded Signup link (returns 201) |
Open the link as the Page or business admin and complete Meta's consent screens. The calls take no request body; your identity comes from the token.
cURL
curl -X POST https://api.broadnet.me/messenger/oauth/generate-link \
-H "Authorization: Bearer $BROADNET_TOKEN"Legacy credentials#
Older SMPP-era integrations may use the legacy HTTP API under /websmpp, which takes a username and password as request parameters. Credentials in URLs end up in server and proxy logs, so new integrations should use the Bearer-token REST API described here.
Next steps#
- Quickstart: send your first SMS with your token.
- Errors and limits: error bodies, retries and rate limits.
- Messenger and Instagram: connect a Page or account, then send.
Ready to send your first message?
Request test credentials. An engineer sets up your account, and test sends go to your own verified numbers.
Request test access