Search Leads
Use the lead search APIs to find campaign leads by campaign, list, phone number, lead state, disposition, timezone, or custom lead fields.
Search Endpoints
| Operation | Method and path |
|---|---|
| Search leads | POST https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{accountId}/campaignLeads/leadSearch |
| Search leads by phone list | POST https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{accountId}/campaignLeads/leadSearchByPhoneList |
| List lead states | GET https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{accountId}/campaignLeads/leadStates |
| List system dispositions | GET https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{accountId}/campaignLeads/systemDispositions |
Rate Limiting & Stability
Lead search requests are throttled per RingCX sub-account. Standard leadSearch requests are limited to 15 requests per 10 seconds and 60 requests per 30 seconds. Requests with count=true are limited to 90 requests per 10 seconds and 180 requests per 30 seconds. Search-by-exact-number requests are limited to 30 requests per 10 seconds and 120 requests per 60 seconds. Use narrow filters and pagination, and implement exponential backoff on 429 Too Many Requests responses.
SDK Setup
SDK examples in this article use JWT authentication and load credentials from environment variables.
npm install ringcentral-engage-voice-client dotenv
pip3 install ringcentral_engage_voice python-dotenv
Create a .env file in the directory where you run the sample:
RC_CLIENT_ID=<clientId>
RC_CLIENT_SECRET=<clientSecret>
RC_JWT=<jwt>
The SDK wrapper reads these values, signs in with RingCentral, and exchanges the RingCentral access token for a RingCX access token before calling RingCX APIs.
Search Leads
POST https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{accountId}/campaignLeads/leadSearch
Authorization: Bearer <ringcxAccessToken>
Content-Type: application/json
{
"campaignId": 12345,
"campaignIds": [12345],
"listIds": [],
"leadStates": ["READY"],
"agentDispositions": [],
"systemDispositions": [],
"physicalStates": ["CA"],
"leadTimezones": []
}
import requests
account_id = "<accountId>"
access_token = "<ringcxAccessToken>"
payload = {
"campaignId": 12345,
"campaignIds": [12345],
"listIds": [],
"leadStates": ["READY"],
"agentDispositions": [],
"systemDispositions": [],
"physicalStates": ["CA"],
"leadTimezones": [],
}
response = requests.post(
f"https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{account_id}/campaignLeads/leadSearch",
headers={
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
},
json=payload,
)
response.raise_for_status()
print(response.json())
const accountId = "<accountId>";
const accessToken = "<ringcxAccessToken>";
const payload = {
campaignId: 12345,
campaignIds: [12345],
listIds: [],
leadStates: ["READY"],
agentDispositions: [],
systemDispositions: [],
physicalStates: ["CA"],
leadTimezones: []
};
const response = await fetch(
`https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/${accountId}/campaignLeads/leadSearch`,
{
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
}
);
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());
const EngageVoice = require("ringcentral-engage-voice-client").default;
require("dotenv").config();
async function main() {
const ev = new EngageVoice({
clientId: process.env.RC_CLIENT_ID,
clientSecret: process.env.RC_CLIENT_SECRET
});
await ev.authorize({ jwt: process.env.RC_JWT });
const payload = {
campaignId: 12345,
campaignIds: [12345],
listIds: [],
leadStates: ["READY"],
agentDispositions: [],
systemDispositions: [],
physicalStates: ["CA"],
leadTimezones: []
};
const response = await ev.post(
"/api/v1/admin/accounts/{accountId}/campaignLeads/leadSearch",
payload
);
console.log(response.data);
}
main().catch(console.error);
import os
from dotenv import load_dotenv
from ringcentral_engage_voice import RingCentralEngageVoice
load_dotenv()
ev = RingCentralEngageVoice(
os.environ["RC_CLIENT_ID"],
os.environ["RC_CLIENT_SECRET"],
)
ev.authorize(jwt=os.environ["RC_JWT"])
payload = {
"campaignId": 12345,
"campaignIds": [12345],
"listIds": [],
"leadStates": ["READY"],
"agentDispositions": [],
"systemDispositions": [],
"physicalStates": ["CA"],
"leadTimezones": [],
}
response = ev.post(
"/api/v1/admin/accounts/{accountId}/campaignLeads/leadSearch",
payload,
).json()
print(response)
Use campaignIds when searching across more than one campaign. Use campaignId when the API operation or action expects a primary campaign context.
Search by Phone Number
POST https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{accountId}/campaignLeads/leadSearchByPhoneList
Authorization: Bearer <ringcxAccessToken>
Content-Type: application/json
{
"phoneList": [
"4155550100",
"4155550101"
],
"campaignIds": [12345]
}
import requests
account_id = "<accountId>"
access_token = "<ringcxAccessToken>"
payload = {
"phoneList": [
"4155550100",
"4155550101",
],
"campaignIds": [12345],
}
response = requests.post(
f"https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{account_id}/campaignLeads/leadSearchByPhoneList",
headers={
"Authorization": f"Bearer {access_token}",
"Content-Type": "application/json",
},
json=payload,
)
response.raise_for_status()
print(response.json())
const accountId = "<accountId>";
const accessToken = "<ringcxAccessToken>";
const payload = {
phoneList: [
"4155550100",
"4155550101"
],
campaignIds: [12345]
};
const response = await fetch(
`https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/${accountId}/campaignLeads/leadSearchByPhoneList`,
{
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
"Content-Type": "application/json"
},
body: JSON.stringify(payload)
}
);
if (!response.ok) throw new Error(await response.text());
console.log(await response.json());
const EngageVoice = require("ringcentral-engage-voice-client").default;
require("dotenv").config();
async function main() {
const ev = new EngageVoice({
clientId: process.env.RC_CLIENT_ID,
clientSecret: process.env.RC_CLIENT_SECRET
});
await ev.authorize({ jwt: process.env.RC_JWT });
const payload = {
phoneList: [
"4155550100",
"4155550101"
],
campaignIds: [12345]
};
const response = await ev.post(
"/api/v1/admin/accounts/{accountId}/campaignLeads/leadSearchByPhoneList",
payload
);
console.log(response.data);
}
main().catch(console.error);
import os
from dotenv import load_dotenv
from ringcentral_engage_voice import RingCentralEngageVoice
load_dotenv()
ev = RingCentralEngageVoice(
os.environ["RC_CLIENT_ID"],
os.environ["RC_CLIENT_SECRET"],
)
ev.authorize(jwt=os.environ["RC_JWT"])
payload = {
"phoneList": [
"4155550100",
"4155550101",
],
"campaignIds": [12345],
}
response = ev.post(
"/api/v1/admin/accounts/{accountId}/campaignLeads/leadSearchByPhoneList",
payload,
).json()
print(response)
Search Metadata
Use metadata endpoints to populate filters before building a search request.
GET https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{accountId}/campaignLeads/leadStates
Authorization: Bearer <ringcxAccessToken>
Accept: application/json
GET https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{accountId}/campaignLeads/systemDispositions
Authorization: Bearer <ringcxAccessToken>
Accept: application/json
import requests
account_id = "<accountId>"
access_token = "<ringcxAccessToken>"
headers = {
"Authorization": f"Bearer {access_token}",
"Accept": "application/json",
}
lead_states = requests.get(
f"https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{account_id}/campaignLeads/leadStates",
headers=headers,
)
lead_states.raise_for_status()
system_dispositions = requests.get(
f"https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/{account_id}/campaignLeads/systemDispositions",
headers=headers,
)
system_dispositions.raise_for_status()
print(lead_states.json())
print(system_dispositions.json())
const accountId = "<accountId>";
const accessToken = "<ringcxAccessToken>";
const headers = {
Authorization: `Bearer ${accessToken}`,
Accept: "application/json"
};
const leadStates = await fetch(
`https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/${accountId}/campaignLeads/leadStates`,
{ headers }
);
if (!leadStates.ok) throw new Error(await leadStates.text());
const systemDispositions = await fetch(
`https://ringcx.ringcentral.com/voice/api/v1/admin/accounts/${accountId}/campaignLeads/systemDispositions`,
{ headers }
);
if (!systemDispositions.ok) throw new Error(await systemDispositions.text());
console.log(await leadStates.json());
console.log(await systemDispositions.json());
const EngageVoice = require("ringcentral-engage-voice-client").default;
require("dotenv").config();
async function main() {
const ev = new EngageVoice({
clientId: process.env.RC_CLIENT_ID,
clientSecret: process.env.RC_CLIENT_SECRET
});
await ev.authorize({ jwt: process.env.RC_JWT });
const leadStates = await ev.get(
"/api/v1/admin/accounts/{accountId}/campaignLeads/leadStates"
);
const systemDispositions = await ev.get(
"/api/v1/admin/accounts/{accountId}/campaignLeads/systemDispositions"
);
console.log(leadStates.data);
console.log(systemDispositions.data);
}
main().catch(console.error);
import os
from dotenv import load_dotenv
from ringcentral_engage_voice import RingCentralEngageVoice
load_dotenv()
ev = RingCentralEngageVoice(
os.environ["RC_CLIENT_ID"],
os.environ["RC_CLIENT_SECRET"],
)
ev.authorize(jwt=os.environ["RC_JWT"])
lead_states = ev.get(
"/api/v1/admin/accounts/{accountId}/campaignLeads/leadStates"
).json()
system_dispositions = ev.get(
"/api/v1/admin/accounts/{accountId}/campaignLeads/systemDispositions"
).json()
print(lead_states)
print(system_dispositions)
Results
The search response returns matching lead records and lead metadata. Use the returned lead IDs with lead actions when you need to reset, suppress, move, email, or delete a set of leads.