Introduction
The Spektif API follows RESTful architecture standards, offering clear and consistent resource-based endpoints. All requests and responses are transmitted in JSON format, leveraging standard HTTP verbs, status codes, and authentication protocols to enable secure, efficient, and scalable integrations.
API Base URL
Please note that Spektif does not provide a sandbox or test environment. All API requests are processed in the live environment, so ensure that all request data and parameters are accurate before making any calls.
https://www.devcrm.spektif.id/external-api
Authentication
All requests to the Spektif API require authentication. Each API request must include a valid client-id and client-secret to the request header, which can be obtained from your Spektif Dashboard under Developer Tools.
In addition to credentials, Spektif enforces IP-based security. You must register and enable your server’s public IP address in the IP Whitelist section of the dashboard. Requests originating from non-whitelisted IP addresses will be automatically rejected.
Both valid API credentials and an approved IP address are mandatory. Without completing these two steps, authentication will fail and API access will not be granted.
Response Format
All responses from the Spektif API are returned in JSON format. Each response follows a consistent structure and includes a status indicator, message, and relevant data payload when applicable. Standard HTTP status codes are used to represent the outcome of each request.
Sample Success Response
{
"status": "success",
"remark": "contact_list",
"message":[
"Contact list fetched successfully"
],
"data": {
...you get all data here
}
}
Error Sample Response
{
"remark": "Unauthorized",
"status": "error",
"message": [
"The client secret is required"
]
}
{
"remark": "Unauthorized",
"status": "error",
"message": [
"Access to this API endpoint is restricted to IP addresses that have been explicitly whitelisted.",
"In order to access this API endpoint, please add your IP address (::1) to the white list from the user dashboard."
]
}
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/contact/list',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Get Contact List
This endpoint allows you to retrieve a complete list of contacts associated with your Spektif account.
Query Parameters
Query parameters that allow you to customize the API response.
| Nama | Deskripsi | Wajib | Default |
|---|---|---|---|
page |
Specifies the page number to retrieve. | Tidak | 1 |
paginate |
Defines the number of items returned per page. | Tidak | 20 |
search |
Searches for contacts by firstname, lastname or mobile number. | Tidak | - |
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/contact/store',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
// mobile_code no longer required; a full number will be parsed automatically
CURLOPT_POSTFIELDS => array('firstname' => 'John','lastname' => 'Doe','mobile' => '081988123456'),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Create New Contact
This endpoint allows you to add a new contact to your Spektif account. Provide the necessary contact details, and upon successful request, the API returns the created contact’s information in JSON format for easy integration.
Required Fields
The following fields are required to create a new contact in the system.
| Nama | Wajib | Default |
|---|---|---|
firstname |
Ya | - |
lastname |
Ya | - |
mobile |
Ya | - |
mobile |
Ya | - |
city |
Tidak | - |
state |
Tidak | - |
post_code |
Tidak | - |
address |
Tidak | - |
profile_image |
Tidak | - |
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/contact/update/{contactId}',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
// mobile_code is no longer required; pass a full phone number and it will be parsed
CURLOPT_POSTFIELDS => array('firstname' => 'John','lastname' => 'Doe','mobile' => '081988123456'),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Perbarui Kontak
This endpoint allows you to update an existing contact. You only need to send the fields you want to modify. Any field not included in the request will remain unchanged.
Required Fields
The following fields are required to create a new contact in the system.
| Nama | Wajib | Default |
|---|---|---|
firstname |
Ya | - |
lastname |
Ya | - |
mobile |
Ya | - |
city |
Tidak | - |
state |
Tidak | - |
post_code |
Tidak | - |
address |
Tidak | - |
profile_image |
Tidak | - |
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/contact/delete/{contactId}',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_POSTFIELDS => array('firstname' => 'John','lastname' => 'Doe','mobile_code' => '880','mobile' => '01988'),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Delete Contact
This endpoint allows you to delete a contact by its unique ID. Deletion may be restricted if the contact has associated messages or is blocked.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/inbox/conversation-list',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Conversation List
Retrieve a paginated list of conversations for the authenticated user, including contact info and conversation status.
Query Parameters
| Nama | Deskripsi | Default |
|---|---|---|
status |
Filter conversations by status. Use below value for the filter conversation via status. Done = 1; Pending = 2; Important = 3; Unread = 4; | Semua |
page |
Specifies the page number to retrieve. | 1 |
paginate |
Defines the number of items returned per page. | 20 |
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/inbox/change-conversation-status/2',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array('status' => '1'),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Change Conversation Status
Update the status of a conversation such as pending, done, or important. Here Done = 1, Pending = 2 and Important = 3,UnRead=4
URL Parameters
| Parameter | Tipe | Deskripsi |
|---|---|---|
conversation_id |
integer | Unique ID of the conversation |
Request Body
| Field | Tipe | Wajib |
|---|---|---|
status |
integer | YEs |
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/inbox/conversation-details/2',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_POSTFIELDS => array('status' => '1'),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Conversation Details
Retrieve complete details of a conversation including contact information, notes, tags, and list associations.
URL Parameters
| Parameter | Tipe | Deskripsi |
|---|---|---|
conversation_id |
integer | Unique ID of the conversation |
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/inbox/send-message',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
// mobile_code no longer required; provide full number and it will be parsed automatically
CURLOPT_POSTFIELDS => array('mobile' => '081234567890','message' => 'Hello world'),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Kirim Pesan
Send WhatsApp messages to a mobile number. This endpoint supports text, media, location, interactive lists, CTA URLs, and e-commerce messages. If no existing contact or conversation is found for the provided phone number, a new contact and conversation will be created automatically.
Request Body
| Field | Tipe | Wajib | Deskripsi |
|---|---|---|---|
mobile |
string | yes | A full mobile number. Country code will be detected automatically; include leading zero or international prefix. |
from_number |
string | conditional | A valid WhatsApp Business phone number registered on your account and in the Meta dashboard is required. If no ID is provided, the message will be sent using your default registered WhatsApp account. |
message |
string | Conditional | Text message body. Required if no media, location, or interactive data is provided |
image |
file | No | Image file (jpg, jpeg, png – max 5MB) |
document |
file | No | Document file (pdf, doc, docx – max 100MB) |
video |
file | No | Video file (mp4 – max 16MB) |
audio |
file | No | Audio file – max 16MB |
latitude |
decimal | Conditional | Latitude for location message |
longitude |
decimal | Conditional | Longitude for location message |
cta_url_id |
integer | No | CTA URL ID for interactive button messages |
interactive_list_id |
integer | No | Interactive list ID |
Notes
At least one message type must be provided.
Interactive messages require an active plan.
Blocked contacts cannot send or receive messages.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/inbox/send-template-message',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
// mobile_code not required anymore; submit a single full number instead
CURLOPT_POSTFIELDS => array('mobile' => '081234567890','template_id' => 'your template id'),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Send Template Message
Send an approved WhatsApp template message to an existing conversation. Template messages are commonly used for notifications, alerts, and business-initiated communication.
Request Body
| Field | Tipe | Wajib | Deskripsi |
|---|---|---|---|
mobile |
string | yes | A full mobile number. Country code will be detected automatically; include leading zero or international prefix. |
from_number |
string | conditional | A valid WhatsApp Business phone number registered on your account and in the Meta dashboard is required. If no ID is provided, the message will be sent using your default registered WhatsApp account. |
template_id |
string | Yes | The WhatsApp template ID (whatsapp_template_id) from Meta. You can get this from the template-list endpoint. |
Notes
Only approved WhatsApp templates can be sent.
Template messages are typically used for business-initiated conversations.
Blocked contacts cannot receive template messages.
WhatsApp account must be connected before sending messages.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/inbox/template-list',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Get Template List
This endpoint allows you to fetch all WhatsApp templates associated with your account.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/otp/send',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array(
// mobile_code is not required; a single mobile number will be parsed automatically
'mobile' => '81234567890',
'from_number' => '628001234567'
),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Send OTP
Send a one-time password (OTP) to a destination phone number via WhatsApp. The OTP will be sent using the approved AUTHENTICATION template configured in your OTP settings. Make sure you have created and approved an authentication template in the Template menu and selected it in the OTP configuration. The API returns a reference_id that must be used for subsequent verification.
Request Parameters
| Nama | Wajib | Deskripsi |
|---|---|---|
mobile |
Ya | Full destination mobile number. Country code will be auto-detected from first digits or leading zero. |
from_number |
Ya | Your WhatsApp Business phone number that will send the OTP (must be registered and configured) |
Success Response
{
"remark": "otp_sent",
"status": "success",
"message": ["OTP sent successfully"],
"data": {
"reference_id": "otp_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"expires_in": 300
}
}
Rate Limit Response (429)
{
"remark": "rate_limit_exceeded",
"status": "error",
"message": ["Too many OTP requests. Please wait 10 minutes before trying again."],
"data": {
"retry_after": 542
}
}
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/otp/verify',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array(
'reference_id' => 'otp_a1b2c3d4-e5f6-7890-abcd-ef1234567890',
'otp_code' => '123456'
),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Verify OTP
Verify an OTP code that was previously sent. Use the reference_id returned from the Send OTP endpoint along with the OTP code entered by the user. The OTP will be invalidated after successful verification or after exceeding the maximum verification attempts.
Request Parameters
| Nama | Wajib | Deskripsi |
|---|---|---|
reference_id |
Ya | The reference ID returned from the Send OTP endpoint |
otp_code |
Ya | The OTP code entered by the user |
Success Response
{
"remark": "otp_verified",
"status": "success",
"message": ["OTP verified successfully."],
"data": {
"reference_id": "otp_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"verified_at": "2026-03-02T10:30:00+07:00"
}
}
Error Response (Invalid Code)
{
"remark": "invalid_code",
"status": "error",
"message": ["Invalid OTP code."],
"data": {
"remaining_attempts": 3
}
}
Error Response (Expired)
{
"remark": "expired",
"status": "error",
"message": ["This OTP has expired. Please request a new one."]
}
$curl = curl_init();
$referenceId = 'otp_a1b2c3d4-e5f6-7890-abcd-ef1234567890';
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/otp/status?reference_id=' . $referenceId,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Check OTP Status
Check the current status of a previously sent OTP request. Possible statuses: pending, sent, delivered, verified, expired, failed.
Query Parameters
| Nama | Wajib | Deskripsi |
|---|---|---|
reference_id |
Ya | The reference ID of the OTP request |
Success Response
{
"remark": "otp_status",
"status": "success",
"message": ["OTP status retrieved."],
"data": {
"reference_id": "otp_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"destination_number": "6281234567890",
"status": "sent",
"sent_at": "2026-03-02T10:25:00+07:00",
"verified_at": null,
"expires_at": "2026-03-02T10:30:00+07:00",
"verify_attempts": 0,
"created_at": "2026-03-02T10:25:00+07:00"
}
}
Status Values
| Status | Deskripsi |
|---|---|
pending |
OTP created but not yet sent to WhatsApp |
sent |
OTP has been sent via WhatsApp API |
delivered |
OTP message has been delivered to the recipient |
verified |
OTP has been successfully verified |
expired |
OTP has expired and can no longer be used |
failed |
OTP sending failed or max verification attempts exceeded |
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/otp/resend',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => array(
'reference_id' => 'otp_a1b2c3d4-e5f6-7890-abcd-ef1234567890'
),
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
Resend OTP
Resend an OTP to the same destination number. The previous OTP will be invalidated and a new OTP code will be generated and sent. A new reference_id will be returned. This endpoint is also subject to rate limiting.
Request Parameters
| Nama | Wajib | Deskripsi |
|---|---|---|
reference_id |
Ya | The reference ID of the original OTP request to resend |
Success Response
{
"remark": "otp_resent",
"status": "success",
"message": ["OTP sent successfully"],
"data": {
"reference_id": "otp_new-uuid-generated-here",
"expires_in": 300
}
}
Important Notes
- The previous OTP associated with the reference_id will be expired.
- A new reference_id is returned that must be used for verification.
- Rate limiting applies — too many resends will trigger a cooldown.
$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://www.devcrm.spektif.id/external-api/otp/history?page=1&per_page=15&status=verified',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'GET',
CURLOPT_HTTPHEADER => array(
'client-id: YOUR-CLIENT-ID',
'client-secret: YOUR-CLIENT-SECRET',
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
OTP History
Retrieve a paginated list of OTP requests. Filter by status, from_number, or destination_number.
Query Parameters
| Nama | Wajib | Deskripsi |
|---|---|---|
page |
Tidak | Page number for pagination (default: 1) |
per_page |
Tidak | Number of results per page (default: 15, max: 100) |
from_number |
Tidak | Filter by WhatsApp sender number |
destination_number |
Tidak | Filter by destination phone number |
status |
Tidak | Filter by status: pending, sent, delivered, verified, expired, failed |
Success Response
{
"remark": "otp_history",
"status": "success",
"message": ["OTP history retrieved."],
"data": {
"data": [
{
"reference_id": "otp_a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"destination_number": "6281234567890",
"status": "verified",
"verify_attempts": 1,
"sent_at": "2026-03-02T10:25:00+07:00",
"verified_at": "2026-03-02T10:26:30+07:00",
"expires_at": "2026-03-02T10:30:00+07:00",
"created_at": "2026-03-02T10:25:00+07:00"
}
],
"pagination": {
"current_page": 1,
"last_page": 5,
"per_page": 15,
"total": 67
}
}
}