Migrate from Plivo to SimpleSMS

Moving SMS to SimpleSMS means three renames in the send call, a new webhook handler, and porting your numbers. The console importer reads your numbers, applications and Powerpacks and prepares the SimpleSMS side for review. This guide walks through the importer and then the code.

What you need

  • A SimpleSMS account with a sandbox key (signup).
  • Your Auth ID (20 characters) and Auth Token.
  • For porting: the authorized person's full name, the account number, and the last 4 digits of a port-out PIN if there is one. The importer pre-fills the account number field from your Auth ID.

Run the importer

  1. In the console open Numbers, then Import from another provider, and choose what you send: transactional, marketing, or both.
  2. Choose Plivo, enter the Auth ID and Auth Token, and select Scan account. The scan reads your applications, numbers and Powerpacks with read-only requests.
  3. Review the plan. Deselect anything you do not want.
  4. Complete the port authorization and confirm.

What the importer brings over

In your accountBecomes in SimpleSMS
A number with SMS enabledA port request, tagged from-plivo
The message URL of the application a number is attached toA webhook endpoint subscribed to message.received, message.opted_out and message.opted_in
A PowerpackA sender pool with the same name; its numbers join as their ports complete
A number's aliasThe number's label

The importer does not create an endpoint for delivery reports from this provider. Add one for message.sent, message.delivered and message.failed yourself in the console under Webhooks. If Powerpacks cannot be read, the numbers are still listed, without pools, and the plan says so.

Change the code

Send with one JSON request and a bearer key:

bash
curl -X POST https://api.joinsimplesms.com/v1/messages \
  -H "Authorization: Bearer $SIMPLESMS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"from": "+15005550100", "to": "+15005550006", "body": "Your code is on the way."}'
javascript
import { SimpleSMS } from 'joinsimplesms';

const sms = new SimpleSMS(process.env.SIMPLESMS_API_KEY);

await sms.messages.send({
  from: '+15005550100',
  to: '+15005550006',
  body: 'Your code is on the way.',
});
In your current codeIn SimpleSMS
Auth ID and Auth Token as HTTP Basic authOne API key: Authorization: Bearer ssms_sk_...
srcfrom
dstto (one recipient per call; use a batch for many)
textbody
powerpack_uuid in place of srcA pool id (pool_...) as from
url on each send for delivery reportsA webhook endpoint on the account
X-Plivo-Signature-V2 header with a noncesimplesms-signature header: t=<timestamp>,v1=<HMAC-SHA256>

Write numbers in E.164 with the plus sign (+14155550132). The API also accepts 10 digit US and Canada numbers and normalizes them.

Rewrite the webhook handler

Inbound messages and delivery reports both arrive as signed JSON events at the endpoints registered on your account:

javascript
import { verifyWebhook } from 'joinsimplesms';

// Express: mount with express.raw({ type: 'application/json' }) so req.body is the raw bytes.
app.post('/webhooks/sms', async (req, res) => {
  let event;
  try {
    event = await verifyWebhook({
      payload: req.body,
      signature: req.headers['simplesms-signature'],
      secret: process.env.SIMPLESMS_WEBHOOK_SECRET,
    });
  } catch {
    return res.status(400).end();
  }

  if (event.type === 'message.received') {
    // event.data has message_id, from, to and body
  }
  if (event.type === 'message.delivered' || event.type === 'message.failed') {
    // event.data.message_id is the message you sent
  }
  res.status(200).end();
});

SimpleSMS posts one JSON event per delivery: { id, type, created_at, data }. Each endpoint has its own signing secret (whsec_...), shown next to the endpoint in the console. Respond with a 2xx within 5 seconds; a failed delivery is retried with backoff and can be replayed from the console (webhooks).

To send one message to a list, create a batch of up to 10,000 recipients. It validates numbers, removes duplicates and opted-out recipients, and reports results per recipient.

After the import

  • Keep your current service running until each port completes. Running the plan creates things only on the SimpleSMS side. A number moves when the carrier completes its port, and each port shows its status in the console (requested, submitted, foc_set, complete, or rejected with the reason). See Number porting.
  • Register before you text the public. A US local number can reach people other than your verified recipients only once it is linked to an approved brand and campaign. Start the registration while the ports are in flight; carrier review usually takes 3 to 7 business days.
  • Bring your opt-outs. The importer does not copy a suppression list. Export yours and load it with POST /v1/consent/import (up to 500 numbers per call) or in the console, so nobody who said STOP hears from you again. From the first inbound message SimpleSMS enforces STOP, START and HELP itself (opt-out and consent).
  • Rehearse in the sandbox. A test key runs every endpoint with simulated delivery and real, signed webhooks, so the new handler can be finished before a single number has moved (sandbox).

What the importer does not move

  • Message history, contacts and templates. Contacts can be imported separately from a CSV (contacts).
  • Numbers outside the United States and Canada. They are listed and skipped.
  • Numbers that are not SMS-enabled. SimpleSMS numbers are for SMS only.
  • More than 2,000 numbers in one scan.

Your credentials are used for read-only requests during the scan and are not stored, logged or echoed back.

More in migrate