Documentation Index Fetch the complete documentation index at: https://docs.firstquadrant.ai/llms.txt
Use this file to discover all available pages before exploring further.
The FirstQuadrant API provides powerful filtering capabilities to help you find exactly the data you need. This guide covers search queries, advanced filters, and field selection.
Quick start
# Search contacts by name or email
curl "https://api.us.firstquadrant.ai/v5/contacts?query=john" \
-H "Authorization: Bearer YOUR_API_KEY"
# Filter by email domain
curl "https://api.us.firstquadrant.ai/v5/contacts?filter.email.contains=@acme.com" \
-H "Authorization: Bearer YOUR_API_KEY"
# Select specific fields
curl "https://api.us.firstquadrant.ai/v5/contacts?select[]=id&select[]=email&select[]=firstName" \
-H "Authorization: Bearer YOUR_API_KEY"
Search with query parameter
The query parameter performs full-text search across relevant fields:
# Search contacts
GET /v5/contacts?query=john
# Search campaigns
GET /v5/campaigns?query=welcome
# Combine with other filters
GET /v5/contacts?query=john & filter.tags.has =customer
The search is case-insensitive and searches across multiple fields depending on the resource type.
Advanced filtering
Filter syntax
Filters use the format: filter.field.operator=value
# Single filter
filter.email.equals =john@example.com
# Multiple filters (AND logic)
filter.firstName.equals =John & filter.lastName.contains =Doe
# Nested field filters
filter.customProperties.industry.equals =technology
Available operators
String operators
Operator Description Example equalsExact match (case-sensitive) filter.email.equals=john@example.comnotNot equal to filter.status.not=inactivecontainsContains substring filter.email.contains=@gmail.comstartsWithStarts with string filter.name.startsWith=JohnendsWithEnds with string filter.email.endsWith=.eduinValue in array filter.status.in=active,pendingnotInValue not in array filter.status.notIn=deleted,archived
Number operators
Operator Description Example equalsEqual to filter.score.equals=100notNot equal to filter.score.not=0gtGreater than filter.score.gt=50gteGreater than or equal filter.score.gte=50ltLess than filter.score.lt=100lteLess than or equal filter.score.lte=100inValue in array filter.priority.in=1,2,3
Date operators
Operator Description Example equalsExact date match filter.createdAt.equals=2024-01-15gtAfter date filter.createdAt.gt=2024-01-01gteOn or after date filter.lastActivityAt.gte=2024-01-01ltBefore date filter.createdAt.lt=2024-12-31lteOn or before date filter.updatedAt.lte=2024-12-31
Array operators
Operator Description Example hasArray contains value filter.tags.has=customerhasEveryArray contains all values filter.tags.hasEvery=customer,viphasSomeArray contains any value filter.tags.hasSome=lead,prospectisEmptyArray is empty filter.tags.isEmpty=true
Boolean operators
Operator Description Example equalsBoolean value filter.isActive.equals=truenotOpposite boolean filter.isVerified.not=true
Filtering examples
JavaScript
Python
TypeScript
// Advanced filtering with multiple conditions
const params = new URLSearchParams ({
"filter.status.equals" : "active" ,
"filter.createdAt.gte" : "2024-01-01" ,
"filter.tags.hasSome" : "customer,lead" ,
"filter.customProperties.score.gt" : "50" ,
query: "john" ,
});
const response = await fetch ( `https://api.us.firstquadrant.ai/v5/contacts? ${ params } ` , {
headers: {
Authorization: "Bearer YOUR_API_KEY" ,
"FirstQuadrant-Organization-ID" : "org_YOUR_ORG_ID" ,
},
});
const contacts = await response . json ();
Field selection
Use the select[] parameter to specify which fields to include in the response:
Basic field selection
# Select only id, email, and name fields
GET /v5/contacts?select[]=id &select[]=email&select[]=firstName&select[]=lastName
# Response includes only selected fields
[
{
"id" : "con_abc123" ,
"email" : "john@example.com" ,
"firstName" : "John" ,
"lastName" : "Doe"
}
]
Nested field selection
Use dot notation for nested fields:
# Select nested fields
GET /v5/contacts?select[]=id &select[]=email&select[]=company.name&select[]=customProperties.score
# Response
[
{
"id" : "con_abc123" ,
"email" : "john@example.com" ,
"company" : {
"name" : "Acme Corp"
},
"customProperties" : {
"score" : 85
}
}
]
Field selection reduces payload size and improves performance:
// Fetch only essential fields for a list view
const listParams = new URLSearchParams ({
"select[]" : [ "id" , "email" , "firstName" , "lastName" , "company.name" ],
limit: "100" ,
});
// Fetch all fields for a detail view
const detailResponse = await fetch ( `https://api.us.firstquadrant.ai/v5/contacts/ ${ contactId } ` );
Complex filter combinations
Example 1: Sales qualified leads
Find high-value leads from specific industries:
GET /v5/contacts?
filter.customProperties.leadScore.gte =80 &
filter.customProperties.industry.in =technology,finance,healthcare &
filter.tags.has =qualified &
filter.lastActivityAt.gte =2024-01-01 &
orderBy = customProperties.leadScore &
sort = desc
Example 2: Email campaign targets
Find contacts for an email campaign:
GET /v5/contacts?
filter.email.endsWith =.com &
filter.emailOptOut.equals = false &
filter.tags.hasEvery =customer,active &
filter.customProperties.lastPurchaseDate.gte =2023-01-01 &
select[] =id &
select[] =email &
select[] =firstName
Example 3: Data cleanup
Find potentially duplicate contacts:
GET /v5/contacts?
filter.email.contains =@gmail.com &
filter.createdAt.gte =2024-01-01 &
orderBy = email &
sort = asc
Special filters
Null and empty values
# Find contacts without a company
filter.companyId.equals =null
# Find contacts with no tags
filter.tags.isEmpty = true
# Find contacts with any tags
filter.tags.isEmpty = false
Date ranges
// Contacts created this month
const startOfMonth = new Date ();
startOfMonth . setDate ( 1 );
startOfMonth . setHours ( 0 , 0 , 0 , 0 );
const params = new URLSearchParams ({
"filter.createdAt.gte" : startOfMonth . toISOString (),
"filter.createdAt.lt" : new Date (). toISOString (),
});
Pattern matching
# Email domains
filter.email.endsWith =@company.com
# Phone numbers with area code
filter.phone.startsWith =+1415
# Names containing substring
filter.firstName.contains =john
Best practices
Use indexes : Filter on indexed fields (id, email, createdAt) for better performance
Limit results : Always use pagination with filters
Select fields : Only request fields you need
Combine wisely : Too many filters can slow queries
// ❌ Inefficient: Fetching all fields for large dataset
const response = await fetch ( "/v5/contacts?limit=100" );
// ✅ Efficient: Select only needed fields with filters
const response = await fetch (
"/v5/contacts?" + "filter.status.equals=active&" + "select[]=id&select[]=email&select[]=name&" + "limit=50" ,
);
Common use cases
1. Segmentation
// VIP customers in California
const vipCA = {
"filter.tags.has" : "vip" ,
"filter.customProperties.state.equals" : "CA" ,
"filter.customProperties.lifetimeValue.gt" : "10000" ,
};
2. Time-based queries
// Contacts inactive for 90 days
const ninetyDaysAgo = new Date ();
ninetyDaysAgo . setDate ( ninetyDaysAgo . getDate () - 90 );
const inactive = {
"filter.lastActivityAt.lt" : ninetyDaysAgo . toISOString (),
"filter.status.equals" : "active" ,
};
3. Data export
// Export specific fields with filters
async function exportContacts ( filters ) {
const params = new URLSearchParams ({
... filters ,
"select[]" : [ "id" , "email" , "firstName" , "lastName" , "createdAt" ],
limit: "100" ,
});
// Paginate through all results
let allContacts = [];
let hasMore = true ;
let cursor = null ;
while ( hasMore ) {
if ( cursor ) params . set ( "startingAfter" , cursor );
const response = await fetch ( `/v5/contacts? ${ params } ` );
const page = await response . json ();
allContacts = allContacts . concat ( page );
hasMore = page . length === 100 ;
if ( hasMore ) cursor = page [ page . length - 1 ]. id ;
}
return allContacts ;
}
Troubleshooting
Common issues
Invalid operator : Ensure the operator is valid for the field type
Field not found : Check field names and nested paths
Type mismatch : Ensure filter values match the field type
Special characters : URL-encode special characters in filter values
Debugging tips
// Log the exact URL being called
const params = new URLSearchParams ( filters );
console . log ( `API URL: https://api.us.firstquadrant.ai/v5/contacts? ${ params } ` );
// Check response headers for debugging info
const response = await fetch ( url );
console . log ( "Request ID:" , response . headers . get ( "X-Request-Id" ));