Gateway Platform API (SMS & Voice)
Send SMS and place calls (incl. flash-call OTP) through your registered Gateway devices via a simple REST API, with optional webhook delivery instead of polling.
Gateway Platform API (SMS & Voice)
Send SMS and place calls (including flash-call OTP verification) programmatically through your own registered SMS/Voice Gateway devices — your phone(s) running the 6X Gateway app do the actual sending, and the API just queues the request. This is separate from the SMPP-bind and Business API systems documented elsewhere: it always requires at least one active gateway device on your account, and it's billed at the same retail rates as sending manually from the Gateway Devices page in your wholesale portal.
Authentication
Every request needs your account's API key, sent as either:
X-API-Key: YOUR_API_KEY
...or as a query parameter:
?api_key=YOUR_API_KEY
Get (or regenerate) your API key from Profile in your wholesale portal. Regenerating immediately invalidates the old key — update your integration before doing so.
Note: this is a different key from the api_key shown on an individual Gateway Device's card — the device key identifies one physical phone; this account-level key identifies you as the caller and is what these endpoints check.
Rate limit
All four endpoints below are limited to 60 requests/minute per IP. Exceeding it returns HTTP 429 — back off and retry after a few seconds.
POST /api/v1/wholesale/sms/send
Queues an SMS on your first active SMS Gateway device.
| Field | Type | Required | Description |
|---|---|---|---|
| from | string | Yes | Sender ID (subject to your account's sender-ID rules for the destination country) |
| to | string | Yes | Recipient phone, international format e.g. +447911123456 |
| message | string | Yes | SMS text |
Example request
curl -X POST https://app.6xcom.com/api/v1/wholesale/sms/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"6XBiz","to":"+447911123456","message":"Your order has shipped."}'
Response
{
"success": true,
"message_id": "abc123",
"parts": 1,
"amount": 0.035,
"balance": 4.965
}
POST /api/v1/voice/call/send
Queues a normal (billed per-minute) call on your first active Voice Gateway device.
| Field | Type | Required | Description |
|---|---|---|---|
| to | string | Yes | Destination phone, international format |
| type | string | No | normal (default) or flash |
| webhook_url | string | No | See Webhook delivery below |
Example request
curl -X POST https://app.6xcom.com/api/v1/voice/call/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"+447911123456"}'
Response
{
"success": true,
"callId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"status": "queued",
"type": "normal"
}
POST /api/v1/voice/otp/send
Same request/response shape as voice/call/send, but always places a flash call (a ~4-second ring never meant to be answered — the caller ID itself is the OTP) regardless of any type field submitted. Purpose-built for OTP/2FA integrations. Billed a flat per-attempt fee from the superadmin-configured Flash-Verification Rates table (not a per-minute rate) — destinations with no flash rate configured are rejected with a 402.
curl -X POST https://app.6xcom.com/api/v1/voice/otp/send \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"+447911123456","webhook_url":"https://yourapp.example.com/6x-webhook"}'
GET /api/v1/voice/otp/status/{callId}
Polls the current status of a call queued via either voice endpoint above. Use the callId returned at send time.
curl https://app.6xcom.com/api/v1/voice/otp/status/d290f1ee-6c54-4b01-90e6-d701748f0851 \
-H "X-API-Key: YOUR_API_KEY"
{
"success": true,
"callId": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"type": "flash",
"status": "ended",
"durationSeconds": 4,
"cost": 0.05,
"error": null
}
| status | Meaning |
|---|---|
| pending | Queued, waiting for your gateway device to pick it up |
| initiated | Device has placed the call, not yet finished |
| ended | Call finished normally — terminal, cost is final |
| failed | Call failed (device offline, no signal, etc.) — terminal, nothing charged |
Webhook delivery (alternative to polling)
Instead of polling otp/status, pass a webhook_url when sending a call (either voice endpoint). Once the call reaches a terminal state (ended or failed), 6X POSTs the same JSON shape shown above to your URL — a short timeout applies and delivery is retried once on failure, then given up (poll as a fallback if you need a stronger guarantee).
Every webhook request carries two headers so you can verify it actually came from 6X:
| Header | Description |
|---|---|
| X-6X-Timestamp | Unix timestamp the request was sent |
| X-6X-Signature | sha256=<hex> — HMAC-SHA256 of "{timestamp}.{raw JSON body}", keyed with your account API key |
Verifying the signature (PHP)
$timestamp = $_SERVER['HTTP_X_6X_TIMESTAMP'];
$signature = $_SERVER['HTTP_X_6X_SIGNATURE'];
$body = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $yourApiKey);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit;
}
Error codes (all endpoints)
| Status | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 402 | Insufficient wallet balance for this destination, or (OTP) no flash-verification rate configured |
| 404 | Unknown callId, or it belongs to a different account |
| 422 | No active gateway device of the right type on your account, or a validation error |
| 429 | Rate limit exceeded (60 requests/minute) |