VoxiSMS API (2.0.0)

Download OpenAPI specification:

License: MIT

Public API for sending SMS messages and subscribing to inbound-message webhooks on the VoxiSMS platform. Outbound SMS is enqueued and delivered by the VoxiSMS Android app via the device's native SMS capability.

Authentication

Every request uses HMAC-SHA256 request signing. Include these headers:

  • customer-id: your VoxiSMS customer ID
  • timestamp: current Unix timestamp in seconds
  • signature: lowercase hex HMAC-SHA256 signature

Build the signature from this exact canonical string:

METHOD + "\n" + SIGN_PATH + "\n" + TIMESTAMP + "\n" + CUSTOMER_ID + "\n" + BODY

Compute HMAC-SHA256 over the UTF-8 bytes of this canonical string using your VoxiSMS secret key as the HMAC key, then encode the digest as lowercase hexadecimal.

For POST https://api.voxisms.com/v2/enqueue-message, the signed path is /enqueue-message, not /v2/enqueue-message. The timestamp must be within 5 minutes of server time, and BODY must be the exact JSON bytes sent in the request body, with no extra trailing newline.

Inbound-message webhooks are signed the same way in reverse: each delivery carries an X-VoxiSMS-Signature header you verify with the subscription's signingSecret.

sms

Outbound SMS

Enqueue an SMS for delivery.

HMAC-authenticated (customer-id + timestamp + signature). Use your VoxiSMS secret key only as the HMAC key, and send the resulting digest as a lowercase hexadecimal HMAC-SHA256 string in the signature header. Once accepted, the message is queued for delivery and the response returns the VoxiSMS message identifier.

Authorizations:
(customerIdsignaturetimestamp)
Request Body schema: application/json
required
id
string or null

Optional client-supplied message identifier, limited to 128 UTF-8 bytes. If omitted, null, or blank, VoxiSMS generates one.

message
required
string non-empty \S

SMS message text. Must contain a non-whitespace character and be at most 1,600 UTF-8 bytes.

recipient
required
string non-empty \S

Destination phone number in E.164 format. Must contain a non-whitespace character and be at most 32 UTF-8 bytes.

requestedTime
integer or null <int64>

Optional requested delivery time as a Unix timestamp in seconds.

source
string or null

Optional integration or origin identifier, limited to 128 UTF-8 bytes.

Responses

Request samples

Content type
application/json
{
  • "id": "order-123",
  • "message": "Hello from VoxiSMS",
  • "recipient": "+15551234567",
  • "requestedTime": 1700000000,
  • "source": "api"
}

Response samples

Content type
application/json
{
  • "messageId": "sample-message-id-12345"
}

webhooks

Webhook subscriptions and inbound-message delivery

Inbound SMS delivered to your subscription's targetUrl. Webhook

Sent by webhook-dispatcher to the targetUrl of every active subscription whose eventTypes include inbound_message.received, once per inbound SMS. The body is the flat InboundMessageEvent (same shape and same deterministic eventId as GET /inbound-events, so poll and push dedupe consistently). Verify authenticity by recomputing X-VoxiSMS-Signature. Respond 2xx to acknowledge; deliveries are at-least-once, so dedupe on X-VoxiSMS-Event-Id.

Authorizations:
webhookSignature
header Parameters
X-VoxiSMS-Timestamp
required
string
Example: 1721635200

Unix time in seconds at signing; part of the signed string. Reject deliveries whose timestamp is outside your tolerance window to blunt replay.

X-VoxiSMS-Event
required
string
Example: inbound_message.received

Event type wire string; currently always inbound_message.received.

X-VoxiSMS-Event-Id
required
string
Example: evt_a1b2c3d4

The evt_-prefixed deterministic event id (mirrors the body eventId). Dedupe on this — a delivery can be repeated.

X-VoxiSMS-Delivery-Id
required
string
Example: del_9f8e7d6c

The del_-prefixed deterministic id for this (eventId, subscriptionId) delivery; stable across retries of the same delivery.

Request Body schema: application/json
required
content
required
string
customerId
required
string
event
required
string
eventId
required
string
fromNumber
required
string
messageId
required
string
messageType
required
string
occurredAt
required
string
toNumber
required
string
version
required
string

Responses

Request samples

Content type
application/json
{
  • "content": "Hello from a customer",
  • "customerId": "cust_123",
  • "event": "inbound_message.received",
  • "eventId": "evt_a1b2c3d4",
  • "fromNumber": "+15551234567",
  • "messageId": "01HZY...",
  • "messageType": "sms",
  • "occurredAt": "2026-07-22T09:20:00.000Z",
  • "toNumber": "+15557654321",
  • "version": "1"
}

List the customer's most recent inbound SMS as webhook events (`performList`).

HMAC-authenticated. Returns a BARE JSON array of the SAME event shape the webhook POSTs, so Zapier's editor "test trigger" step has real sample data. An empty result is [], not an error.

Authorizations:
(customerIdsignaturetimestamp)

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Register (idempotent upsert) a webhook subscription.

HMAC-authenticated (customer-id + timestamp + signature). A re-fired subscribe for the same (customerId, targetUrl, eventTypes) tuple is idempotent — the returned subscriptionId and signingSecret are stable across repeats.

Authorizations:
(customerIdsignaturetimestamp)
Request Body schema: application/json
required
eventTypes
Array of strings (EventType)
Default: ["inbound_message.received"]
Items Value: "inbound_message.received"

Event types to subscribe to. The only supported value is inbound_message.received, which is also the default when omitted.

Provider (string)
Default: "generic"
targetUrl
required
string

HTTPS URL that receives signed webhook deliveries, limited to 2,048 UTF-8 bytes. Must target a public host; http, localhost, and private/link-local/unspecified addresses are rejected.

Responses

Request samples

Content type
application/json
{}

Response samples

Content type
application/json
{
  • "createdAt": "2019-08-24T14:15:22Z",
  • "eventTypes": [
    ],
  • "signingSecret": "string",
  • "status": "active",
  • "subscriptionId": "string",
  • "targetUrl": "string"
}

Unsubscribe a webhook subscription.

HMAC-authenticated; the signature covers the full request path (including the subscription id), since there is no single canonical DELETE route. Idempotent — deleting an unknown or already-removed subscription still returns 200.

Authorizations:
(customerIdsignaturetimestamp)
path Parameters
subscriptionId
required
string

Subscription id returned by the subscribe call

Responses

Response samples

Content type
application/json
Example
{
  • "error": "string"
}