Webhook SMS API
Receive text messages at your own web address and send replies through a simple API.
The Webhook SMS integration allows you to receive inbound SMS/MMS messages via HTTP webhooks and send outbound SMS through a simple REST API. This supports two-way messaging with AI platforms, automation tools, and custom applications.
How it works:
- A customer sends an SMS/MMS to your provisioned DID
- Our system forwards the message as a JSON POST to your configured webhook URL
- Your service can reply immediately in the HTTP response (synchronous reply)
- Your service can also send outbound SMS at any time via the outbound API endpoint (asynchronous)
Base URL
All API endpoints are served from:
https://api.cloudspirevoice.com/
Receiving Inbound SMS
When a customer sends an SMS or MMS to your DID, your webhook endpoint receives an HTTP POST with a JSON payload.
Request Details
| Property | Value |
|---|---|
| Method | POST |
| Content-Type | application/json |
| Authorization | Value of your configured Auth Header (if set), otherwise omitted |
| Timeout | 30 seconds |
Inbound Payload
{
"event": "sms.inbound",
"from": "+17705551234",
"to": "+14045559999",
"text": "Hello, I need help with my account",
"media": [
"https://api.cloudspirevoice.com/uploads/wh_67ae1b2f3c4d5.jpg"
],
"timestamp": "2026-02-13T14:30:00-05:00"
}
Payload Fields
| Field | Type | Always Present | Description |
|---|---|---|---|
event | string | Yes | Always "sms.inbound" |
from | string | Yes | The sender's phone number in E.164 format (+1XXXXXXXXXX) |
to | string | Yes | Your DID that received the message, in E.164 format |
text | string | Yes | The message body. May be an empty string for MMS-only messages. |
media | array | No | Array of publicly accessible URLs for MMS attachments. Only present when the message includes media. Files are hosted on our server and retained for 30 days. |
timestamp | string | Yes | ISO 8601 timestamp with timezone offset |
Expected Response
Your endpoint must return an HTTP status in the 2xx range to confirm receipt. Any non-2xx response is treated as a delivery failure.
Fire-and-Forget (No Reply)
Return HTTP 200 with an empty body or any body without a reply field. The message is delivered to your system and no reply is sent to the customer.
Synchronous Reply
To send an immediate SMS reply back to the customer, return a JSON response with a reply field:
{
"reply": "Thanks for reaching out! Your account number is 12345.",
"media": ["https://example.com/receipt.pdf"]
}
| Field | Type | Required | Description |
|---|---|---|---|
reply | string | Yes | The SMS text to send back to the customer. Must be non-empty. |
media | array | No | Array of publicly accessible media URLs to include as MMS attachments. |
If the reply field is missing or empty, no reply is sent.
Sending Outbound SMS (Asynchronous)
Use this endpoint when your service needs to send an SMS outside of the synchronous reply window, for example, sending a follow-up message minutes or hours later, or initiating a new conversation.
Endpoint
POST https://api.cloudspirevoice.com/webhook-to-sms.php
Headers
| Header | Value |
|---|---|
Content-Type | application/json |
Request Payload
{
"from": "14045559999",
"to": "17705551234",
"text": "Your appointment is confirmed for Friday at 3pm.",
"secret": "your-webhook-secret",
"media_url": "https://example.com/confirmation.jpg"
}
Request Fields
| Field | Type | Required | Description |
|---|---|---|---|
from | string | Yes | The DID to send from (your provisioned number). Must be a DID configured with WEBHOOK destination. Any of the formats below is accepted. |
to | string | Yes | The recipient phone number. A number written with a leading + is sent exactly as written. Without the +, a 10-digit number is read as a US or Canada number; include the country code for any other country. |
text | string | Conditional | The message body. Required unless media_url is provided. |
secret | string | Yes | The webhook secret configured for this DID. Must match exactly. |
media_url | string | No | A publicly accessible URL for an MMS attachment (image, PDF, etc.). When provided, the message is sent as MMS. If media_url is provided, text may be empty. |
Success Response
HTTP 200
{
"status": "success",
"message": "SMS Queued | FROM: 14045559999 | TO: 17705551234 | ID: bw-msg-abc123"
}
The ID value is the carrier message ID and can be used for delivery tracking.
Error Response
HTTP 400
{
"status": "error",
"message": "Authentication failed: invalid secret. Error: [WH-AUTH]"
}
Error Codes
| Code | Meaning | Resolution |
|---|---|---|
[WH-AUTH] | Secret is missing or does not match | Verify the secret value matches the Webhook Secret provided to you by your Cloudspire administrator |
[WH-1] | Missing required fields or invalid JSON | Ensure from, to, and either text or media_url are present in a valid JSON body |
[WH-2] | Phone number format invalid | Send a 10-digit US or Canada number, or a number with its country code (10 to 15 digits in all). Spaces, dashes, parentheses and a leading + are fine. |
[WH-3] | DID not configured for webhook | The from number must be provisioned for webhook SMS by your Cloudspire administrator |
[WH-23-2] | The number cannot send texts yet | The number is inactive or not set up for texting, or the account does not yet have the SMS Message Package and an approved business texting registration. Contact your Cloudspire administrator. |
[WH-23-CAP] | Trial texting limit reached | A trial account has used its included texts. Upgrade to a plan to keep sending. |
[WH-23-TF] | Toll-free number | Toll-free numbers need toll-free verification to send texts, which a business texting registration does not provide. Send from a local number. |
[WH-23-OPTOUT] | Recipient opted out | The recipient replied STOP to this number. Nothing is sent until they reply START. |
[WH-23-9] | Temporary failure (HTTP 503) | The message was not sent. Retry the request. |
[WH-BW-APP] | Texting is not available right now | The message was not sent. Contact your Cloudspire administrator. |
Complete Two-Way Example
This example demonstrates a typical two-way SMS flow using n8n as middleware between your DID and an AI service.
Step 1: Your Endpoint Receives Inbound SMS
When a customer texts your DID, your webhook endpoint receives:
{
"event": "sms.inbound",
"from": "+17705551234",
"to": "+14045559999",
"text": "What are your business hours?",
"timestamp": "2026-02-13T14:30:00-05:00"
}
Step 2: Send a Synchronous Reply
If your service can generate a reply within 30 seconds (e.g., a quick AI lookup), respond directly in the HTTP response body:
{
"reply": "Our business hours are Monday-Friday 9am-5pm EST. Can I help with anything else?"
}
The system automatically sends this as an SMS from your DID to the customer.
Step 3: Send an Async Follow-Up
If your service needs to send a message later (a follow-up, a scheduled reminder, or any message outside the 30-second window), POST to the outbound endpoint:
curl -X POST https://api.cloudspirevoice.com/webhook-to-sms.php \
-H "Content-Type: application/json" \
-d '{
"from": "14045559999",
"to": "17705551234",
"text": "Just following up. Did you need anything else?",
"secret": "your-webhook-secret"
}'
Phone Number Format Reference
| Context | Format | Example |
|---|---|---|
Inbound payload (from, to) | E.164 with + | +14045559999 |
Outbound request (from, to) | Digits, with or without +; punctuation is ignored | 14045559999, +14045559999, (404) 555-9999 |
A number written with a leading + is sent exactly as written. Without the +, a 10-digit number is read as a US or Canada number and sent with its 1 country code, and any other number must include its country code.
Billing and Limits
- Both inbound webhook deliveries and outbound SMS count against your DID's monthly message limit
- Synchronous replies sent from webhook responses also count toward the limit
- When the limit is reached, outbound sends return error
[WH-23-3]. Inbound messages are still delivered to your webhook, but automatic replies will fail. - Usage resets on the 1st of each month
Media / MMS Notes
- Inbound MMS attachments are downloaded from the carrier and re-hosted at
https://api.cloudspirevoice.com/uploads/ - Hosted media files are automatically cleaned up after 30 days
- For outbound MMS, the
media_urlmust be a publicly accessible HTTP or HTTPS URL - If an invalid
media_urlis provided on outbound, the message is sent as SMS only (the media is silently dropped)