Integrate your Service with SMS API

Overview

The SMS API Integration enables third-party SMS aggregators to connect natively with Optimove’s SMS module. This integration flips the traditional model—instead of Optimove building dedicated connectors for every provider, your service can now integrate directly using our standardized API.

This approach is particularly valuable for connecting with local operators or niche providers without requiring specific R&D development cycles. By integrating your service with the SMS API, you act as the execution channel for SMS campaigns orchestrated by Optimove, utilizing a bi-directional flow to handle campaign transmission, delivery reporting, and incoming customer messages.

This document details the four critical flows required for integration:

  1. Configuration: Setting up credentials in the Optimove UI.
  2. Handshake: Establishing the authenticated connection (replaces traditional webhook registration).
  3. Campaign Transmission: Receiving campaign batches from Optimove.
  4. Delivery & Incoming Reporting: Sending status updates and replies back to Optimove.

Integration Architecture

High-level sequence diagram of the SMS API integration flows.

Authentication and Security

All endpoints in this integration require strict authentication to ensure data integrity.

Required Headers

Every request (both inbound to Optimove and outbound to the Aggregator) must include the following headers. Note the difference in the API Key header name depending on the direction.

FlowDirectionAPI Key HeaderSignature Header
HandshakeTo Optimoveapp-api-keyx-hub-signature
Delivery ReportTo Optimoveapp-api-keyx-hub-signature
Incoming MessageTo Optimoveapp-api-keyx-hub-signature
Campaign TransmissionTo AggregatorX-API-Keyx-hub-signature

HMAC Signature Generation

The x-hub-signature header contains an HMAC-SHA256 signature of the request body using the shared Secret Key provided during configuration. The signature format follows the GitHub webhook signature format: sha256={signature}.

Example (Node.js):

const crypto = require("crypto");

const payload = JSON.stringify(requestBody);
const secret = "your-shared-secret";

const signature = crypto
  .createHmac("sha256", secret)
  .update(payload)
  .digest("hex");

const hubSignature = `sha256=${signature}`;

Example (Python):

import hashlib
import hmac
import json

payload = json.dumps(request_body, separators=(',', ':'))
secret = b'your-shared-secret'
signature = hmac.new(secret, payload.encode(), hashlib.sha256).hexdigest()
hub_signature = f'sha256={signature}'

Obtaining Credentials

Before initiating the API flows, you must obtain the credentials from the Optimove tenant.

  1. In the Optimove interface, navigate to Settings > SMS Configuration.
  2. Select the API Vendor option (currently labeled OptiText API Vendor in the UI).
  3. Once the feature is enabled, you will see the following read-only credentials:
    • Base URL: The endpoint URL for SMS API calls.
    • API Token: The unique token identifying the tenant.
    • Secret Key: Used for HMAC signature generation.

Important: The Secret Key is only visible in this screen before the Handshake is completed. Once you successfully perform the Handshake (Flow 1), the Secret Key will be hidden for security.

Flow 1: Handshake Endpoint

Direction: Aggregator -> Optimove

The handshake is a one-time setup call that connects your aggregator service to the tenant's SMS instance. It registers your callback URL for receiving campaigns and sets the default Sender ID.

  • URL: {baseurl}/api/v1/aggregator/handshake
  • Method: POST

Request Body

FieldTypeRequiredDescription
aggregatorApiKeyStringYesYour API key that Optimove will use to authenticate when sending campaigns.
campaignSendUrlStringYesThe webhook URL on your system where Optimove will POST campaign requests.
senderIdStringYesDefault sender identifier used for campaigns.

Example Request:

curl -X POST "{baseurl}/api/v1/aggregator/handshake"   -H "Content-Type: application/json"   -H "app-api-key: {your-app-api-key}"   -H "x-hub-signature: sha256={signature}"   -d '{
    "aggregatorApiKey": "your-aggregator-api-key",
    "campaignSendUrl": "https://your-aggregator.com/api/v1/campaigns/send",
    "senderId": "YourCompany"
  }'

Responses

  • 200 OK: Handshake completed successfully.
  • 409 Conflict: Handshake data unchanged (duplicate request).
  • 500 Internal Server Error: Handshake failed.

Flow 2: Campaign Transmission Webhook

Direction: Optimove -> Aggregator

Once the handshake is complete, Optimove will use the campaignSendUrl provided in Flow 1 to transmit SMS campaign batches to your service.

  • URL: Defined by you in Flow 1.
  • Method: POST
  • Headers: Includes X-API-Key (your key) and x-hub-signature.

Request Body Structure

FieldTypeDescription
batchIdStringUnique identifier for the message batch.
recipientsArrayArray of recipient objects containing message data.
metadataObjectCampaign context (Required for Flow 3).

Recipient Object:

FieldTypeDescription
messageStringSMS text to send.
mobileNumberStringRecipient’s mobile number (E.164).
customerIdStringUnique customer identifier.

Metadata Object Details:

FieldTypeDescription
appIdIntegerApplication identifier.
campaignIdStringCampaign identifier.
campaignTypeInteger1 (Scheduled) or 2 (Triggered).
channelIdIntegerCommunication channel identifier.
scheduledTimeLongUnix timestamp in milliseconds.
tenantIdIntegerTenant identifier.

Example Request:

{
  "batchId": "batch-123",
  "metadata": {
    "appId": 123,
    "campaignId": "232522",
    "campaignType": 1,
    "channelId": 493,
    "scheduledTime": 1704106200000,
    "tenantId": 1
  },
  "recipients": [
    {
      "message": "Hello! Your order is ready.",
      "mobileNumber": "+1234567890",
      "customerId": "customer-001"
    }
  ]
}

Response & Retry Logic

Status CodeOptimove Behavior
2xxSuccess — no retry.
429Will retry with exponential backoff.
500/503Will retry with exponential backoff.
400-422No retry — campaign aborted for that request.

Flow 3: Delivery Report Endpoint

Direction: Aggregator -> Optimove
URL: {baseurl}/api/v1/aggregator/delivery-report
Method: POST

Request Body

SectionFieldRequiredDescription
typestatusYesDelivered, Failed, or Unknown.
subStatusYesSee mapping table.
recipientmobileNumberYesRecipient's number.
customerIdYesUnique identifier.
metadataall fieldsYesMust match Flow 2 metadata exactly.

Status Mapping

ResultStatusSubStatus
SuccessDeliveredDeliveredToHandset
Invalid NumberFailedInvalidNumber
General FailureFailedFailed
UnknownUnknownUnknown

Example Request:

{
  "type": {
    "status": "Delivered",
    "subStatus": "DeliveredToHandset"
  },
  "recipient": {
    "mobileNumber": "+1234567890",
    "customerId": "customer-123"
  },
  "metadata": {
    "appId": 123,
    "campaignId": "campaign-789",
    "tenantId": 456,
    "channelId": 493,
    "campaignType": 1,
    "scheduledTime": 1735737600000
  }
}

Flow 4: Incoming Messages Webhook

Direction: Aggregator -> Optimove
URL: {baseurl}/api/v1/aggregator/incoming-message
Method: POST

Request Body

FieldTypeDescription
toStringBrand or sender ID.
fromStringCustomer’s phone number.
messageStringInbound message text.
sentAtStringISO 8601 timestamp.

Example Request:

{
  "messages": [
    {
      "to": "YourBrand",
      "from": "1234567891",
      "message": "stop",
      "sentAt": "2025-10-01T12:34:56Z"
    }
  ]
}

Best Practices

Security & Authentication

  • Validate Signatures: Always verify the x-hub-signature on every incoming request (Handshake, Transmission) using your shared Secret Key before processing the payload.
  • Constant-Time Comparison: When verifying HMAC signatures, use a constant-time comparison function (e.g., hmac.compare_digest in Python) to prevent timing attacks.
  • HTTPS Only: Ensure all endpoints (both yours and Optimove's) are accessed over HTTPS to protect sensitive customer data and credentials in transit.

Timing & Retries

  • Real-Time Reporting: Send delivery reports immediately as messages are processed. Do not batch them for long periods or delay reports while waiting for a "final" status if an intermediate one is available.
  • Exponential Backoff: Implement exponential backoff for retrying failed requests (e.g., network timeouts, 500-level errors) to avoid overwhelming the API.
  • Do Not Retry Client Errors: Never retry 400-level errors (e.g., 400 Bad Request, 401 Unauthorized), as these indicate a permanent issue with the request format or credentials.

Data Integrity

  • Preserve Metadata: You must return the exact metadata object received in the Campaign Transmission payload when sending Delivery Reports. This allows Optimove to map the status back to the correct Tenant, Campaign, and Customer.
  • Exact Number Formatting: Ensure mobile numbers in reports match the format received in the transmission payload exactly.

Monitoring

  • Alert on Failures: Set up internal alerts for high rates of signature verification failures or 401 Unauthorized responses, which could indicate a configuration drift or security issue.
  • Track Success Rates: Monitor the success rate of your delivery report submissions to ensure campaign analytics in Optimove remain accurate.