Subscribe

Overview

The Subscribe API provides the ability to set a phone number or email status as subscribed or unsubscribed. This is important so that you do not send a message to your users accidentally unless they have explicitly opted for it. There may be cases when multiple users share a phone number or email; however, once a phone number or email is marked as unsubscribed (DND), communication is stopped for all users using the specified number or email.

For example, a user opts out of receiving messages. You can pass the phone number or email address and the status as Unsubscribe in the Subscribe API. The user phone number or email is unsubscribed for all users who share the same phone number or email. After the user opts to receive messages again, the phone number or email can be changed back to Resubscribe.

πŸ“˜

Note

To set only a specific user state as DND, set the MSG-sms flag for SMS or MSG-email flag for an email to false in the Upload User Profiles. If the other users sharing the number or email have not opted out, they will continue to receive messages.

πŸ“˜

Note

From January 13, 2020 onwards, Channel Unsubscribed Event also triggers the Subscribe API.

Passing subscription status for phone numbers or email requires a POST request with a JSON payload specifying the phone number or email and subscription status. There is no limit on the number of requests to the API, but the batch size for each request must be up to 1000.

πŸ“˜

Note

The batch size denotes the maximum number of records that can be fetched in a single call. The response may vary.

Base URL

Here is an example base URL from the account in the India region:
https://in1.api.clevertap.com/1/subscribe

Region

Refer Region for more details.

HTTP Method

POST

Headers

Refer Headers for more details.

Body Parameters

  • Add the type as email or phone number
  • Add the value of the email or phone number
  • Set the status to Unsubscribe or Resubscribe.
ParameterDescriptionTypeExample Value
typeSet to phone or email. Required.stringβ€œphone”
"email"
valueThe phone number or email address of the userstring"+919213231415"
"[email protected]"
statusPass the status of the number or email. The valid values can be Unsubscribe or Resubscribe.stringUnsubscribe or Resubscribe.

The following is an example JSON payload for iOS/Android.

{
    "d": [
        {   
            "type": "phone",
            "value": "+919213231415",
            "status": "Unsubscribe"
        },
        {
            "type": "phone",
            "value": "+919213231416",
            "status": "Resubscribe"
        },
    {
            "type": "email",
            "value": "[email protected]",
            "status": "Unsubscribe"
        },
        {
            "type": "email",
            "value": "[email protected]",
            "status": "Resubscribe"
        }
    ]
}

Example Request

Here is an example cURL request to the Subscribe API showing the headers needed to authenticate the request from the account in the India region:

curl --location --request POST 'https://in1.api.clevertap.com/1/subscribe'
--header 'X-CleverTap-Account-Id: ACCOUNT_ID' \ 
--header 'X-CleverTap-Passcode: PASSCODE' \ 
--header 'Content-Type: application/json' \ 
--data-raw '{ "d": [ { "type": "phone", "value": "+919213231415", "status": "Unsubscribe" }, { "type": "phone", "value": "+919213231416", "status": "Resubscribe" }, { "type": "email", "value": "[email protected]", "status": "Unsubscribe" }, { "type": "email", "value": "[email protected]", "status": "Resubscribe" } ] }'
require "uri"
require "net/http"
url = URI("https://in1.api.clevertap.com/1/subscribe")
https = Net::HTTP.new(url.host, url.port);
https.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-CleverTap-Account-Id"] = "ACCOUNT_ID"
request["X-CleverTap-Passcode"] = "PASSCODE"
request["Content-Type"] = "application/json"
request.body = "{ \"d\": [ { \"type\": \"phone\", \"value\": \"+919213231415\", \"status\": \"Unsubscribe\" }, { \"type\": \"phone\", \"value\": \"+919213231416\", \"status\": \"Resubscribe\" }, { \"type\": \"email\", \"value\": \"[email protected]\", \"status\": \"Unsubscribe\" }, { \"type\": \"email\", \"value\": \"[email protected]\", \"status\": \"Resubscribe\" } ] }"
response = https.request(request)
puts response.read_body
import requests
url = "https://in1.api.clevertap.com/1/subscribe"
payload = "{ \"d\": [ { \"type\": \"phone\", \"value\": \"+919213231415\", \"status\": \"Unsubscribe\" }, { \"type\": \"phone\", \"value\": \"+919213231416\", \"status\": \"Resubscribe\" }, { \"type\": \"email\", \"value\": \"[email protected]\", \"status\": \"Unsubscribe\" }, { \"type\": \"email\", \"value\": \"[email protected]\", \"status\": \"Resubscribe\" } ] }"
headers = {
  'X-CleverTap-Account-Id': 'ACCOUNT_ID',
  'X-CleverTap-Passcode': 'PASSCODE',
  'Content-Type': 'application/json'
}
response = requests.request("POST", url, headers=headers, data = payload)
print(response.text.encode('utf8'))
<?php
require_once 'HTTP/Request2.php';
$request = new HTTP_Request2();
$request->setUrl('https://in1.api.clevertap.com/1/subscribe');
$request->setMethod(HTTP_Request2::METHOD_POST);
$request->setConfig(array(
  'follow_redirects' => TRUE
));
$request->setHeader(array(
  'X-CleverTap-Account-Id' => 'ACCOUNT_ID',
  'X-CleverTap-Passcode' => 'PASSCODE',
  'Content-Type' => 'application/json'
));
$request->setBody('{ "d": [ { "type": "phone", "value": "+919213231415", "status": "Unsubscribe" }, { "type": "phone", "value": "+919213231416", "status": "Resubscribe" }, { "type": "email", "value": "[email protected]", "status": "Unsubscribe" }, { "type": "email", "value": "[email protected]", "status": "Resubscribe" } ] }');
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();
}
var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://in1.api.clevertap.com/1/subscribe',
  'headers': {
    'X-CleverTap-Account-Id': 'ACCOUNT_ID',
    'X-CleverTap-Passcode': 'PASSCODE',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({"d":[{"type":"phone","value":"+919213231415","status":"Unsubscribe"},{"type":"phone","value":"+919213231416","status":"Resubscribe"},{"type":"email","value":"[email protected]","status":"Unsubscribe"},{"type":"email","value":"[email protected]","status":"Resubscribe"}]})
};
request(options, function (error, response) { 
  if (error) throw new Error(error);
  console.log(response.body);
});
package main
import (
  "fmt"
  "strings"
  "net/http"
  "io/ioutil"
)
func main() {
  url := "https://in1.api.clevertap.com/1/subscribe"
  method := "POST"
  payload := strings.NewReader("{ \"d\": [ { \"type\": \"phone\", \"value\": \"+919213231415\", \"status\": \"Unsubscribe\" }, { \"type\": \"phone\", \"value\": \"+919213231416\", \"status\": \"Resubscribe\" }, { \"type\": \"email\", \"value\": \"[email protected]\", \"status\": \"Unsubscribe\" }, { \"type\": \"email\", \"value\": \"[email protected]\", \"status\": \"Resubscribe\" } ] }")
  client := &http.Client {
  }
  req, err := http.NewRequest(method, url, payload)
  if err != nil {
    fmt.Println(err)
  }
  req.Header.Add("X-CleverTap-Account-Id", "ACCOUNT_ID")
  req.Header.Add("X-CleverTap-Passcode", "PASSCODE")
  req.Header.Add("Content-Type", "application/json")
  res, err := client.Do(req)
  defer res.Body.Close()
  body, err := ioutil.ReadAll(res.Body)
  fmt.Println(string(body))
}

Example Response

{
    "status": "success",
    "processed": 4,
    "unprocessed": []
}

Debugging

Requests with processing errors are returned in the API call response as shown in the example below.

{
    "status":<success, partial, fail>, 
    "processed":<count>, 
    "unprocessed": [{"status":"fail", "code":<error code>, "error":<error msg>, "record":<record>}]
}

To test if your data will be submitted without errors, you can add the parameter dryRun=1 to the URL. This validates the input without submitting the data to CleverTap.

SMS Delivery

The message delivery is decided by the phone-level and user-level subscription status. If a phone number has opted out but not the associated user profile, then the SMS is not delivered.

Phone-level subscription (MSG-dndPhone)User-level SMS subscription (MSG-sms)Reachability
SubscribedSubscribedReachable
SubscribedUnsubscribedUnreachable
UnsubscribedSubscribedUnreachable
UnsubscribedUnsubscribedUnreachable

Email Delivery

The message delivery is decided by the email-level and user-level subscription status. If an email address has opted out but not the associated user profile, then the message is not delivered.

Handling subscriptions will automatically trigger the subscribe and disassociate APIs leading to Email-level subscription instead of User-level subscription.

Email-level subscription (MSG-dndEmail)User-level Email subscription (MSG-email)Reachability
SubscribedSubscribedReachable
SubscribedUnsubscribedUnreachable
UnsubscribedSubscribedUnreachable
UnsubscribedUnsubscribedUnreachable

To understand the common queries and concerns related to CleverTap APIs, refer to API FAQs.


What’s Next