V 2.0
Contact
Overview
The Contact API provides endpoints to manage contacts within the system. It enables operations such as adding, updating, and deleting contacts in contact lists.
Base Path
All Contact API endpoints are under: /api/v2/AddContactApi/
Key Features:
-
Contact Management:
- Add new contacts to contact lists
- Update existing contact information
- Soft delete contacts (mark as deleted)
- Hard delete contacts (permanently remove)
-
Authentication:
- Supports session-based authentication (SSID)
- Supports token-based authentication (userId + token)
- Permission-based access control (ADD_CONTACTS permission required)
-
Flexible Contact List IDs:
- Supports numeric contact list IDs
- Supports MongoDB ObjectId format for contact list IDs
-
Action Types:
- Action 0: Add new contact
- Action 1: Update existing contact
- Action 2: Soft delete contact (mark as deleted)
-
Response Format:
- Success responses include contact_id
- Operation status and message included
- Error codes for troubleshooting
Permissions Required:
-
ADD_CONTACTS- Required for all contact operations
Add Contact
Endpoint
- Method: POST
-
Path:
v4-api.deepcall.com/api/v2/contact/addContact/
Description
The Add Contact endpoint allows you to add new contacts, update existing contacts, or soft delete contacts from contact lists. The behavior is controlled by the action parameter.
Use Cases
- Adding new contacts to a contact list for campaigns
- Updating contact information (phone numbers, names, custom fields)
- Soft deleting contacts (marking as deleted without permanent removal)
- Bulk contact import operations
- CRM integration for contact synchronization
- Campaign contact list management
- Managing scheduled/rescheduled campaign contacts
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| userId | string | Yes* | User ID for authentication (*required if ssid not provided) |
| token | string | Yes* | Authentication token (*required if ssid not provided) |
| ssid | string | Yes* | Session ID (*required if userId/token not provided) |
| clId | number/string | Yes | Contact List ID (numeric or MongoDB ObjectId) |
| action | number | Yes | Action type: 0=Add, 1=Update, 2=Soft Delete |
| record | object | Yes | Contact data object with fields |
| campaignReschedule | string/number | No | Reschedule timestamp for campaign contacts |
| campaignSchedule | string/number | No | Schedule timestamp for campaign contacts |
| source | string | No | Source of contact addition (e.g., "API", "Import") |
| editPanelContactId | string | No | Contact ID for update operations |
Record Object Fields
The record object can contain any custom fields defined in your contact list. Common fields include:
| Field | Type | Description |
|---|---|---|
| mobile | string | Mobile number (primary contact field) |
| name | string | Contact name |
| string | Email address | |
| address | string | Contact address |
| city | string | City |
| state | string | State |
| country | string | Country |
| [custom] | string | Any custom fields defined in contact list |
Action Types
Action 0 - Add New Contact:
- Creates a new contact in the contact list
- Validates mobile number against DND filters
- Checks for duplicate contacts
- Assigns unique contact ID
Action 1 - Update Existing Contact:
- Updates existing contact information
- Requires
editPanelContactIdor matching mobile number - Preserves contact history
- Updates last modified timestamp
Action 2 - Soft Delete:
- Marks contact as deleted (is_deleted: 1)
- Contact remains in database but excluded from campaigns
- Can be restored if needed
- Maintains data integrity for reporting
Request Examples
Example 1: Add New Contact with SSID
{
"ssid": "{{ssid}}",
"clId": 123,
"action": 0,
"record": {
"mobile": "919876543210",
"name": "John Doe",
"email": "john@example.com"
}
}
Example 2: Add Contact with Token Auth
{
"userId": "{{userid}}",
"token": "{{token}}",
"clId": 123,
"action": 0,
"record": {
"mobile": "919876543210",
"name": "Jane Smith",
"email": "jane@example.com",
"city": "New York"
}
}
Example 3: Add Contact with MongoDB ObjectId
{
"ssid": "{{ssid}}",
"clId": "507f1f77bcf86cd799439011",
"action": 0,
"record": {
"mobile": "919876543210",
"name": "Mike Johnson"
}
}
Example 4: Update Existing Contact
{
"ssid": "{{ssid}}",
"clId": 123,
"action": 1,
"editPanelContactId": "contact_12345",
"record": {
"mobile": "919876543210",
"name": "John Doe Updated",
"email": "john.updated@example.com"
}
}
Example 5: Soft Delete Contact
{
"ssid": "{{ssid}}",
"clId": 123,
"action": 2,
"record": {
"mobile": "919876543210"
}
}
Example 6: Add Contact with Campaign Schedule
{
"ssid": "{{ssid}}",
"clId": 123,
"action": 0,
"campaignSchedule": 1732435200,
"source": "API",
"record": {
"mobile": "919876543210",
"name": "Scheduled Contact",
"email": "scheduled@example.com"
}
}
Example 7: Add Contact with Multiple Custom Fields
{
"userId": "{{userid}}",
"token": "{{token}}",
"clId": 123,
"action": 0,
"record": {
"mobile": "919876543210",
"name": "Sarah Williams",
"email": "sarah@example.com",
"address": "123 Main St",
"city": "Mumbai",
"state": "Maharashtra",
"country": "India",
"company": "Tech Corp",
"designation": "Manager"
}
}
Response Details
Success Response
Status Code: 200
{
"code": 200,
"status": "success",
"message": "Contact added successfully",
"contactId": "contact_12345"
}
Response Field Descriptions
| Field | Type | Description |
|---|---|---|
| code | number | Response code (200 for success) |
| status | string | Response status ("success") |
| message | string | Success message |
| contactId | string | Unique ID of the added/updated contact |
Error Response Examples
Error 1: Invalid Contact List ID
Status Code: 200
{
"status": "error",
"message": "Invalid contact list",
"code": 1006
}
Error 2: Permission Denied
Status Code: 200
{
"status": "error",
"message": "Permission denied",
"code": 1015
}
Error 3: Invalid Mobile Number
Status Code: 200
{
"status": "error",
"message": "Contact number not valid",
"code": 1005
}
Error 4: Missing Required Fields
Status Code: 200
{
"status": "error",
"message": "Please provide record",
"code": 1022
}
Error 5: Invalid Action
Status Code: 200
{
"status": "error",
"message": "Please provide action/(accepted: 0,1,2)",
"code": 1029
}
Validation Rules
-
Mobile Number Validation:
- Must be a valid phone number format
- DND filtering applied if enabled
- Duplicate checking based on contact list settings
-
XSS Protection:
- All input fields sanitized for XSS attacks
- HTML tags and special characters filtered
-
Contact List Validation:
- Must belong to the authenticated user
- Must be active (not deleted)
- Must exist in the system
-
Field Type Validation:
- Custom fields validated against field definitions
- Data types enforced (text, number, date, etc.)
Notes
- All contacts are stored with timestamps (create_date, last_update)
- Contact IDs are unique within a contact list
- Soft deleted contacts can be filtered in campaign reports
- Hard delete operation available via separate endpoint
- Campaign schedule/reschedule timestamps in Unix format
Add Contact
var axios = require('axios');
var data = '{"ssid": "{{ssid}}","clId": 123,"action": 0,"record": {"mobile": "919876543210","name": "John Doe","email": "john@example.com"}}';
var config = {
method: 'post',
url: '{{brand}}/api/v2/AddContactApi/addContact',
headers: {
'Content-Length': ''
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
setUrl('{{brand}}/api/v2/AddContactApi/addContact');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
'follow_redirects' => TRUE
));
$request->setHeader(array(
'Content-Length' => ''
));
$request->setBody('{"ssid": "{{ssid}}","clId": 123,"action": 0,"record": {"mobile": "919876543210","name": "John Doe","email": "john@example.com"}}');
try {
$response = $request->send();
if ($response->getStatus() == 200) {
echo $response->getBody();
}
else {
echo 'Unexpected HTTP status: ' . $response->getStatus() . ' ' .
$response->getReasonPhrase();
}
}
catch(HTTP_Request2_Exception $e) {
echo 'Error: ' . $e->getMessage();
}import http.client
conn = http.client.HTTPSConnection("{{brand}}")
payload = "{\"ssid\": \"{{ssid}}\",\"clId\": 123,\"action\": 0,\"record\": {\"mobile\": \"919876543210\",\"name\": \"John Doe\",\"email\": \"john@example.com\"}}"
headers = {
'Content-Length': ''
}
conn.request("POST", "/api/v2/AddContactApi/addContact", payload, headers)
res = conn.getresponse()
data = res.read()
print(data.decode("utf-8"))var client = new RestClient("{{brand}}/api/v2/AddContactApi/addContact");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
var body = @"{" + "\n" +
@" ""ssid"": ""{{ssid}}""," + "\n" +
@" ""clId"": 123," + "\n" +
@" ""action"": 0," + "\n" +
@" ""record"": {" + "\n" +
@" ""mobile"": ""919876543210""," + "\n" +
@" ""name"": ""John Doe""," + "\n" +
@" ""email"": ""john@example.com""" + "\n" +
@" }" + "\n" +
@"}";
request.AddParameter("text/plain", body, ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);curl --location -g --request POST '{{brand}}/api/v2/AddContactApi/addContact' \
--data-raw '{
"ssid": "{{ssid}}",
"clId": 123,
"action": 0,
"record": {
"mobile": "919876543210",
"name": "John Doe",
"email": "john@example.com"
}
}'var request = http.Request('POST', Uri.parse('{{brand}}/api/v2/AddContactApi/addContact'));
request.body = '''{\n "ssid": "{{ssid}}",\n "clId": 123,\n "action": 0,\n "record": {\n "mobile": "919876543210",\n "name": "John Doe",\n "email": "john@example.com"\n }\n}''';
http.StreamedResponse response = await request.send();
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
}
else {
print(response.reasonPhrase);
}
package main
import (
"fmt"
"strings"
"net/http"
"io/ioutil"
)
func main() {
url := "%7B%7Bbrand%7D%7D/api/v2/AddContactApi/addContact"
method := "POST"
payload := strings.NewReader(`{
"ssid": "{{ssid}}",
"clId": 123,
"action": 0,
"record": {
"mobile": "919876543210",
"name": "John Doe",
"email": "john@example.com"
}
}`)
client := &http.Client {
}
req, err := http.NewRequest(method, url, payload)
if err != nil {
fmt.Println(err)
return
}
res, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(string(body))
}POST /api/v2/AddContactApi/addContact HTTP/1.1
Host: {{brand}}
Content-Length: 159
{
"ssid": "{{ssid}}",
"clId": 123,
"action": 0,
"record": {
"mobile": "919876543210",
"name": "John Doe",
"email": "john@example.com"
}
}OkHttpClient client = new OkHttpClient().newBuilder()
.build();
MediaType mediaType = MediaType.parse("text/plain");
RequestBody body = RequestBody.create(mediaType, "{\n \"ssid\": \"{{ssid}}\",\n \"clId\": 123,\n \"action\": 0,\n \"record\": {\n \"mobile\": \"919876543210\",\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}");
Request request = new Request.Builder()
.url("{{brand}}/api/v2/AddContactApi/addContact")
.method("POST", body)
.addHeader("Content-Length", "")
.build();
Response response = client.newCall(request).execute();var myHeaders = new Headers();
myHeaders.append("Content-Length", "");
var raw = "{\n \"ssid\": \"{{ssid}}\",\n \"clId\": 123,\n \"action\": 0,\n \"record\": {\n \"mobile\": \"919876543210\",\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}";
var requestOptions = {
method: 'POST',
headers: myHeaders,
body: raw,
redirect: 'follow'
};
fetch("{{brand}}/api/v2/AddContactApi/addContact", requestOptions)
.then(response => response.text())
.then(result => console.log(result))
.catch(error => console.log('error', error));CURL *curl;
CURLcode res;
curl = curl_easy_init();
if(curl) {
curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_URL, "%7B%7Bbrand%7D%7D/api/v2/AddContactApi/addContact");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_DEFAULT_PROTOCOL, "https");
struct curl_slist *headers = NULL;
headers = curl_slist_append(headers, "Content-Length: ");
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
const char *data = "{\n \"ssid\": \"{{ssid}}\",\n \"clId\": 123,\n \"action\": 0,\n \"record\": {\n \"mobile\": \"919876543210\",\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}";
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
res = curl_easy_perform(curl);
}
curl_easy_cleanup(curl);
#import
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"%7B%7Bbrand%7D%7D/api/v2/AddContactApi/addContact"]
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:10.0];
NSDictionary *headers = @{
@"Content-Length": @""
};
[request setAllHTTPHeaderFields:headers];
NSData *postData = [[NSData alloc] initWithData:[@"{\n \"ssid\": \"{{ssid}}\",\n \"clId\": 123,\n \"action\": 0,\n \"record\": {\n \"mobile\": \"919876543210\",\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}" dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:postData];
[request setHTTPMethod:@"POST"];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if (error) {
NSLog(@"%@", error);
dispatch_semaphore_signal(sema);
} else {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *) response;
NSError *parseError = nil;
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
NSLog(@"%@",responseDictionary);
dispatch_semaphore_signal(sema);
}
}];
[dataTask resume];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); open Lwt
open Cohttp
open Cohttp_lwt_unix
let postData = ref "{\n \"ssid\": \"{{ssid}}\",\n \"clId\": 123,\n \"action\": 0,\n \"record\": {\n \"mobile\": \"919876543210\",\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}";;
let reqBody =
let uri = Uri.of_string "%7B%7Bbrand%7D%7D/api/v2/AddContactApi/addContact" in
let headers = Header.init ()
|> fun h -> Header.add h "Content-Length" ""
in
let body = Cohttp_lwt.Body.of_string !postData in
Client.call ~headers ~body `POST uri >>= fun (_resp, body) ->
body |> Cohttp_lwt.Body.to_string >|= fun body -> body
let () =
let respBody = Lwt_main.run reqBody in
print_endline (respBody)$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Content-Length", "")
$body = "{`n `"ssid`": `"{{ssid}}`",`n `"clId`": 123,`n `"action`": 0,`n `"record`": {`n `"mobile`": `"919876543210`",`n `"name`": `"John Doe`",`n `"email`": `"john@example.com`"`n }`n}"
$response = Invoke-RestMethod '{{brand}}/api/v2/AddContactApi/addContact' -Method 'POST' -Headers $headers -Body $body
$response | ConvertTo-Jsonrequire "uri"
require "net/http"
url = URI("{{brand}}/api/v2/AddContactApi/addContact")
http = Net::HTTP.new(url.host, url.port);
request = Net::HTTP::Post.new(url)
request["Content-Length"] = ""
request.body = "{\n \"ssid\": \"{{ssid}}\",\n \"clId\": 123,\n \"action\": 0,\n \"record\": {\n \"mobile\": \"919876543210\",\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}"
response = http.request(request)
puts response.read_body
printf '{
"ssid": "{{ssid}}",
"clId": 123,
"action": 0,
"record": {
"mobile": "919876543210",
"name": "John Doe",
"email": "john@example.com"
}
}'| http --follow --timeout 3600 POST '{{brand}}/api/v2/AddContactApi/addContact' \
Content-Length:import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif
var semaphore = DispatchSemaphore (value: 0)
let parameters = "{\n \"ssid\": \"{{ssid}}\",\n \"clId\": 123,\n \"action\": 0,\n \"record\": {\n \"mobile\": \"919876543210\",\n \"name\": \"John Doe\",\n \"email\": \"john@example.com\"\n }\n}"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "{{brand}}/api/v2/AddContactApi/addContact")!,timeoutInterval: Double.infinity)
request.addValue("", forHTTPHeaderField: "Content-Length")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
semaphore.signal()
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
Example Response
[{"key":"Date"
"value":"Sun
23 Nov 2025 12:00:00 GMT"}
{"key":"Content-Type"
"value":"application\/json; charset=utf-8"}
{"key":"Connection"
"value":"keep-alive"}
{"key":"Access-Control-Allow-Origin"
"value":"*"}]
{
"message": "Operation successfull",
"status": "success",
"code": 200,
"operation": "uploaded",
"contact_id": "Pf_WsJoBv5FDR6l2wa4r"
}