API Reference

API Documentation

Everything you need to integrate Vertex into your stack. Send messages, verify OTPs, configure webhooks, and manage your account — all through a single RESTful API.

Quick Start#

Vertex provides a RESTful JSON API. All requests must be made over HTTPS. Authenticate using your API key via the Authorization header. The base URL for all API requests is:

https://api.vertex.pk/v1

Below is a complete example of sending an SMS message using the Vertex API. Replace the placeholder API key with your own live or test key.

send-sms
curl -X POST https://api.vertex.pk/v1/messages \
  -H "Authorization: Bearer vx_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+923001234567",
    "from": "VERTEX",
    "content": "Your OTP is 492013",
    "channel": "sms"
  }'

Vertex responds with a JSON payload containing the message ID and current status. All message IDs are prefixed with msg_ and are globally unique.

Tip: Use the Vertex Sandbox environment with your test API key to experiment without sending real messages. Sandbox responses include realistic DLR simulations.

Setup & Installation#

Install the Vertex SDK for your preferred language using the package manager of your choice:

Node.js
npm install @vertex/node-sdk
Python
pip install vertex-client
PHP
composer require vertex/vertex-php
Laravel
composer require vertex/laravel

Sandbox Environment#

Every Vertex account comes with a fully-featured sandbox environment. Sandbox API keys begin with vx_test_ and behave identically to production keys except that no real messages are sent. Delivery receipts are simulated after a configurable delay.

sandbox-config.js
import Vertex from "@vertex/node-sdk";

// Use your sandbox key — messages will not be delivered
const vertex = new Vertex("vx_test_your_sandbox_key_here");

// Optional: simulate DLR after 2 seconds
vertex.configure({ sandbox: { dlrDelayMs: 2000 } });

// All other API methods work identically to production

Authentication#

Vertex uses API keys to authenticate requests. You can manage your API keys from the Vertex Dashboard. Each key is prefixed to indicate its environment:

Live
vx_live_...
Sends real messages. Use in production.
Test
vx_test_...
Sandbox environment. No real sends.
Restricted
vx_restricted_...
Read-only or scoped to specific endpoints.

Include the API key in all requests as a bearer token in theAuthorization header:

Authorization: Bearer vx_live_abc123def456

Security Best Practices#

Store API keys securely. Never expose them in client-side code, version control, or logs. Use environment variables or a secrets manager in production. Rotate keys regularly and use restricted keys with minimal required permissions using Vertex's RBAC system.

All API requests must be made over TLS 1.2 or higher. Requests made over plain HTTP will be rejected. Vertex supports IP allow-listing at the account level — configure trusted IPs in the dashboard.

REST API#

The Vertex API is organised around REST. All requests must be made to the production base URL. We return JSON-encoded responses and use standard HTTP response codes to indicate success or failure.

Endpoints#

Below is a complete list of available REST endpoints. All paths are relative tohttps://api.vertex.pk.

MethodPathDescription
GET/v1/messagesList all messages
POST/v1/messagesSend a new message
GET/v1/messages/:idRetrieve a message
DELETE/v1/messages/:idCancel a queued message
POST/v1/otp/generateGenerate an OTP
POST/v1/otp/verifyVerify an OTP code
GET/v1/accountsGet account details
GET/v1/balanceCheck wallet balance
GET/v1/sendersList sender IDs
POST/v1/sendersRegister a sender ID
GET/v1/webhooksList webhook endpoints
POST/v1/webhooksCreate a webhook endpoint
PUT/v1/webhooks/:idUpdate a webhook endpoint
DELETE/v1/webhooks/:idDelete a webhook endpoint

Pagination#

List endpoints return paginated results using cursor-based pagination. The response includes a cursor field — pass its value as the starting_after parameter to fetch the next page.

pagination.json
// Response
{
  "data": [ ... ],
  "cursor": "msg_01JABCDEFGHIJKLMNOPQRST",
  "has_more": true
}

// Next request
GET /v1/messages?starting_after=msg_01JABCDEFGHIJKLMNOPQRST&limit=50

Idempotency#

Vertex supports idempotent requests to safely retry API calls without duplicate side-effects. Send an Idempotency-Keyheader with a unique UUID for each request. Vertex stores the response for that key for 24 hours and returns it for any subsequent requests with the same key.

Idempotency keys are strongly recommended for send and OTP endpoints to prevent accidental duplicate charges during network retries.

SMS API#

The SMS API lets you send branded, transactional, and promotional messages across all major Pakistani operators. Messages are routed through Vertex's carrier-grade SMPP infrastructure with automatic failover.

Send SMS#

Send a text message to a single recipient. The tofield must be in E.164 format. For branded SMS, frommust be an approved sender ID.

POST /v1/messages
to * — Recipient phone number (E.164)
from * — Sender ID or shortcode
content * — Message body (max 1600 chars)
channelsms (default), whatsapp
template — Optional template name for template-based sends
variables — Key-value pairs for template variables
send-sms
curl -X POST https://api.vertex.pk/v1/messages \
  -H "Authorization: Bearer vx_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+923001234567",
    "from": "VERTEX",
    "content": "Your OTP is 492013",
    "channel": "sms"
  }'

A successful response returns the message ID and current status:

response.json
{
  "id": "msg_01JABCDEFGHIJKLMNOPQRST",
  "status": "queued",
  "to": "+923001234567",
  "from": "VERTEX",
  "channel": "sms",
  "content": "Your OTP is 492013",
  "parts": 1,
  "credits": 0.85,
  "created_at": "2026-07-22T10:30:00.000Z"
}

DLR Callback#

Delivery receipts (DLR) are sent to your configured webhook endpoint. Each DLR includes the message ID, the delivery status, operator details, and timestamps. You can also poll the GET /v1/messages/:idendpoint for the latest status.

Sender IDs#

Branded sender IDs must be registered and approved before use. The approval process typically takes 1–2 business days. Submit sender ID registration requests via the Vertex Dashboardor the POST /v1/senders API endpoint.

OTP API#

Vertex's OTP API provides sub-second generation and verification with intelligent fallback across SMS, WhatsApp, and voice channels. OTPs are single-use, time-limited, and automatically expire.

Generate OTP#

Generate and send a one-time passcode to a recipient. The OTP code is auto-generated and sent via the specified channel. The response contains the otp_id which you must store to verify later.

POST /v1/otp/generate
to * — Recipient phone number (E.164)
channelsms, whatsapp, voice
length — Number of digits (default: 6, max: 8)
expiry_minutes — OTP validity period (default: 5, max: 30)
generate-otp
curl -X POST https://api.vertex.pk/v1/otp/generate \
  -H "Authorization: Bearer vx_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+923001234567",
    "channel": "sms",
    "length": 6,
    "expiry_minutes": 5
  }'

Response contains the OTP ID and delivery status:

otp-generate-response.json
{
  "otp_id": "otp_01JABCDEFGHIJKLMNOPQRST",
  "status": "sent",
  "to": "+923001234567",
  "channel": "sms",
  "expires_at": "2026-07-22T10:35:00.000Z"
}

Verify OTP#

Verify the code provided by the user against the generated OTP. Each OTP can be verified a limited number of times (default: 3 attempts) before it is locked. Once verified or expired, the OTP cannot be reused.

POST /v1/otp/verify
otp_id * — The OTP ID returned from generate
code * — The code provided by the end user
verify-otp
curl -X POST https://api.vertex.pk/v1/otp/verify \
  -H "Authorization: Bearer vx_live_abc123def456" \
  -H "Content-Type: application/json" \
  -d '{
    "otp_id": "otp_01JABCDEFGHIJKLMNOPQRST",
    "code": "492013"
  }'

The response indicates whether verification succeeded:

otp-verify-response.json
// Success
{
  "valid": true,
  "otp_id": "otp_01JABCDEFGHIJKLMNOPQRST",
  "verified_at": "2026-07-22T10:31:15.000Z"
}

// Failure
{
  "valid": false,
  "reason": "invalid_code",
  "attempts_remaining": 2
}

Webhook API#

Webhooks allow you to receive real-time notifications about message delivery status changes, OTP events, and account alerts. Configure webhook endpoints in the dashboard or via the API. Each endpoint can subscribe to specific event types.

Events#

Vertex sends webhook events as HTTP POST requests to your configured URL. Each event payload includes the event type, a unique ID, and the associated data object.

EventDescription
message.sentMessage accepted by operator and sent to recipient.
message.deliveredMessage confirmed as delivered to the handset (DLR received).
message.failedMessage delivery failed. Check failure_reason for details.
message.queuedMessage has been queued for delivery.
otp.generatedAn OTP has been generated and sent to the recipient.
otp.verifiedAn OTP has been successfully verified.
otp.expiredAn OTP has expired without verification.
balance.lowWallet balance is below the configured threshold.
Event payload format: All webhook events follow the { id, type, data, created_at } structure. The data field contains the relevant object (message, OTP, etc.).

Webhook Signing#

Every webhook request includes a Vertex-Signatureheader. This is an HMAC-SHA256 signature of the raw request body, signed with your webhook signing secret. Always verify this signature before processing the event to ensure the request is genuinely from Vertex.

verify-webhook.js
import crypto from "crypto";

function verifyWebhook(body, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(body)
    .digest("hex");

  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

// Express / Fastify middleware example
app.post("/webhooks/vertex", (req, res) => {
  const sig = req.headers["vertex-signature"];
  const secret = process.env.VERTEX_WEBHOOK_SECRET;

  if (!verifyWebhook(JSON.stringify(req.body), sig, secret)) {
    return res.status(401).send("Invalid signature");
  }

  // Process the event
  res.status(200).send("OK");
});

Retries#

If your webhook endpoint does not return a 2xx status within 5 seconds, Vertex will retry the delivery with exponential backoff. The retry schedule is: 10s, 30s, 2m, 10m, 30m, 2h, 6h, 24h. After 24 hours of continuous failure, the event is dropped and logged. You can replay failed events from the dashboard.

Idempotent delivery: Webhook events include an id field that is unique per event. Use it to deduplicate deliveries in case of retries.

Error Codes#

The Vertex API uses standard HTTP status codes to indicate success or failure. Error responses include a machine-readable error_codeand a human-readable message.

Error CodeHTTPDescription
invalid_credentials401API key is missing, invalid, or expired.
insufficient_balance402Wallet balance is too low to send the message.
invalid_recipient400The recipient phone number is invalid or not E.164 formatted.
invalid_sender400The sender ID is invalid, unregistered, or not approved.
rate_limit_exceeded429Request rate exceeds the allowed limit for your plan.
duplicate_request409A request with the same idempotency key already exists.
channel_not_enabled403The specified channel is not enabled for your account.
invalid_template400The template name does not exist or params do not match.
otp_expired400The OTP has expired. Generate a new one.
otp_already_verified400This OTP has already been verified.
too_many_attempts429Too many OTP verification attempts. Try again later.
internal_error500An unexpected error occurred. Contact support if persistent.
Error response format: All errors return { error_code, message, request_id }. Include the request_id when contacting support.

Rate Limits#

Rate limits protect the API from abuse and ensure fair usage across all customers. Limits are applied per API key and are reset every minute.

Standard
Starter and Growth plans.
60 req/min
High Throughput
Custom Enterprise plans with throughput add-on.
600 req/min
Burst
SMPP customers with dedicated infrastructure.
1,200 req/min

When a rate limit is exceeded, the API returns a 429status code with the rate_limit_exceeded error code. The response includes Retry-After header indicating the number of seconds to wait before retrying.

rate-limit-headers.json
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1721655000
Retry-After: 12

{
  "error_code": "rate_limit_exceeded",
  "message": "Rate limit exceeded. Try again in 12 seconds.",
  "request_id": "req_01JABCDEFGHIJKLMNOPQRST"
}

SDKs & Libraries#

Vertex provides official client libraries for the most popular programming languages. All SDKs are open-source, type-safe, and published on their respective package registries.

Node.js@vertex/node-sdk
npm install @vertex/node-sdk
Pythonvertex-client
pip install vertex-client
PHPvertex/vertex-php
composer require vertex/vertex-php
Laravelvertex/laravel
composer require vertex/laravel
Gogithub.com/vertexpk/go-vertex
go get github.com/vertexpk/go-vertex
Javacom.vertex:vertex-java
gradle: com.vertex:vertex-java:1.0.0
.NETVertex.Sdk
dotnet add package Vertex.Sdk
Rubyvertex-ruby
gem install vertex-ruby