Callback Configuration Instructions
This section introduces how to configure the EngageLab OTP callback address and related security verification mechanisms to ensure the reliability and security of callback data.
Callback Address Configuration and Verification
After configuring the callback address, EngageLab OTP will automatically send an HTTP POST request to this address to verify the availability of the interface. Your service must return an HTTP 200 status code within 3 seconds, otherwise the system will consider the address unavailable.
Note:
To ensure that callback data can be received normally, please add 119.8.170.74 and 114.119.180.30 to your server's firewall whitelist.
Request Example
Assuming your callback address is https://example.engagelabotp.callback.com, the system will send the following request:
curl -X POST https://example.engagelabotp.callback.com -d '{}'
Response Requirements
Your service only needs to return an HTTP 200 status code and does not need to return any content. For example:
HTTP/1.1 200 OK
Content-Length: 0
Note:
The callback address verification only judges the HTTP status code and does not require returning specific message content. Please ensure your service interface can correctly respond with 200 within 3 seconds.
Callback Security Mechanism
To ensure the security and trusted source of callback data, EngageLab OTP supports multiple security verification methods.
Username and Secret Verification (Optional)
- Optional configuration. If a username is set, a secret must also be set.
- After configuration, EngageLab adds an
X-CALLBACK-IDfield to the HTTP Header of each callback request, in the following format:
X-CALLBACK-ID: timestamp={timestamp};nonce={nonce};username={username};signature={signature}
- Where:
timestamp: The timestamp when the callback was sentnonce: Random numberusername: The username you configuredsignature: Signature information, calculated as follows
Signature Calculation Method (Python Example)
import hashlib, hmac
def verify(username, secret, timestamp, nonce, signature):
return signature == hmac.new(
key=secret.encode(),
msg=f'{timestamp}{nonce}{username}'.encode(),
digestmod=hashlib.sha256
).hexdigest()
- The server can use the above method to verify the legitimacy of the callback request.
Authorization Authentication (Optional)
- If your callback interface requires authentication (such as Basic Auth, Bearer Token, etc.), you can fill in the Authorization information during configuration.
- EngageLab will automatically carry this Authorization field when requesting, making it convenient for your service to verify the request identity.
Callback Event Description
Message Status
Message status is used to track the status changes of each message in its lifecycle. It is used to understand the progress of message sending, delivery, verification, and other links in real time, facilitating statistical analysis, exception handling, and user experience optimization.
| Event Identifier | Description |
|---|---|
| plan | Message planned to be sent, enters pending queue |
| target_valid | Target number is valid |
| target_invalid | Target number is invalid |
| sent | Message successfully sent |
| sent_failed | Message sending failed |
| delivered | Message delivered to user device |
| delivered_failed | Message sent, but failed to deliver to user device |
| verified | User successfully completed OTP verification |
| verified_failed | User verification failed |
| verified_timeout | User did not complete verification within the specified time, timed out |
Callback Data Structure
Outer Structure
{
"total": 1,
"rows": [
{
// ReportLifecycle object
}
]
}
| Field Name | Type | Description |
|---|---|---|
| total | int | Number of data items in this callback |
| rows | array | Lifecycle status data array |
ReportLifecycle Object
| Field Name | Type | Description |
|---|---|---|
| message_id | string | Unique message ID |
| to | string | Recipient number |
| server | string | Service type (e.g., otp) |
| channel | string | Channel type |
| itime | int64 | Callback timestamp (seconds) |
| custom_args | object | Custom parameters (returned if passed in) |
| status | object | Status details object |
status Object
| Field Name | Type | Description |
|---|---|---|
| message_status | string | Current message status (see table below) |
| status_data | object | Status data object |
| billing | object | Billing information object (returned when billed) |
| error_code | int | Error code, 0 means no error |
| error_detail | object | Error details (returned when an error occurs) |
status_data Object
| Field Name | Type | Description |
|---|---|---|
| msg_time | int64 | Message creation timestamp (sec) |
| message_id | string | Message ID |
| current_send_channel | string | Current sending channel name |
| template_key | string | Template configuration Key |
| business_id | string | Business ID |
billing Object (returned when billed)
| Field Name | Type | Description |
|---|---|---|
| cost | float64 | Cost amount |
| currency | string | Currency, fixed as "USD" |
Generally, only messages in the sent stage contain billing information.
error_detail Object (returned when an error occurs)
| Field Name | Type | Description |
|---|---|---|
| message | string | Error message description |
Example: Message successfully sent
{
"total": 1,
"rows": [
{
"message_id": "123456789",
"to": "+6598765432",
"server": "sms",
"channel": "sms",
"itime": 1701234567,
"custom_args": {
"order_id": "ORDER123",
"user_id": "USER456"
},
"status": {
"message_status": "sent",
"status_data": {
"msg_time": 1701234560,
"message_id": "123456789",
"current_send_channel": "CHANNEL_A",
"template_key": "verify_code",
"business_id": "1001"
},
"billing": {
"cost": 0.005,
"currency": "USD"
},
"error_code": 0
}
}
]
}
Example: Message sending failed
{
"total": 1,
"rows": [
{
"message_id": "123456790",
"to": "+6598765433",
"server": "sms",
"channel": "sms",
"itime": 1701234568,
"status": {
"message_status": "sent_fail",
"status_data": {
"msg_time": 1701234561,
"message_id": "123456790",
"current_send_channel": "CHANNEL_B",
"template_key": "verify_code",
"business_id": "1001"
},
"error_code": 4001,
"error_detail": {
"message": "Invalid phone number"
}
}
}
]
}
Message Notification
Message notifications refer to system-level business events or alerts. They are used to remind business parties to pay attention to important information such as service running status, balance, template audit, etc., facilitating timely processing and risk warning.
| Event Identifier | Description |
|---|---|
| insufficient_verification_rate | Verification rate below set threshold |
| insufficient_balance | Insufficient account balance |
| template_audit_result | Notification of template audit result |
Example
{
"total": 1,
"rows": [{
"server": "otp",
"itime": 1712458844,
"notification": {
"event": "insufficient_balance",
"notification_data": {
"business_id": "1744569418236633088",
"remain_balance": -0.005, // Current balance;
"balance_threshold": 2 // Alert threshold;
}
}
}]
}
Message Response
Message response mainly refers to callback response events when interacting with users or external systems.
| Event Identifier | Description |
|---|---|
| uplink_message | Upstream message content replied by user via SMS, etc. |
Example
{
"total": 1,
"rows": [
{
"server": "otp",
"itime": 1741083306,
"message_id": "0",
"business_id": "0",
"response": {
"event": "uplink_message",
"response_data": {
"message_sid": "SM1234567890",
"account_sid": "AC1234567890",
"from": "+1234567890",
"to": "+0987654321",
"body": "Hello, it's time to struggle!"
}
}
}
]
}
System Events
System events cover operational behaviors related to accounts, templates, API calls, etc. They facilitate monitoring, auditing, and automated processing of key operations such as account login, key changes, API calls, etc.
| Event Identifier | Description |
|---|---|
| account_login | Account login related operation notification |
| key_manage | Key change, management related operation notification |
| msg_history | Message history query related operation notification |
| template_manage | Template addition, modification, deletion operation notification |
| api_call | API interface call related operation notification |
Callback Data Structure
Outer Structure
{
"total": 1,
"rows": [
{
// System event object
}
]
}
| Field | Type | Description |
|---|---|---|
| total | int64 | Total number of events in this callback |
| rows | array | System event object array |
System Event Object
| Field | Type | Description |
|---|---|---|
| server | string | Fixed as "otp" |
| itime | int64 | Event occurrence timestamp (sec) |
| system_event | object | System event content |
system_event Object
| Field | Type | Description |
|---|---|---|
| event | string | Event type |
| data | object | Event data |
data Object
| Field | Type | Description |
|---|---|---|
| business_id | string | Business ID |
| org_id | string | Organization ID |
| operator | object | Operator information |
operator Object
| Field | Type | Description |
|---|---|---|
| string | Operator email (if any) | |
| api_key | string | API Key (if any) |
| ip_address | string | Operation IP |
Request Structure
{
"total": 1,
"rows": [
{
"server": "otp",
"itime": 1694012345,
"system_event": {
"event": "account_login",
"data": {
"business_id": "123",
"org_id": "org-abc",
"operator": {
"email": "foo@example.com",
"api_key": "api-xxxx",
"ip_address": "1.2.3.4"
},
"account_login": {
"action": "login_success"
}
}
}
}
]
}
Account Login Event
| Field | Type | Description |
|---|---|---|
| action | string | login_success / login_failed / logout |
| fail_reason | string | Login failure reason, returned only when login_failed |
Example
{
"event": "account_login",
"data": {
"business_id": "123",
"org_id": "org-abc",
"operator": {
"email": "foo@example.com",
"ip_address": "1.2.3.4"
},
"account_login": {
"action": "login_success"
}
}
}
Template Management Event
| Field | Type | Description |
|---|---|---|
| action | string | create template / update template / delete template |
| template_id | string | Template ID |
| template_name | string | Template name |
Example
{
"event": "template_manage",
"data": {
"business_id": "123",
"org_id": "org-abc",
"operator": {
"email": "foo@example.com",
"ip_address": "1.2.3.4"
},
"template_manage": {
"action": "update template",
"template_id": "tmpl-456",
"template_name": "Verification Code"
}
}
}
Key Management Event
| Field | Type | Description |
|---|---|---|
| action | string | Enum values:create api_key: Create API Keyupdate api_key: Update API Keydelete api_key: Delete API Keyview api_secret: View API Secret |
| api_key | string | API Key |
| description | string | Description (optional) |
Example
{
"event": "key_manage",
"data": {
"business_id": "123",
"org_id": "org-abc",
"operator": {
"email": "foo@example.com",
"ip_address": "1.2.3.4"
},
"key_manage": {
"action": "create",
"api_key": "apikey-789",
"description": "New Key"
}
}
}
API Call Event
| Field | Type | Description |
|---|---|---|
| api_path | string | API path |
| method | string | HTTP method |
Example
{
"event": "api_call",
"data": {
"business_id": "123",
"org_id": "org-abc",
"operator": {
"api_key": "apikey-789",
"ip_address": "1.2.3.4"
},
"api_call": {
"api_path": "/api/v1/messages/send",
"method": "POST"
}
}
}










