SMS and MMS
Connect Twilio, Amazon SNS, AWS End User Messaging, or Azure Communication Services to the local text emulator.
What Sqrzl does
Sqrzl captures outbound text requests, stores them for inspection, and lets you simulate inbound messages and delivery updates. It does not send messages through a carrier. Start Sqrzl with the quickstart; SMS APIs use http://localhost:9000 and the admin UI uses http://localhost:9001.
Provider endpoints
| Provider | Local entry point | Supported send operation |
|---|---|---|
| Twilio | http://localhost:9000 | POST /2010-04-01/Accounts/{AccountSid}/Messages.json |
| Amazon SNS | http://localhost:9000 | Query API Publish with a direct phone number. |
| AWS End User Messaging SMS Voice v2 | http://localhost:9000 | SendTextMessage and SendMediaMessage. |
| Azure Communication Services SMS | http://localhost:9000 | POST /sms?api-version=... with one or more recipients. |
Connect an SDK
Twilio
import os
import twilio
client = twilio.Client(
os.environ["SQRZL_TWILIO_ACCOUNT_SID"],
os.environ["SQRZL_TWILIO_AUTH_TOKEN"],
)
client.api.base_url = "http://localhost:9000"
message = client.messages.create(
to="+15550001001",
from_="+15550001000",
body="Local Sqrzl test",
)Configure both SQRZL_TWILIO_ACCOUNT_SID and SQRZL_TWILIO_AUTH_TOKEN on Sqrzl to require Basic authentication and sign Twilio callbacks.
Amazon SNS
import boto3
client = boto3.client(
"sns",
endpoint_url="http://localhost:9000",
aws_access_key_id="admin",
aws_secret_access_key="sqrzl-secret",
region_name="us-east-1",
)
client.publish(
PhoneNumber="+15550001002",
Message="Local Sqrzl test",
)AWS End User Messaging SMS Voice v2
import boto3
client = boto3.client(
"pinpoint-sms-voice-v2",
endpoint_url="http://localhost:9000",
aws_access_key_id="admin",
aws_secret_access_key="sqrzl-secret",
region_name="us-east-1",
)
client.send_text_message(
DestinationPhoneNumber="+15550001003",
OriginationIdentity="+15550001000",
MessageBody="Local Sqrzl test",
MessageType="TRANSACTIONAL",
)The v2 adapter also supports send_media_message with an optional S3 media URI, plus DryRun validation without capture.
Azure Communication Services SMS
import base64
from azure.communication.sms import SmsClient
from azure.core.pipeline.transport import RequestsTransport
class LocalHttpTransport(RequestsTransport):
def send(self, request, **kwargs):
if request.url.startswith("https://"):
request.url = "http://" + request.url.removeprefix("https://")
return super().send(request, **kwargs)
access_key = base64.b64encode(b"shared-secret").decode("ascii")
connection = (
"endpoint=http://localhost:9000;accesskey=" + access_key
)
client = SmsClient.from_connection_string(
connection,
transport=LocalHttpTransport(),
)
client.send(
from_="+15550001000",
to=["+15550001004", "+15550001005"],
message="Local Sqrzl test",
enable_delivery_report=True,
)The ACS SDK normalizes its endpoint to HTTPS. This transport rewrites the signed request to the emulator's local HTTP listener. Set SQRZL_ACS_CONNECTION_STRING on Sqrzl with the same access key.
Configure authentication
- Twilio uses
SQRZL_TWILIO_ACCOUNT_SIDandSQRZL_TWILIO_AUTH_TOKENtogether. - AWS adapters use
SQRZL_ACCESS_KEY_IDandSQRZL_SECRET_ACCESS_KEYwhen generic API authentication is enabled. - ACS SMS uses the shared key in
SQRZL_ACS_CONNECTION_STRING.
The checked-in Compose file sets generic credentials to admin and sqrzl-secret. See configuration to change them.
Inspect and simulate messages
Open http://localhost:9001 and choose Texts. The admin surface lets you search messages and conversations, inject an inbound message, change an outbound message to delivered or failed, configure callback destinations by provider and local number, inspect callback requests and their bounded responses, and create linked retries.
Delivery changes are explicit. Sqrzl does not advance messages on a timer. Callback failures do not undo a captured message or delivery state; redirects are not followed.
Callback access
Callback destinations may use localhost, 127.0.0.1, or ::1 by default. Add other local callback hosts as a comma-separated list in SQRZL_TEXT_CALLBACK_ALLOWED_HOSTS. Each callback attempt times out after 5000 ms by default; set SQRZL_TEXT_CALLBACK_TIMEOUT_MS to change the limit.
A Twilio StatusCallback URL must pass the same host allowlist. Outbound media URLs are references only: Sqrzl does not fetch them. Inbound Twilio simulations can include base64 media that is stored and served from authenticated Twilio-shaped media URLs.
Supported scope
- Twilio accepts
To,FromorMessagingServiceSid, an optional body up to 1600 characters, up to 10 absolute HTTP(S) media URLs, and an optional allowlisted status callback. A service-selected sender initially returns accepted with zero segments; an explicit sender returns queued. - SNS accepts direct E.164
PhoneNumberPublish requests, raw messages orMessageStructure=jsonselecting thesmsvalue withdefaultfallback, and up to 10 message attributes. - SMS Voice v2 accepts the documented JSON fields for its text and media send operations. MMS can reference one optional S3 media URI; remote media is never fetched.
- ACS SMS supports API versions
2021-03-07and2026-01-23, 1 to 100 E.164 recipients, per-recipient repeatability results, delivery-report options, tags, and timeouts from 60 to 43200 seconds. Rejected recipients in a mixed result are not captured.
SNS topics and fan-out, AWS inbound MMS, ACS MMS, TwiML execution, WhatsApp, RCS, voice calls, automatic delivery timing, remote media fetching, and provider management APIs are unsupported. Check the compatibility matrix for exact request fields and errors.
Request and capture limits
SQRZL_MAX_REQUEST_BYTES defaults to 128 MiB per HTTP request body. Separately, each capture transaction has a conservative 64 MiB projected aggregate materialization limit, including message fan-out copies and inline media.
Oversized requests receive a provider-shaped 413 and create no partial captures. This capture limit is separate from the request-body setting; see configuration for that setting.