Sending messages
Send an outbound SMS with POST /api/messages, including the credit cost model, response shape, and error codes.
Sending messages
Send an outbound SMS to a single recipient. The message is dispatched through the phone gateway and the cost is debited from your sms_credits balance.
https://sms.hep.gg/api/messagesAuth requiredRequest
Send the body as application/x-www-form-urlencoded (JSON is also accepted). Authenticate with your raw API key in the Authorization header, with no Bearer prefix.
recipient+447700900000. Validated by the server; an invalid or missing number returns an error.contentThe sender is fixed server-side (defaults to +2899682626); callers cannot set it.
Credit cost
Each message costs one credit per 160-character segment:
creditCost = max(1, ceil(content_length / 160))
So a 1 to 160 character message costs 1 credit, 161 to 320 costs 2, and so on. Credits are debited atomically from your sms_credits balance before the message is dispatched. If your balance is lower than the cost, the send is rejected and nothing is debited. Each spend is recorded in your unified transaction log on the dashboard.
Response
On success you get 200 with the sent-message payload.
{
"ID": "a1b2c3d4-...",
"sent_from": "+2899682626",
"sent_to": "+447700900000",
"sent_to_parsed": {
"isValid": true,
"phoneNumber": "+447700900000",
"countryIso2": "GB",
"countryIso3": "GBR",
"countryCode": "+44"
},
"content": "Hello from Hep.gg",
"owner": "your-hepgg-user-id",
"creditCost": 1
}IDsent_fromsent_tosent_to_parsedisValid, phoneNumber (E.164), countryIso2, countryIso3, and countryCode.contentownercreditCostExamples
curl -X POST https://sms.hep.gg/api/messages \
-H "Authorization: $SMS_KEY" \
-d "recipient=+447700900000" \
-d "content=Hello from Hep.gg"const res = await fetch("https://sms.hep.gg/api/messages", {
method: "POST",
headers: {
Authorization: process.env.SMS_KEY,
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
recipient: "+447700900000",
content: "Hello from Hep.gg",
}),
});
if (!res.ok) {
const { error } = await res.json();
throw new Error(`SMS send failed: ${error}`);
}
const message = await res.json();
console.log(message.ID, message.creditCost);Errors and status codes
Validation and entitlement failures return 400 with a JSON error string. Authentication failures from the auth layer return 401 or 403.
| Status | Body | When |
|---|---|---|
400 | { "error": "Please provide content to send along with this request." } | content is missing or empty. |
400 | { "error": "Invalid Recipient Phone Number Or None Provided." } | recipient is missing or not a valid number. |
400 | { "error": "Content too long, please keep it under 800 characters. You can send multiple messages!" } | content is 800 characters or more. |
400 | { "error": "Content too short, please send 1 character or more." } | content is empty after parsing. |
400 | { "error": "You don't have enough credits to complete this request." } | Your sms_credits balance is below the cost. |
400 | { "error": "Invalid authentication token" } | The key passed the gate but failed re-validation during send. |
400 | { "error": "This API key is disabled" } | The key is disabled. |
400 | { "error": "Your account is not enabled for SMS sending" } | Your account is not enabled for SMS. |
401 | { "error": "Unauthorized: No API Key Provided" } | No Authorization header. |
401 | { "error": "Unauthorized: Incorrect Token" } | The key does not match any account (this is what you get if you mistakenly send a Bearer prefix). |
403 | { "error": "This API key is disabled" } | The key is disabled. |
403 | { "error": "Your account is not enabled to use this API. Join https://hep.gg/support for more information." } | Your account is not enabled for SMS. |
There is no rate-limit response documented and no pagination; this endpoint sends exactly one message per call.