Changelog
2026-10-05: Opt-outs you can see
recipient_opted_out: a send to an opted-out number now answers403with its own code (it was the genericforbidden) and says when and how the person opted out, in the message and asopted_out_at,opted_out_viaandopted_out_method.failure.codeis stillopted_out. If you matched onforbiddenfor this case, match the new code.message.blocked: every refused send emits an event and webhook, is noted in the number's consent history, and is counted onGET /v1/consent/{phone}(blocked_sends,last_blocked_at).message.help_requested: emitted when a recipient texts HELP.- Replies in your name: STOP, START and HELP replies now name your business, and a registered number sends exactly the replies its registration filed, with your support contact. They used to name Delivered.
- START is confirmed: someone who was opted out gets one "you are resubscribed" reply. A repeat STOP no longer sends a second confirmation.
consent.get()is also available ascontacts.consent(phone)in the Node and Python SDKs.- The suppression list fails closed: if it cannot be read, a send
answers
503withRetry-Afterinstead of going out unchecked.
2026-10-05: Delivered is now SimpleSMS
The product has a new name and a new home, joinsimplesms.com. It is the same service, the same account, the same prices and the same terms; nothing you built has to change. Apart from the API host, everything issued under the Delivered name keeps working, with no end date:
- API host: this one changes.
api.deliveredsms.comandmcp.deliveredsms.comare retired and answer410 host_retiredwith the new host in the body. Point your base URL athttps://api.joinsimplesms.com/v1(MCP:https://mcp.joinsimplesms.com). Paths, request shapes and your key are unchanged. - API keys.
dsms_sk_...keys (andresms_sk_...) authenticate forever. Only newly created keys get the newssms_sk_prefix. - Webhook headers. Every delivery carries
simplesms-signature/simplesms-event-idand, with identical values,dsms-signature/dsms-event-id(and theresms-pair). Signing secrets are unchanged. - Response header.
X-Delivered-Sender-Stateis still sent, alongsideX-SimpleSMS-Sender-State. - Node package.
npm install deliveredsmsstill works: it re-exports the newjoinsimplesmspackage, andDelivered/DeliveredErrorare aliases ofSimpleSMS/SimpleSMSError(the same classes). - CLI.
deliveredsmsanddsmsstill run; the new command issimplesms. A key saved in~/.deliveredsms.jsonis still read. - Environment variables. The SDKs and CLI read
SIMPLESMS_API_KEYandSIMPLESMS_BASE_URLfirst, thenDELIVERED_API_KEYandDELIVERED_BASE_URL. - Agent skills.
/skills/deliveredand/skills/delivered-verifyredirect to/skills/simplesmsand/skills/simplesms-verify. - Your data. Numbers, webhook endpoints, registrations, opt-outs and message history were not migrated or re-created. They are where they were.
What does change, and when you would notice:
- Texts we send for you name SimpleSMS. The Verify template when you send no
app_name(SimpleSMS code: 482193...), and the sandbox suffix on texts to your own phone. Your own message bodies and your ownapp_nameare untouched. - Webhook requests identify as
SimpleSMS-Webhooks/1.0inUser-Agent(wasDelivered-Webhooks/1.0). Verify the signature, not the user agent. - The console lives at joinsimplesms.com. You sign in with the same account; the first visit to the new address asks you to sign in once.
To move over at your own pace: point your base URL at
api.joinsimplesms.com, install joinsimplesms, rename Delivered to
SimpleSMS, and read simplesms-signature in your webhook handler. None
of it is required.
2026-10-04: Sender status
- Numbers show where they stand. Every number carries
sender(test_only,pending,active,action_neededwith a plain reason). NewGET /v1/numbers/{number}, and thenumber.sender_updatedevent. See Numbers. - Test only until registered. A live US number that is not linked to an
approved registration can text your verified numbers and nobody else. Other
sends answer
403 sender_not_registeredwithX-Delivered-Sender-State. This replaces theX-Delivered-Registration/X-Delivered-Warningheaders, which are gone: unregistered traffic is now stopped instead of warned about. - Automatic linking. When a registration is approved, the account's live
numbers are linked to it and become
active; numbers bought later link on their own.POST /v1/numbers/{number}/registrationchooses a registration explicitly (up to 49 numbers each). - One form to go live. Submitting a registration from a sandbox account
is also the live-access request. Submit now requires complete business
details and answers
400naming what is missing.
2026-10-04: Automations
- Event-driven flows:
POST /v1/track(events.trackin the SDKs) records what a person did; a flow listening for that event sends, waits, waits for another event with a timeout, and branches. See Automations. /v1/automations: create, edit, activate, pause, and read runs with a step-by-step timeline. New key scopeautomations.- Webhook events:
automation.run.started,automation.run.completed,automation.run.failed. - Console: Automations, with three starter templates and a "Send a test event" button that works in the sandbox.
2026-10-04: Contacts API
/v1/contacts: create-or-update by phone number, retrieve, update, delete, and list withtagandphone_numberfilters. The same address book the console uses. See Contacts.POST /v1/contacts/import: bulk upsert, up to 500 per request, with skipped rows reported by index.POST /v1/contacts/bulk: add tags, remove tags, or delete for up to 500 contacts in one call.- New key scope
contacts.contactsresource in the Node and Python SDKs.
2026-10-01: Message observability
- Message timeline: every message records each step with a timestamp
(
accepted→validated→queued→sent_to_carrier→carrier_accepted→delivered/failed; inbound:received) astimelineonGET /v1/messages/{id}. segments,encoding,price,destination_carrieron every message.- Readable failures: failed messages,
message.failedevents, and refused sends (opt-out, content block, rate limit, spend limit) carry afailureobject with a stable code, a plain explanation, and what to do. See delivery failures. - List filters:
status,direction,to,from,created_after,created_before(alongsidecustomer_id) onGET /v1/messages, with full pages. Automatic carrier retries show up on the timeline per attempt. - Sandbox numbers for every failure, opt-out, rate limiting, and a really
delayed delivery. The happy-path number now settles to
deliveredinstead of stayingsent. - Idempotency-Key now applies to scheduled sends too.
- Console: message filters and a message inspector (timeline latencies, cost, failure, related webhook events).
2026-10-01: Reliability
- Automatic carrier retries: temporary carrier failures no longer fail a
send.
POST /v1/messagesanswers202with the messagequeuedand we retry it after 30s, 2m and 10m. New message fields:attempts,next_attempt_at. A message is never submitted twice. - Missing delivery reports: a sent message with no delivery report after
72 hours is marked
receipt_status: "missing". Its status stayssent. - Idempotency-Key on
POST /v1/verifyandPOST /v1/numbers. Failed requests now release their key. - Webhook delivery log: status code, latency, attempt and the first 2 KB of
your endpoint's response for every attempt, in the console and at
GET /v1/webhooks/deliveries.GET /v1/webhookslists endpoints. - Replay to one endpoint:
POST /v1/events/{id}/replay, and per-row Replay in the console. - Undelivered events: events whose retries ran out are kept for 30 days with one-click replay, instead of being dropped.
- Status page (and
/status.json) for the API, sending, inbound and webhooks.
2026-10-01: Customers and the Python SDK
- Customers (
/v1/customers): for platforms sending on behalf of other businesses. Assign numbers to a customer and its messages, verifications, events and webhooks carrycustomer_id;GET /v1/customers/{id}/usagereports per-customer usage by day. See Customers. customer_idonPOST /v1/messages,POST /v1/verify,POST /v1/numbers, newPATCH /v1/numbers/{number}, and filters onGET /v1/messagesandGET /v1/numbers. Numbers now always includecustomer_id(nullwhen unassigned).- Python SDK:
pip install joinsimplesms. No dependencies, typed, retries, idempotent sends, webhook verification. - Node SDK: consent and customers resources,
listAll()iterators, andverifyWebhook().
2026-10-01: Compliance autopilot (registration)
- Website disclosure check:
POST /v1/registrationschecks your website, privacy policy, terms and opt-in page against what carrier reviewers look for, with evidence and copy-paste fixes for every finding. - Generated copy: opt-in disclosure, privacy clause, SMS terms, samples, HELP/STOP replies, and the full brand + campaign draft.
- Registration workflow: recheck, submit, carrier review, rejections with
plain-language reasons and fixes, resubmission;
registration.updatedevents. See Compliance & registration. - Opt-in proof:
proofonPOST /v1/consent/{phone}and/v1/consent/export?type=ledger. - Live sends without an approved registration carry an
X-Delivered-Registrationwarning header. Nothing is blocked.
2026-10-01: Account controls
- Deliverability:
GET /v1/deliverabilityand Console → Deliverability report delivery rates by day, carrier, and sending number, with failure reasons. Sharp drops raise adeliverability.degradedwebhook event. - Spend limits: a monthly USD cap on live messaging with alert thresholds
(
GET/PATCH /v1/spend-limit). Sends past the cap returnspend_limit_reachedand are not charged;spend.threshold_reachedfires at each threshold. - Audit log: key, team, webhook, spend-limit, number, consent, and
settings changes, with actor and IP. Console → Audit log and
GET /v1/audit-logs. - Key scopes: restrict a key to the endpoint families it needs; others
answer
403 insufficient_scope. Existing keys keep full access. - Viewer role: read-only teammates.
2026-09-30: Spam scores retired
GET /v1/lookup/{phone}/spamnow answers 410 Gone (endpoint_retired). Its scores came from data SimpleSMS no longer uses.GET /v1/lookup/{phone}(line type and carrier) is unchanged. The MCPlookup_spamtool and the CLI's--spamflag are gone; the SDK'slookup.spam()is deprecated and throwsendpoint_retired.
2026-09-22: Pricing
- Outbound SMS is $0.009 per message, all-in. Carrier fees are still included and A2P 10DLC registration is still free; the rate simply now covers what a US text costs to deliver. Verification, numbers, lookups, and the free tier are unchanged.
- The pricing comparison now includes business-texting products (Text Request, Solutions by Text) alongside the API providers.
2026-08-14: Consent autopilot (TCPA)
- Revocation in plain English: "please stop texting me" now opts a number out, not just the STOP keyword. Three detection tiers (keyword, phrase, AI with confidence scores), per the FCC's April 2025 reasonable-means rule.
- Consent ledger: every opt-out, opt-in, import and verification exemption is appended to a per-number history that is never deleted.
- Consent API:
GET/POST /v1/consent/{phone}, paginatedGET /v1/consent, bulk/v1/consent/import(up to 500), and CSV/v1/consent/export. - Console Compliance page: suppression list with per-number history, import, export, and the verification-exemption audit log.
message.opted_outevents now carrymethodand (for AI detections)confidence;verification.sent_to_opted_outis now subscribable as a webhook event.
2026-08-06: Early access launch
- Sandbox-first API surface:
/v1/messages(send, get, list, Idempotency-Key support),/v1/numbers(search, purchase, release),/v1/lookup(+/spam),/v1/events, andPOST /v1/test/inboundfor simulating inbound SMS. - Self-serve console at /console: instant free sandbox keys, no card.
- Live mode (after live-access review): real number provisioning across 200+ US/Canada area codes and real SMS delivery.
- Agent surface: OpenAPI (yaml ·
json),
llms.txt, single-file docs (llms-full.txt), markdown twins of every docs page, an MCP server, and an agent skill (simplesms).
Known limitations
- Live delivery receipts are not yet emitted; a live message's status stays
sent(sandbox simulates the full lifecycle). Webhook endpoints shipped 2026-08-13.
Get product updates
New features and API changes, by email. Or follow the Atom feed.