Custom List API (Teams)

Overview

Custom list segments are segments you create from your own list of users. You create a custom list segment in three steps as follows:

  1. Request a pre-signed URL with your first API call. A pre-signed URL gives you temporary access to upload your list of users.

  2. Upload your file to the pre-signed URL.

  3. Indicate completion of the upload with a second API call. CleverTap processes the file and displays the segment on the dashboard.

    • If your account has Teams enabled, you can allocate the segment to one or more teams in this step.

Step 1: Create a Pre-signed URL

This request generates a pre-signed URL that you use to upload your custom list file. The URL remains valid for 24 hours.

Base URL

Here is an example base URL from the India region:
https://in1.api.clevertap.com/get_custom_list_segment_url
Refer to Region for region-specific endpoints.

HTTP Method

POST

Headers

The following headers are required. For details, see Headers.

Example Request

curl -X POST \
  https://in1.api.clevertap.com/get_custom_list_segment_url \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/json' \
  -H 'X-CleverTap-Account-Id: ACCOUNT_ID' \
  -H 'X-CleverTap-Passcode: PASSCODE'
import requests

url = "https://in1.api.clevertap.com/get_custom_list_segment_url"
headers = {
    "Cache-Control": "no-cache",
    "Content-Type": "application/json",
    "X-CleverTap-Account-Id": "ACCOUNT_ID",
    "X-CleverTap-Passcode": "PASSCODE"
}

response = requests.post(url, headers=headers)
print(response.text)

const url = "https://in1.api.clevertap.com/get_custom_list_segment_url";
const headers = {
  "Cache-Control": "no-cache",
  "Content-Type": "application/json",
  "X-CleverTap-Account-Id": "ACCOUNT_ID",
  "X-CleverTap-Passcode": "PASSCODE"
};

axios.post(url, {}, { headers })
  .then(res => console.log(res.data))
  .catch(err => console.error(err.response ? err.response.data : err.message));
require 'net/http'
require 'uri'

uri = URI.parse("https://in1.api.clevertap.com/get_custom_list_segment_url")
request = Net::HTTP::Post.new(uri)
request["X-CleverTap-Account-Id"] = "ACCOUNT_ID"
request["X-CleverTap-Passcode"] = "PASSCODE"
request["Content-Type"] = "application/json"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

puts response.body
<?php
$headers = array(
  'X-CleverTap-Account-Id: ACCOUNT_ID',
  'X-CleverTap-Passcode: PASSCODE',
  'Content-Type: application/json'
);
$url = "https://in1.api.clevertap.com/get_custom_list_segment_url";

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$response = curl_exec($ch);
curl_close($ch);

echo $response;

Step 2: Upload Custom List File

Once you have the pre-signed URL, upload the user list file.

File Format Requirements

  • File must be CSV.
  • Include a header row.
  • Use UTF-8 encoding.
  • Maximum file size: 5 GB.
  • Mandatory columns: identity (user identifier).

Example Request

curl --request PUT \
  --upload-file "<path to file on your local machine>" \
  "<PRE-SIGNED URL>"
import requests

file_path = "<path to file on your local machine>"
presigned_url = "<PRE-SIGNED URL>"

with open(file_path, "rb") as file:
    response = requests.put(presigned_url, data=file)

print(response.status_code)
require "net/http"

uri = URI("<PRE-SIGNED URL>")
request = Net::HTTP::Put.new(uri)
request.body = File.read("<path to file on your local machine>")
request["Content-Type"] = "text/csv"

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end
const fs = require("fs");
const axios = require("axios");

const filePath = "<path to file on your local machine>";
const presignedUrl = "<PRE-SIGNED URL>";

axios.put(presignedUrl, fs.createReadStream(filePath), {
  headers: { "Content-Type": "text/csv" }
})
.then(res => console.log("Upload complete:", res.status))
.catch(err => console.error(err.message));
<?php
$filePath = "<path to file on your local machine>";
$presignedUrl = "<PRE-SIGNED URL>";

$ch = curl_init($presignedUrl);
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_INFILE, fopen($filePath, "r"));
curl_setopt($ch, CURLOPT_INFILESIZE, filesize($filePath));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
curl_close($ch);

echo $response;

Step 3: Indicate Completion of File Upload

After you upload the file, call this endpoint to confirm completion. CleverTap processes the file and creates the custom list segment.
If your account has Teams enabled, include the optional team_allocations array to allocate the new segment to team(s).

Base URL

Example base URL from the India region:
https://in1.api.clevertap.com/upload_custom_list_segment_completed

HTTP Method

POST

Headers

All headers are required.

The following table lists the required headers for this request.

HeaderDescriptionExample
X-CleverTap-Account-IdYour CleverTap Account ID.ACCOUNT_ID
X-CleverTap-PasscodeYour CleverTap Account Passcode.PASSCODE
Content-TypeAlways set to application/json.application/json

Body Parameters

Provide the following body parameters. Include the Teams parameter only if Teams are enabled for your account.

ParameterDescriptionTypeRequiredExample
nameName of the segment.StringYes"sample_segment"
creatorName of the user making this API call.StringYes"Jane"
filenameName of the uploaded file.StringYes"my_file_name.csv"
emailAdmin email address of the owner.StringYes"[email protected]"
urlPre-signed URL used for upload, obtained in Step 1.StringYes"<PRE-SIGNED URL>"
replaceIf true, replaces an existing segment with the same name.BooleanNofalse
team_allocationsTeams only. Array that maps the created segment to one or more team names. Omit this field if not using Teams.Array of objectsNo*See “Teams Object” below
  • Required only when allocating segments to teams due to account policy or configuration.

Each object in team_allocations uses the following keys.

KeyDescriptionTypeRequiredExample
segment_nameName of the segment to allocate (use the same value as name in this request).StringYes"Premium Users"
customer_segment_idInternal ID if already available; omit when creating a new segment without an existing ID.StringNo"SEG12345"
team_namesOne or more team names to assign to the segment. Team names must match names configured in your account and are case-sensitive.Array of stringsYes["team A"]

Example Teams Payload

[
  {
    "segment_name": "Premium Users",
    "customer_segment_id": "SEG12345",
    "team_names": ["team A"]
  }
]

Example Request

curl -X POST \
  https://in1.api.clevertap.com/upload_custom_list_segment_completed \
  -H 'Content-Type: application/json' \
  -H 'X-CleverTap-Account-Id: ACCOUNT_ID' \
  -H 'X-CleverTap-Passcode: PASSCODE' \
  -d '{
    "name":"sample_segment",
    "email":"[email protected]",
    "filename":"my_file_name.csv",
    "creator":"Jane",
    "url":"<PRE-SIGNED URL>",
    "replace":false,
    "team_allocations":[
      {
        "segment_name":"sample_segment",
        "customer_segment_id":"SEG12345",
        "team_names":["team A"]
      }
    ]
  }'
import requests

url = "https://in1.api.clevertap.com/upload_custom_list_segment_completed"
headers = {
    "Content-Type": "application/json",
    "X-CleverTap-Account-Id": "ACCOUNT_ID",
    "X-CleverTap-Passcode": "PASSCODE"
}
data = {
    "name": "sample_segment",
    "email": "[email protected]",
    "filename": "my_file_name.csv",
    "creator": "Jane",
    "url": "<PRE-SIGNED URL>",
    "replace": False,
    "team_allocations": [
        {
            "segment_name": "sample_segment",
            "customer_segment_id": "SEG12345",
            "team_names": ["team A"]
        }
    ]
}

response = requests.post(url, json=data, headers=headers)
print(response.json())
const axios = require("axios");

const url = "https://in1.api.clevertap.com/upload_custom_list_segment_completed";
const headers = {
  "Content-Type": "application/json",
  "X-CleverTap-Account-Id": "ACCOUNT_ID",
  "X-CleverTap-Passcode": "PASSCODE"
};

const data = {
  name: "sample_segment",
  email: "[email protected]",
  filename: "my_file_name.csv",
  creator: "Jane",
  url: "<PRE-SIGNED URL>",
  replace: false,
  team_allocations: [
    {
      segment_name: "sample_segment",
      customer_segment_id: "SEG12345",
      team_names: ["team A"]
    }
  ]
};

axios.post(url, data, { headers })
  .then(res => console.log(res.data))
  .catch(err => console.error(err.response ? err.response.data : err.message));
require 'net/http'
require 'json'

uri = URI("https://in1.api.clevertap.com/upload_custom_list_segment_completed")
request = Net::HTTP::Post.new(uri, 'Content-Type' => 'application/json')
request["X-CleverTap-Account-Id"] = "ACCOUNT_ID"
request["X-CleverTap-Passcode"] = "PASSCODE"
request.body = {
  name: "sample_segment",
  email: "[email protected]",
  filename: "my_file_name.csv",
  creator: "Jane",
  url: "<PRE-SIGNED URL>",
  replace: false,
  team_allocations: [
    {
      segment_name: "sample_segment",
      customer_segment_id: "SEG12345",
      team_names: ["team A"]
    }
  ]
}.to_json

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end

puts response.body
<?php
$url = "https://in1.api.clevertap.com/upload_custom_list_segment_completed";
$headers = array(
  'Content-Type: application/json',
  'X-CleverTap-Account-Id: ACCOUNT_ID',
  'X-CleverTap-Passcode: PASSCODE'
);
$data = array(
  "name" => "sample_segment",
  "email" => "[email protected]",
  "filename" => "my_file_name.csv",
  "creator" => "Jane",
  "url" => "<PRE-SIGNED URL>",
  "replace" => false,
  "team_allocations" => array(
    array(
      "segment_name" => "sample_segment",
      "customer_segment_id" => "SEG12345",
      "team_names" => array("team A")
    )
  )
);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);

$response = curl_exec($ch);
curl_close($ch);

echo $response;

Error Codes

The Custom List API may return various error responses depending on the request.

Use the following table to troubleshoot common errors. (Teams-specific checks can also trigger team_ids_required if your account requires team allocation.)

HTTP StatusErrorDescription
400json_parse_failedThe request body contains invalid JSON.
400invalid_payloadThe segmentUploadDetails field is missing or empty.
401missing_fieldsOne or more required fields are missing — segment name, email ID, creator, filename, or pre-signed URL.
401invalid_emailThe email format is invalid or the email is not associated with an admin.
401segment_not_foundNo existing segment found to replace.
401segment_in_progressA previous segment upload is still being processed.
401duplicate_nameA segment with the same name already exists.
401url_already_usedThe pre-signed URL has already been used.
401file_not_foundThe file was not found in cloud storage.
401file_not_uploadedThe file has not been uploaded to cloud storage yet.
401cloud_connection_failedFailed to connect to cloud storage.
401team_ids_requiredTeam IDs must be provided when team-based segmentation is enabled.
401feature_not_enabledThe custom list segments feature is not enabled for this account.
401account_meta_missingAccount metadata not found for the specified account ID.
401url_generation_failedFailed to generate the pre-signed URL.
401unexpected_url_errorAn unexpected error occurred during pre-signed URL generation.
413file_too_largeThe uploaded file exceeds the maximum allowed size (5 GB).
415invalid_file_formatThe file format is invalid (only .csv with UTF-8 encoding is supported).
429rate_limit_exceededToo many requests have been made in a short time.
503worker_unavailableThe account’s processing worker is currently unavailable.

Notes

  • team_allocations is optional and only applies to accounts with Teams enabled.
  • Use the exact team names configured in your account for team_names. Team names are case-sensitive.
  • When creating a brand-new segment, you can omit customer_segment_id.
  • If your account enforces team allocation, omitting team_allocations may result in team_ids_required.

//kapa search bot