Valid Sender ID Formats:

Type Max Length Examples
Alphanumeric 11 characters SMSPM, MyApp, Shop.com
Numeric 15 digits 372567890, 1234567890

Code Example:

// ❌ Wrong - not approved
{
  fromNumber: "My Super Long Company Name"; // Too long!
}

// ✅ Correct - approved in account
{
  fromNumber: "SMSPM"; // Must be in your approved list
}

4. "Hash is required"

Error Message:

{
  "error": "Hash is required"
}

Cause: Missing hash parameter

Solutions: ✅ Add hash parameter to request
✅ Get hash from User Account → API
✅ Verify hash is complete (no truncation)
✅ Check for typos


5. "Message text is required"

Error Message:

{
  "error": "Message text is required"
}

Cause: Empty or missing text parameter

Solutions: ✅ Ensure text parameter is not empty
✅ Check for accidental null/undefined values
✅ Verify text is a string, not an object

Code Example:

// ❌ Wrong
{
  text: ""; // Empty!
}
// or
{
  text: null; // Null!
}

// ✅ Correct
{
  text: "Hello World"; // Has content
}

6. "At least one recipient number is required"

Error Message:

{
  "error": "At least one recipient number is required"
}

Cause: Empty toNumber array or missing parameter

Solutions: ✅ Ensure toNumber has at least one phone number
✅ Check array is not empty
✅ Verify variable is defined

Code Example:

// ❌ Wrong
{
  toNumber: []; // Empty array!
}

// ✅ Correct (single)
{
  toNumber: "37256789045";
}

// ✅ Correct (multiple)
{
  toNumber: ["37256789045", "37257788990"];
}

7. HTTP 405 Method Not Allowed

Error: Browser or tool shows "405 Method Not Allowed"

Cause: Using wrong HTTP method

Solutions: ✅ Use GET or POST methods only
✅ For bulk sends, prefer POST
✅ Check your HTTP client configuration

Code Example:

// ❌ Wrong
fetch(url, { method: "PUT" }); // Not supported!

// ✅ Correct
fetch(url, { method: "POST" });

Issues by Symptom

Messages Not Being Delivered

Check:

  1. ✅ Verify phone number is correct and active
  2. ✅ Check your account balance (User Account → Dashboard)
  3. ✅ Confirm sender ID is approved
  4. ✅ Verify you received success response from API
  5. ✅ Check if number is on DND (Do Not Disturb) list
  6. ✅ Wait a few minutes - delivery can take 1-3 minutes

How to Debug:

const response = await sendSMS(data);
console.log("API Response:", JSON.stringify(response, null, 2));

// Success response should look like:
// {
//   "messages": [{
//     "id": "uuid-here",
//     "toNumber": "37256789045",
//     "status": "Added to queue"
//   }]
// }

Unicode Characters Not Displaying

Symptoms: Emoji or special characters appear as ? or boxes

Solutions: ✅ Ensure UTF-8 encoding in your code
✅ For GET requests, properly URL encode Unicode
✅ Use POST requests for easier Unicode handling
✅ Test with simple emoji first (😊)

Code Example:

// ❌ Wrong (GET with unencoded Unicode)
const url = `https://api.smspm.com?text=Hello 😊&...`;

// ✅ Correct (POST with Unicode)
fetch(url, {
  method: "POST",
  headers: { "Content-Type": "application/json; charset=utf-8" },
  body: JSON.stringify({
    text: "Hello 😊 Welcome!",
    // ... other params
  }),
});

// ✅ Correct (GET with encoded Unicode)
const text = encodeURIComponent("Hello 😊 Welcome!");
const url = `https://api.smspm.com?text=${text}&...`;

Long Messages Getting Cut Off

Symptoms: Only first part of message received

Cause: Message split into multiple parts, but only one sent

Solutions: ✅ API automatically splits messages - you should receive all parts
✅ Verify account has enough balance for all parts
✅ Check if carrier supports concatenated SMS
✅ Contact support if issue persists

Message Splitting:

  • Standard: 160 chars → splits at 153 chars per part
  • Unicode: 70 chars → splits at 67 chars per part

Example:

// A 350-character message will send as 3 separate SMS
const longMessage = "a".repeat(350); // 350 characters

// API handles splitting automatically
// Part 1: 153 chars
// Part 2: 153 chars
// Part 3: 44 chars
// Total: 3 SMS charged

CORS Errors in Browser

Error: "CORS policy: No 'Access-Control-Allow-Origin' header"

Cause: Making API calls directly from browser

Solutions:Best: Make calls from your backend server
✅ Never expose credentials in frontend code
✅ Use server-side proxy if needed

Architecture:

Browser → Your Server (API credentials here) → SMSPM API

Example:

// ❌ Wrong - Frontend calling API directly
// Frontend (browser.js)
fetch("https://api.smspm.com", {
  method: "POST",
  body: JSON.stringify({
    hash: "YOUR_HASH", // EXPOSED!
    token: "YOUR_TOKEN", // EXPOSED!
  }),
});

// ✅ Correct - Backend calling API
// Frontend (browser.js)
fetch("/api/send-sms", {
  // Your own server
  method: "POST",
  body: JSON.stringify({
    toNumber: "37256789045",
    text: "Hello",
  }),
});

// Backend (server.js)
app.post("/api/send-sms", async (req, res) => {
  const response = await fetch("https://api.smspm.com", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      hash: process.env.SMSPM_HASH, // Safe!
      token: process.env.SMSPM_TOKEN, // Safe!
      toNumber: req.body.toNumber,
      text: req.body.text,
      fromNumber: "SMSPM",
    }),
  });

  const data = await response.json();
  res.json(data);
});

Request Timeout

Symptoms: Request takes too long or times out

Solutions: ✅ Check your internet connection
✅ Increase timeout in your HTTP client
✅ Retry with exponential backoff
✅ Use smaller batches (split 100 into 2x50)

Code Example:

async function sendWithRetry(data, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const response = await fetch(apiUrl, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(data),
        signal: AbortSignal.timeout(30000), // 30 second timeout
      });

      return await response.json();
    } catch (error) {
      if (i === maxRetries - 1) throw error;

      // Wait before retry (exponential backoff)
      await new Promise((resolve) =>
        setTimeout(resolve, Math.pow(2, i) * 1000)
      );
    }
  }
}

Debugging Tips

1. Test with cURL First

# Test basic connectivity
curl -v "https://api.smspm.com?hash=YOUR_HASH&toNumber=37256789045&text=Test&fromNumber=SMSPM&token=YOUR_TOKEN"

2. Check Response Status

const response = await fetch(apiUrl, options);
console.log("Status:", response.status); // Should be 200
console.log("OK:", response.ok); // Should be true

const data = await response.json();
console.log("Data:", data);

if (data.error) {
  console.error("Error:", data.error);
}

3. Validate Your Data

function validateSMSRequest(data) {
  const errors = [];

  if (!data.hash) errors.push("Missing hash");
  if (!data.token) errors.push("Missing token");
  if (!data.toNumber) errors.push("Missing toNumber");
  if (!data.text) errors.push("Missing text");
  if (!data.fromNumber) errors.push("Missing fromNumber");

  if (data.toNumber) {
    const numbers = Array.isArray(data.toNumber)
      ? data.toNumber
      : [data.toNumber];

    numbers.forEach((num) => {
      const cleaned = num.toString().replace(/\D/g, "");
      if (cleaned.length < 5) {
        errors.push(`Invalid phone: ${num}`);
      }
    });
  }

  return errors;
}

// Usage
const errors = validateSMSRequest(myData);
if (errors.length > 0) {
  console.error("Validation errors:", errors);
} else {
  sendSMS(myData);
}

4. Log Everything (Development Only!)

console.log("=== SMS API Call ===");
console.log("Endpoint:", apiUrl);
console.log("Method:", "POST");
console.log("Payload:", {
  hash: data.hash.substring(0, 8) + "...", // Don't log full credentials
  token: "***", // Never log token
  toNumber: data.toNumber,
  text: data.text,
  fromNumber: data.fromNumber,
});

const response = await fetch(apiUrl, options);
console.log("Response Status:", response.status);

const result = await response.json();
console.log("Response Body:", result);
console.log("===================");

Still Having Issues?

Check System Status

Verify the API is operational (rare outages are announced via email)

Gather Debug Information

Before contacting support, collect:

  1. ✅ Your account hash (first 8 characters only)
  2. ✅ Example request (with token removed)
  3. ✅ Complete error message
  4. ✅ Timestamp of the issue
  5. ✅ Programming language and HTTP library used
  6. ✅ What you expected vs what happened

Contact Support

  • Email: [email protected]
  • Phone: +372 5451 5400 / +447 412 961 801
  • Hours: Daily 08:00-20:00 (GMT +2)

Support Email Template:

Subject: API Issue - [Brief Description]

Account Hash: 52248aec... (first 8 chars only)

Problem: [Describe what's not working]

Expected: [What should happen]

Actual: [What's actually happening]

Request Example (token removed):
{
  "hash": "52248aec...",
  "toNumber": "37256789045",
  "text": "Hello",
  "fromNumber": "SMSPM"
}

Error Response:
{
  "error": "..."
}

Timestamp: 2025-10-16 14:30:00 GMT+2

Environment: Node.js 18, using fetch API

Prevention Checklist

Use this checklist before deploying to production:

  • Credentials stored as environment variables
  • Phone numbers validated before sending
  • Error handling implemented
  • Retry logic for network failures
  • Rate limiting on your side
  • Logging (without exposing credentials)
  • Balance monitoring
  • Test with approved sender IDs
  • Unicode messages tested
  • Bulk sending tested with small batch first
  • Backend handles API calls (not frontend)

Happy troubleshooting! 🔧

Need more help? Check the Complete API Documentation or Quick Start Guide.