API Documentation

QuickSMS API Documentation

Send SMS and RCS messages globally with delivery tracking, smart routing, and real-time webhooks.

Base URL https://api.quicksms.com
Protocol HTTPS only
Version 2.0 · March 2026
Jump to API

Quick Start

Send your first SMS in under two minutes.

Prerequisites

  1. Create a free test account at portal2.quicksms.com/signup
  2. Create an API connection in Management > API Connections
  3. Copy your API key (starts with sk_live_ or sk_test_)

Send a Test Message

Use your sk_test_ key to send in sandbox mode. No credits are deducted and no real SMS is delivered.

curl -X POST https://api.quicksms.com/v1/messages \
  -H "Authorization: Bearer sk_test_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "MSISDN": "447700900001",
    "msg": "Hello from QuickSMS!",
    "sender": "QuickSMS"
  }'
Test sender restriction In test mode, you must use the QuickSMS default test sender. To use a custom sender ID:
Register an SMS Sender ID
Purchase a Virtual Mobile Number
Test allowlist Test accounts (sk_test_ keys) can only send to numbers in your approved test allowlist. Add test numbers in API Connections. The text "This is a QuickSMS test message" is automatically appended.

Expected Response

{
    "sandbox": true,
    "total": 1,
    "accepted": 1,
    "rejected": 0,
    "messages": [{
        "quicksms_id": "msg_80fac5c752941b27",
        "MSISDN": "447700900001",
        "sender": "QuickSMS",
        "status": "ACCEPTED",
        "channel": "SMS",
        "encoding": "GSM-7",
        "message_parts": 1
    }],
    "created_at": "2026-03-26T12:00:00+00:00"
}

Switch to Production

Replace your sk_test_ key with your sk_live_ key. Ensure your sender ID is approved for the destination country. Credits will be deducted per message segment.

Authentication

All API requests require a valid API key in the Authorization header.

Bearer Token (Recommended)

Authorization: Bearer sk_live_EXAMPLE_KEY_REPLACE_ME

Basic Authentication

For backwards compatibility. Send your API key as the username with an empty password.

Authorization: Basic base64(sk_live_EXAMPLE_KEY_REPLACE_ME:)
Note The header value must be the Base64 encoding of your_api_key: (note the trailing colon). The password field is ignored.

API Key Types

PrefixEnvironmentBehaviour
sk_live_ProductionSends real messages. Deducts credits.
sk_test_TestForces sandbox mode. Can only send to approved test numbers.

Connection Status

Only active connections can send messages.

StatusCan Send?Description
draftNoCreated but not yet activated
activeYesFully operational
suspendedNoTemporarily disabled by admin
archivedNoPermanently disabled

IP Allowlisting

Optionally restrict access to specific IPs. Unlisted IPs receive 403 with error code IP_NOT_ALLOWED. Configure at portal2.quicksms.com/account/security.

Brute-Force Protection

After 10 consecutive failed auth attempts from the same IP within 60 seconds, that IP is locked out for 5 minutes. The response includes a Retry-After header.

Best Practices

  • Store API keys in environment variables or a secrets manager — never commit to source control.
  • Use sk_test_ keys in development/staging; reserve sk_live_ keys for production.
  • If a key may be compromised, rotate it immediately in portal2.quicksms.com.
  • Enable IP allowlisting in production.

Send a Message

Send an SMS or RCS message to a single recipient. The API validates, prices, and queues the message in a single request.

POST https://api.quicksms.com/v1/messages

Request Headers

HeaderDescription
AuthorizationRequiredBearer sk_live_xxx or Basic base64(sk_live_xxx:)
Content-TypeRequiredapplication/json
Idempotency-KeyOptionalUnique key (max 128 chars) to prevent duplicate sends

Request Body

FieldTypeDescription
MSISDNstringRequiredRecipient phone number. International format, digits only, no + prefix. 7–15 digits. E.g. 447700900000
msgstringRequiredMessage content. 1–1,530 characters.
senderstringRequiredSender ID. Must be pre-registered and approved.
smart_routingbooleanOptionalEnable RCS with SMS fallback. Default false.
sms_failover_senderstringOptionalSMS sender ID to use if RCS falls back to SMS.
expiryintegerOptionalValidity in seconds. Min 60, max 259,200 (72h). Default 172,800 (48h).
customer_idstringOptionalYour reference. Max 128 chars. Returned in DLR webhooks.
metadataobjectOptionalKey-value pairs. Max 10 keys, each value max 256 chars.
sandboxbooleanOptionalForce sandbox mode. Default false.
callback_urlstringOptionalPer-message DLR webhook URL. Max 2,048 chars.

MSISDN Format

MSISDN (Mobile Station International Subscriber Directory Number) is the international phone number format used by telecom APIs. Digits only, country code prefix, no +.

ExampleCountry
447700900000United Kingdom (+44)
353871234567Ireland (+353)
12025551234United States (+1)

Sender ID Formats

TypeRulesExample
AlphanumericMax 11 chars. Must contain at least one letter.MyStore
NumericMax 15 digits.447700900000
RCS agentMax 25 chars. Only when smart_routing is true.MyBrandAgent

Example Request

curl -X POST https://api.quicksms.com/v1/messages \
  -H "Authorization: Bearer sk_live_EXAMPLE_KEY_REPLACE_ME" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-12345-sms" \
  -d '{
    "MSISDN": "447700900000",
    "msg": "Your order #12345 has been dispatched.",
    "sender": "MyStore",
    "customer_id": "cust_abc123",
    "metadata": { "order_id": "12345", "type": "dispatch_notification" },
    "callback_url": "https://example.com/webhooks/sms"
  }'

Try It

Understanding Responses

Every send request returns one of three outcomes.

Success — Message Queued

202 Accepted Message queued for delivery
{
    "sandbox": false,
    "total": 1,
    "accepted": 1,
    "rejected": 0,
    "messages": [{
        "quicksms_id": "msg_80fac5c752941b27",
        "MSISDN": "447700900000",
        "sender": "MyStore",
        "status": "ACCEPTED",
        "channel": "SMS",
        "encoding": "GSM-7",
        "message_parts": 1,
        "customer_id": "cust_abc123"
    }],
    "created_at": "2026-03-26T12:00:00+00:00"
}
What to do next Store the quicksms_id. If you configured a callback_url, you will receive a delivery receipt when the message reaches a final status. There is no need to poll.

Success — Message Held

202 Accepted Held by out-of-hours restriction
{
    "sandbox": false,
    "messages": [{
        "quicksms_id": "msg_80fac5c752941b27",
        "status": "HELD",
        "scheduled_send_at": "2026-03-27T08:00:00+00:00"
    }]
}
What to do next No action required. The message will be sent automatically at scheduled_send_at. Credits are reserved immediately.

Rejection — Message Not Sent

422 Unprocessable Entity Validation failed
{
    "messages": [{
        "MSISDN": "447700900000",
        "status": "REJECTED",
        "error": {
            "code": "CONTENT_BLOCKED",
            "message": "Message content was blocked by the content filter."
        }
    }]
}
What to do next Check the error.code field and refer to the Error Handling section for corrective action.

Response Fields

FieldTypeDescription
sandboxbooleanWhether sandbox mode was used
totalintegerTotal messages in the request
accepted / rejectedintegerCounts of accepted and rejected messages
messages[].quicksms_idstringUnique message ID (msg_{16 hex}). Only present when accepted.
messages[].statusstringACCEPTED, HELD, or REJECTED
messages[].channelstringSMS or RCS
messages[].encodingstringGSM-7 or UCS-2. null for RCS.
messages[].message_partsintegerSMS segment count. Always 1 for RCS.
messages[].scheduled_send_atstringISO 8601. Only when status is HELD.
messages[].errorobjectcode and message. Only when REJECTED.
created_atstringISO 8601 timestamp

Message Encoding

The API automatically selects the most efficient encoding for your message content.

GSM-7 (Standard)

SegmentsCharacters
1Up to 160
2161–306
3307–459
N⌈length ÷ 153⌉

UCS-2 (Unicode)

SegmentsCharacters
1Up to 70
271–134
3135–201
N⌈length ÷ 67⌉
Cost impact Cost is per segment. A single emoji forces UCS-2 (70-char limit instead of 160). RCS messages are always billed as 1 part regardless of length.
SMS & RCS Character Counter Try our free SMS & RCS Character Counter to check encoding, segment count, and cost before sending.

Delivery Webhooks (DLR)

When a message reaches a final delivery status, QuickSMS sends a POST request to your configured callback URL.

Callback URL Priority

PrioritySourceHow to Configure
1 (highest)Per-message callback_urlInclude in the send request body
2Connection-level URLSet at portal2.quicksms.com/management/api-connections

If neither is configured, no webhook is delivered.

Webhook Headers

POST {your_callback_url}
Content-Type: application/json
X-QuickSMS-Timestamp: 1711468800
X-QuickSMS-Event: dlr
X-QuickSMS-Delivery-Attempt: 1
X-QuickSMS-Signature: sha256=5d7a8c3e...

Webhook Payload

{
    "quicksms_id": "msg_80fac5c752941b27",
    "customer_id": "cust_abc123",
    "channel": "SMS",
    "message_status": "DELIVERED",
    "status_code": 0,
    "message_parts": 1,
    "message_sent_time": "2026-03-26T12:00:01+00:00",
    "delivery_receipt_time": "2026-03-26T12:00:03+00:00",
    "read_receipt": null,
    "read_receipt_timestamp": null,
    "done_time": "2026-03-26T12:00:03+00:00",
    "metadata": { "order_id": "12345" }
}

Payload Fields

FieldTypeDescription
quicksms_idstringMessage ID from send response
customer_idstring|nullYour reference (if provided)
channelstringActual channel: SMS or RCS. May differ from original if RCS fell back.
message_statusstringFinal delivery status
status_codeintegerGSM status code
message_partsintegerSegment count
read_receiptbool|nulltrue if read (RCS only). null for SMS.
read_receipt_timestampstring|nullISO 8601 — when read (RCS only)
done_timestringISO 8601 — when message reached final status
metadataobject|nullYour metadata (if provided)

Retry Policy

Return any 2xx to acknowledge. Failures are retried with exponential backoff:

AttemptDelay
1Immediate
230 seconds
32 minutes
410 minutes
51 hour
After 5 failed attempts the webhook is dropped. Message status is unaffected — check the portal.

Best Practices

  • Respond quickly. Return 200 immediately and process asynchronously.
  • Handle duplicates. Use quicksms_id as a deduplication key.
  • Verify signatures. Validate X-QuickSMS-Signature before processing.

Message Lifecycle

A message moves through distinct statuses from submission to final delivery.

Send Response Statuses

StatusMeaningNext Step
ACCEPTEDQueued for deliveryWait for DLR webhook
HELDDelayed by out-of-hours rulesAuto-dispatched at scheduled_send_at
REJECTEDFailed validation — not sentCheck error.code and fix

Delivery Statuses (via Webhook)

StatusFinal?Meaning
PENDINGNoAwaiting carrier confirmation
DELIVEREDYesConfirmed delivered to handset
UNDELIVEREDYesDelivery failed (e.g. phone off)
EXPIREDYesValidity period elapsed
REJECTEDYesRejected by carrier

Status Flow

Send Response              Delivery Webhook
─────────────              ─────────────────

  ACCEPTED ──────────────▶ PENDING
                              │
                              ├──▶ DELIVERED
                              ├──▶ UNDELIVERED
                              ├──▶ EXPIRED
                              └──▶ REJECTED

  HELD ───(at scheduled)──▶ PENDING ──▶ (same as above)

  REJECTED                  (no webhook — message was never sent)

GSM Status Codes

CodeMeaning
0Delivered successfully
1Invalid destination number
13Rejected by operator
27Absent subscriber (phone off or out of range)
32Network error
255Unknown / expired

Retry Strategy

Not all errors should be retried. Use the HTTP status code to decide.

StatusRetry?Strategy
429YesWait for Retry-After header value, then retry.
500YesRetry with exponential backoff.
503YesService degraded. Retry with backoff.
400–422NoFix the request before resending.

Recommended Backoff

AttemptBase DelayWith Jitter
11 second0.8–1.2s
22 seconds1.6–2.4s
34 seconds3.2–4.8s
48 seconds6.4–9.6s
516 seconds12.8–19.2s
Stop after 5 attempts. Log the failure with the request_id. Always include the same Idempotency-Key when retrying sends to guarantee at-most-once delivery.

Rate Limits

Applied per API connection using a 60-second sliding window. Default: 1,000 requests per minute.

HeaderDescription
X-RateLimit-LimitMaximum requests per minute
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when the window resets
Monitoring guidance Monitor X-RateLimit-Remaining. Throttle when below 10% of your limit. On 429, wait for Retry-After seconds. Ramp up gradually after reset.

Idempotency

Include an Idempotency-Key header (max 128 chars) to prevent duplicate sends.

ScenarioResult
Same key + same payloadReturns cached 202. No duplicate send.
Same key + different payload409 ConflictIDEMPOTENCY_CONFLICT
New keyNormal processing
Key exceeds 128 chars422 validation error

Keys are scoped to your API connection and cached for 24 hours.

Strategy Tie keys to your business event (e.g. order-12345-dispatch-sms) rather than random UUIDs. This makes retries naturally use the same key.

Smart Routing (RCS)

When smart_routing is true and the sender is an approved RCS agent:

  1. Message is routed via RCS
  2. If the recipient doesn't support RCS, the system falls back to SMS automatically
  3. Credits are adjusted — if SMS costs more, the difference is deducted; if less, refunded
  4. DLR webhook channel field indicates which channel was actually used
  5. RCS is billed per message (always 1 part), not per segment
Read receipts RCS supports read receipts. The DLR webhook includes read_receipt: true and read_receipt_timestamp when a recipient reads an RCS message. These are null for SMS.

SMS Failover Sender

When an RCS message falls back to SMS, the sender ID is resolved in this order:

PrioritySourceDescription
1 (highest)sms_failover_sender fieldExplicit sender ID in the API request
2Default registered senderSender marked is_default = true on your account
3First approved senderFirst approved sender on your account
4 (last resort)Sanitised agent nameRCS agent name stripped of non-alphanumeric chars, truncated to 11 chars
Important Always set a default sender on your account or provide sms_failover_sender explicitly. Without either, the fallback sender may not match your brand.

Out-of-Hours Sending

Accounts can restrict dispatch to a defined business hours window. Configured per account in the portal.

ActionAPI BehaviourCredits
rejectMessage rejected with OUT_OF_HOURS. Response includes the window and resume time.Not deducted
holdAccepted with status HELD. Dispatched when window opens. Includes scheduled_send_at.Reserved immediately
Out-of-hours restrictions are bypassed in sandbox mode.

Anti-Flood Protection

Prevents duplicate messages to the same recipient within a configurable window. A duplicate is the same account sending identical content to the same MSISDN within the window.

ModeBehaviour
offNo duplicate checking
enforceDuplicates rejected with DUPLICATE_MESSAGE. Response includes original message ID.
monitorDuplicates logged but message still sent
Anti-flood is bypassed in sandbox mode. Window length configured per account at portal2.quicksms.com/account/security.

Country Restrictions

The recipient's country is determined by MSISDN prefix (e.g. 44 = UK, 353 = Ireland). Per-account overrides are checked first, then the platform-wide setting. Blocked destinations return COUNTRY_NOT_ALLOWED.

Configure at portal2.quicksms.com/account/security. Contact support to request access to blocked destinations.

Sandbox Mode

Simulates the full send-and-deliver flow without carrier delivery. No credits deducted.

How to Activate

MethodDescription
Use a sk_test_ keyAlways forces sandbox mode
Set "sandbox": trueWorks with any key type
Connection environment = testConfigured at portal2.quicksms.com/management/api-connections

Differences from Production

BehaviourProductionSandbox
Real SMS/RCS deliveryYesNo
Credits deductedYesNo
Anti-flood checksActiveBypassed
Out-of-hours checksActiveBypassed
Delivery webhooksReal carrier DLRSimulated after 3–5 seconds
RCS read receiptsFrom recipient deviceSimulated after 5–10 seconds

Simulated Delivery Outcomes

MSISDN Ends InSimulated StatusStatus Code
0000UNDELIVERED27 (Absent subscriber)
9999EXPIRED255
Anything elseDELIVERED0
Use these endings to test your webhook handler for different delivery outcomes.

Webhook Security

When a signing secret is configured, every webhook includes an X-QuickSMS-Signature header with an HMAC-SHA256 signature.

Verification Steps

  1. Extract the X-QuickSMS-Timestamp header value
  2. Get the raw request body (do not parse or re-serialize)
  3. Concatenate: {timestamp}.{body}
  4. Compute HMAC-SHA256 using your signing secret as the key
  5. Compare with the header signature using constant-time comparison
  6. Reject if timestamp is more than 5 minutes old (replay protection)

Verification Examples

const crypto = require('crypto');

function verifyWebhook(req, secret) {
    const timestamp = req.headers['x-quicksms-timestamp'];
    const signature = req.headers['x-quicksms-signature'];
    const body = req.rawBody;

    if (Math.abs(Date.now() / 1000 - parseInt(timestamp)) > 300) {
        throw new Error('Timestamp too old');
    }

    const payload = `${timestamp}.${body}`;
    const expected = 'sha256=' +
        crypto.createHmac('sha256', secret).update(payload).digest('hex');

    if (!crypto.timingSafeEqual(
        Buffer.from(expected), Buffer.from(signature)
    )) { throw new Error('Invalid signature'); }

    return JSON.parse(body);
}
import hmac, hashlib, time, json

def verify_webhook(request, secret):
    timestamp = request.headers.get('X-QuickSMS-Timestamp', '')
    signature = request.headers.get('X-QuickSMS-Signature', '')
    body = request.get_data(as_text=True)

    if abs(time.time() - int(timestamp)) > 300:
        raise ValueError('Timestamp too old')

    payload = f'{timestamp}.{body}'
    expected = 'sha256=' + hmac.new(
        secret.encode(), payload.encode(), hashlib.sha256
    ).hexdigest()

    if not hmac.compare_digest(expected, signature):
        raise ValueError('Invalid signature')

    return json.loads(body)
$secret    = 'your_webhook_signing_secret';
$timestamp = $_SERVER['HTTP_X_QUICKSMS_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_QUICKSMS_SIGNATURE'] ?? '';
$body      = file_get_contents('php://input');

if (abs(time() - (int) $timestamp) > 300) {
    http_response_code(401); die('Timestamp too old');
}

$payload  = "{$timestamp}.{$body}";
$expected = 'sha256=' . hash_hmac('sha256', $payload, $secret);

if (!hash_equals($expected, $signature)) {
    http_response_code(401); die('Invalid signature');
}

$data = json_decode($body, true);
http_response_code(200);

Security Best Practices

PracticeDetail
Environment-specific keysUse sk_test_ in dev/staging. sk_live_ in production only.
Store keys securelyEnvironment variables or secrets manager. Never source control.
Rotate compromised keysRotate immediately in portal2.quicksms.com.
IP allowlistingRestrict production API access to known server IPs.
Verify webhook signaturesAlways validate X-QuickSMS-Signature before processing.
Timestamp freshnessReject webhooks with timestamps older than 5 minutes.
HTTPS callback URLsAlways configure webhook endpoints over HTTPS.
Idempotency keysProtect against duplicate sends from network retries.

Error Handling

All errors return consistent JSON with a unique request_id for support troubleshooting.

{
    "error": {
        "type": "validation_error",
        "code": "INVALID_PHONE_NUMBER",
        "message": "The MSISDN is not valid international format.",
        "param": "MSISDN",
        "request_id": "req_a1b2c3d4"
    }
}

HTTP Status Codes

CodeMeaningRetryable?What to Do
202Accepted / held
400Bad requestNoFix request format or missing fields
401Auth failedNoCheck API key
403ForbiddenNoCheck account status or IP allowlist
404Not foundNoCheck URL path
409Idempotency conflictNoUse a new key for different payloads
422Validation failedNoCheck error code and fix
429Rate limitedYesWait Retry-After seconds
500Server errorYesRetry with backoff

Message Rejection Codes

CodeDescriptionWhat to Do
SENDER_NOT_REGISTEREDSender ID not approvedRegister at portal2.quicksms.com/management/sms-sender-id/register
TEST_NUMBER_NOT_APPROVEDTest: number not in allowlistAdd at portal2.quicksms.com/management/api-connections
COUNTRY_NOT_ALLOWEDDestination country blockedCheck country settings
INSUFFICIENT_CREDITSBalance too lowTop up account
CONTENT_BLOCKEDContent filter triggeredRevise content or contact support
OUT_OF_HOURSOutside business hours (reject mode)Retry during hours or switch to hold
DUPLICATE_MESSAGEAnti-flood: duplicate detectedWait or change content

Request-Level Error Codes

CodeHTTPWhat to Do
MISSING_FIELD400Add the missing field (check param)
BAD_REQUEST400Validate JSON format
INVALID_PHONE_NUMBER422Digits only, no +, 7–15 digits, non-zero start
CONTENT_TOO_LONG422Shorten to ≤1,530 chars
VALIDATION_ERROR422Check message field for detail
UNAUTHORIZED401Verify API key and header format
IP_NOT_ALLOWED403Add IP at portal2.quicksms.com/account/security
ACCOUNT_INACTIVE403Contact admin or QuickSMS support
RATE_LIMITED429Wait Retry-After seconds
AUTH_RATE_LIMITED429Wait lockout; verify key is correct
IDEMPOTENCY_CONFLICT409Use a unique key per distinct message
INTERNAL_ERROR500Retry with backoff; contact support if persistent

Health Endpoint

Check the API's operational status. No authentication required.

GET https://api.quicksms.com/v1/health
200 OK All systems operational
{ "status": "healthy" }
503 Service Unavailable
{ "status": "degraded" }

Use this endpoint for uptime monitoring. A 200 means all critical services are operational. A 503 indicates temporary degradation — retry with backoff.

Code Examples

Basic SMS

curl -X POST https://api.quicksms.com/v1/messages \
  -H "Authorization: Bearer sk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "MSISDN": "447700900000", "msg": "Hello from QuickSMS!", "sender": "MyApp" }'

RCS with SMS Fallback

curl -X POST https://api.quicksms.com/v1/messages \
  -H "Authorization: Bearer sk_live_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "MSISDN": "447700900000",
    "msg": "Your parcel is out for delivery!",
    "sender": "MyBrandAgent",
    "smart_routing": true,
    "sms_failover_sender": "MyBrand",
    "callback_url": "https://example.com/webhooks/dlr"
  }'
$ch = curl_init('https://api.quicksms.com/v1/messages');
curl_setopt_array($ch, [
    CURLOPT_POST           => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer sk_live_your_key_here',
        'Content-Type: application/json',
        'Idempotency-Key: order-12345-sms',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'MSISDN' => '447700900000',
        'msg'    => 'Hello from QuickSMS!',
        'sender' => 'MyApp',
    ]),
]);
$response = curl_exec($ch);
$status   = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$data = json_decode($response, true);

if ($status === 202) {
    $msg = $data['messages'][0];
    echo "Sent: {$msg['quicksms_id']} — Status: {$msg['status']}";
} else {
    echo "Error: " . ($data['error']['message'] ?? $data['messages'][0]['error']['message']);
}
import requests

response = requests.post(
    'https://api.quicksms.com/v1/messages',
    headers={
        'Authorization': 'Bearer sk_live_your_key_here',
        'Idempotency-Key': 'order-12345-sms',
    },
    json={
        'MSISDN': '447700900000',
        'msg': 'Hello from QuickSMS!',
        'sender': 'MyApp',
    }
)

if response.status_code == 202:
    msg = response.json()['messages'][0]
    print(f"Sent: {msg['quicksms_id']} — Status: {msg['status']}")
elif response.status_code == 422:
    err = response.json()['messages'][0]['error']
    print(f"Rejected: {err['code']} — {err['message']}")
else:
    print(f"Error: {response.json()['error']['message']}")

print(f"Rate limit remaining: {response.headers.get('X-RateLimit-Remaining')}")
const response = await fetch('https://api.quicksms.com/v1/messages', {
    method: 'POST',
    headers: {
        'Authorization': 'Bearer sk_live_your_key_here',
        'Content-Type': 'application/json',
        'Idempotency-Key': 'order-12345-sms',
    },
    body: JSON.stringify({
        MSISDN: '447700900000',
        msg: 'Hello from QuickSMS!',
        sender: 'MyApp',
    }),
});
const data = await response.json();

if (response.status === 202) {
    const msg = data.messages[0];
    console.log(`Sent: ${msg.quicksms_id} — Status: ${msg.status}`);
} else {
    console.log(`Error: ${data.error?.message || data.messages?.[0]?.error?.message}`);
}
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer sk_live_your_key_here");
client.DefaultRequestHeaders.Add("Idempotency-Key", "order-12345-sms");

var payload = new {
    MSISDN = "447700900000",
    msg = "Hello from QuickSMS!",
    sender = "MyApp"
};
var response = await client.PostAsJsonAsync(
    "https://api.quicksms.com/v1/messages", payload);
var json = await response.Content.ReadAsStringAsync();

Console.WriteLine(response.StatusCode == System.Net.HttpStatusCode.Accepted
    ? $"Sent: {json}"
    : $"Error ({(int)response.StatusCode}): {json}");

Receiving Incoming Messages V1

V1 API — Inbound messaging uses the V1 API base URL: https://api.quicksms.com/rcs/v2/api. A V2 version with enhanced features is coming soon.

When an incoming message is received by the QuickSMS system, it is checked against a list of registered numbers and RCS senders. If a match is found, a POST request is made to your configured endpoint.

Register your numbers at portal2.quicksms.com/management/numbers.

Incoming Message Fields

InformationPOST FieldExample
Unique ReferenceID42
Number/Sender message sent fromMSISDN447123456789
MessageMessageHello
Number message sent toNumber44789011829
Received Date and TimeDateRecieved2012-06-27 12:33:00

Respond within ~1 second with RECEIVED.

Example Incoming Message

POST https://www.website.co.uk/incoming.php
Content-Type: application/json

{
    "MSISDN": "NotifyTest",
    "Message": "Testing",
    "Number": "44789100000",
    "DateRecieved": "2024-01-28 11:54:32",
    "ID": "MxJFwONIywR7yZysg7iAtDXQ"
}

Coming Soon

Planned capabilities and enhancements.

COMING SOON

Batch/Bulk Sending

Send messages to multiple recipients in a single API request. Ideal for campaigns and high-volume transactional messaging.

COMING SOON

Message Scheduling

Schedule messages for future delivery. Perfect for appointment reminders and time-zone-aware campaigns.

COMING SOON

Receive Message V2

Enhanced inbound messaging with HMAC webhook signing, structured JSON payloads, and metadata support. Upgrading from the current V1 inbound API.

COMING SOON

Manage Contacts API

Create, update, and manage contacts and contact lists programmatically via the API.

COMING SOON

Manage Account API

Manage account settings, users, and billing programmatically via the API.

Changelog

March 2026
V2 Send API V2
  • Bearer token & Basic auth
  • Idempotency keys (24-hour cache)
  • Smart routing — RCS with automatic SMS fallback
  • Sandbox mode with simulated delivery
  • Webhook signing (HMAC-SHA256)
  • Structured JSON error responses with request_id
  • Rate limit headers (X-RateLimit-*)
  • Anti-flood protection & out-of-hours controls
  • Country restrictions with MSISDN prefix matching
January 2025
V1 Inbound Messaging V1
  • Receive incoming SMS & RCS messages via webhook
  • Registered number and RCS sender matching
  • Webhook delivery to configured endpoint
2024
V1 Send API (Legacy) V1
  • HTTP Basic auth (username/password)
  • RCS/SMS sending with 10-second RCS timeout fallback
  • Delivery receipts with status and substatus codes
  • RCS seen receipts
  • Custom reference ID support (cid)
Click to view full V1 API documentation

V1 Send Endpoint

POST https://api.quicksms.com/rcs/v2/api

Authentication: HTTP Basic Authorization header (username:password).

Required Fields

InformationPOST FieldExample
Request TypereqTypeBULK
Number to send toMSISDN447123456789
MessagemsgHello World
SendersenderTestSender

Optional Fields

InformationPOST FieldExample
Multipart allowed (>160 chars)multitrue
Custom ID (returned with receipt)cid123456
Receipt Delivery URLDelurlwww.receipts.co.uk

Example Request

POST https://api.quicksms.com/rcs/v2/api
Content-Type: application/json
Authorization: Basic <base64 encoded username:password>

{
  "reqType": "BULK",
  "MSISDN": "447891658396",
  "msg": "test message",
  "sender": "TestSender"
}

Successful Response

HTTP 200 OK
{ "reference": "42" }

Error Response

HTTP 400 Bad Request
{ "Error": 206, "Description": "Invalid username or password" }

V1 Error Codes

CodeExplanation
200Request was not received through HTTPS
201Request was not made through HTTP POST
202Username/Password not set or incorrect format
203Request type not set
204Invalid request type
205Missing required field
206Username or password incorrect
207Invalid MSISDN
208Not enough credits
209Message too long
210Sender too long
220API temporarily disabled (too many failed logins)
221API permanently disabled (too many failed logins)

V1 Delivery Receipts

POST to your configured endpoint when a message is delivered.

FieldExample
reference564634E434D0586B...
cidcustomid
MSISDN447891658396
deliverytime2024-01-01 16:36:48
status3
substatus5

Status: 3=Delivered, 2=Undeliverable, 4=Expired, 5=Rejected. Respond with RECEIVED.

V1 RCS Seen Receipts

POST when an RCS message is read. Only RCS messages.

FieldExample
reference564634E434D0586B...
CID1234-232-134
MSISDN447891658396
seentime2024-01-01 16:36:48

Respond with RECEIVED.

QuickSMS API Documentation · Version 2.0 · March 2026