Custom Audiences API: The Developer Guide
Learn how to create, manage, and use Meta custom audiences programmatically. Covers customer lists, website audiences, lookalikes, and the Xylo audiences API.
What Are Custom Audiences?
Custom audiences let you target ads to specific groups of people based on data you already have. Instead of relying solely on Meta's interest and demographic targeting, you can upload your customer list, target website visitors, or reach people who engaged with your Instagram content.
There are four main types:
- Customer list audiences -- upload emails, phone numbers, or mobile advertiser IDs to match against Meta users
- Website audiences -- retarget people who visited specific pages on your site (requires the Meta Pixel)
- App activity audiences -- target users based on actions taken in your mobile app
- Engagement audiences -- reach people who interacted with your content on Facebook or Instagram
This guide focuses on creating and managing these audiences programmatically through the API.
Creating a Customer List Audience
The Raw Meta API Way
Creating a customer list audience with the raw API requires several steps:
# Step 1: Create the audience shell
curl -X POST "https://graph.facebook.com/v22.0/act_123456789/customaudiences" \
-d "name=Top Customers Q1 2026" \
-d "subtype=CUSTOM" \
-d "description=Customers with LTV above $500" \
-d "customer_file_source=USER_PROVIDED_ONLY" \
-d "access_token=EAABsbCS1..."
# Step 2: Hash and upload customer data
curl -X POST "https://graph.facebook.com/v22.0/AUDIENCE_ID/users" \
-H "Content-Type: application/json" \
-d '{
"payload": {
"schema": ["EMAIL", "PHONE", "FN", "LN"],
"data": [
["a1b2c3d4e5f6...", "9f8e7d6c5b4a...", "d4c3b2a19876...", "1a2b3c4d5e6f..."],
["f6e5d4c3b2a1...", "4a3b2c1d0e9f...", "6789abcdef01...", "fedcba987654..."]
]
}
}'
Every field must be SHA-256 hashed before upload. The schema array must match the order of fields in each data row. If you get the order wrong, Meta silently accepts the data but match rates plummet.
The Xylo Way
Xylo simplifies audience creation with a single request:
const response = await fetch("https://api.xyloapi.dev/v1/audiences", {
method: "POST",
headers: {
"x-api-key": process.env.XYLO_API_KEY!,
"x-ad-account": "act_123456789",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Top Customers Q1 2026",
type: "customer_list",
description: "Customers with LTV above $500",
customer_file_source: "user_provided_only",
customers: [
{ email: "customer@example.com", phone: "+15551234567", first_name: "Jane", last_name: "Doe" },
{ email: "buyer@example.com", phone: "+15559876543", first_name: "John", last_name: "Smith" }
]
}),
});
const { data: audience } = await response.json();
console.log(`Created audience: ${audience.id}, estimated size: ${audience.approximate_count}`);
Xylo handles the hashing, schema mapping, and batched upload internally. You send plain-text customer data (transmitted over HTTPS), and Xylo hashes it before sending to Meta.
Managing Audience Membership
Audiences are not static. As customers change status, you need to add and remove members.
Adding Members
await fetch(`https://api.xyloapi.dev/v1/audiences/${audienceId}/users`, {
method: "POST",
headers: {
"x-api-key": process.env.XYLO_API_KEY!,
"x-ad-account": "act_123456789",
"Content-Type": "application/json",
},
body: JSON.stringify({
customers: [
{ email: "new-customer@example.com", first_name: "Alice", last_name: "Johnson" }
]
}),
});
Removing Members
await fetch(`https://api.xyloapi.dev/v1/audiences/${audienceId}/users`, {
method: "DELETE",
headers: {
"x-api-key": process.env.XYLO_API_KEY!,
"x-ad-account": "act_123456789",
"Content-Type": "application/json",
},
body: JSON.stringify({
customers: [
{ email: "churned-customer@example.com" }
]
}),
});
Batch Syncing
For large customer lists, process in batches. Meta allows up to 10,000 records per API call:
const BATCH_SIZE = 5000;
async function syncAudience(audienceId: string, customers: Customer[]) {
for (let i = 0; i < customers.length; i += BATCH_SIZE) {
const batch = customers.slice(i, i + BATCH_SIZE);
await fetch(`https://api.xyloapi.dev/v1/audiences/${audienceId}/users`, {
method: "POST",
headers: {
"x-api-key": process.env.XYLO_API_KEY!,
"x-ad-account": "act_123456789",
"Content-Type": "application/json",
},
body: JSON.stringify({ customers: batch }),
});
console.log(`Synced ${Math.min(i + BATCH_SIZE, customers.length)} / ${customers.length}`);
}
}
Listing and Inspecting Audiences
// List all audiences
const response = await fetch("https://api.xyloapi.dev/v1/audiences", {
headers: {
"x-api-key": process.env.XYLO_API_KEY!,
"x-ad-account": "act_123456789",
},
});
const { data: audiences } = await response.json();
for (const audience of audiences) {
console.log(`${audience.name} (${audience.type}): ~${audience.approximate_count} users`);
}
Xylo returns a consistent audience object:
{
"data": [
{
"id": "23851234567890",
"name": "Top Customers Q1 2026",
"type": "customer_list",
"approximate_count": 12500,
"status": "ready",
"created_at": "2026-03-01T10:00:00Z",
"description": "Customers with LTV above $500"
},
{
"id": "23851234567891",
"name": "Website Visitors - Last 30 Days",
"type": "website",
"approximate_count": 45000,
"status": "ready",
"created_at": "2026-02-15T08:00:00Z"
}
]
}
Creating Lookalike Audiences
Lookalike audiences are one of Meta's most powerful targeting features. They find new people who are similar to your existing customers. For a detailed implementation guide, see our Lookalike Audiences guide.
Quick example through Xylo:
const response = await fetch("https://api.xyloapi.dev/v1/audiences", {
method: "POST",
headers: {
"x-api-key": process.env.XYLO_API_KEY!,
"x-ad-account": "act_123456789",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Lookalike - Top Customers 1%",
type: "lookalike",
source_audience_id: "23851234567890",
country: "US",
ratio: 0.01,
}),
});
The ratio parameter controls audience size: 0.01 (1%) is the most similar to your source audience, while 0.10 (10%) is broader but less precise.
Using Audiences in Ad Targeting
Once you have created an audience, use it as a targeting parameter when creating ad sets:
await fetch("https://api.xyloapi.dev/v1/ad-sets", {
method: "POST",
headers: {
"x-api-key": process.env.XYLO_API_KEY!,
"x-ad-account": "act_123456789",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Retargeting - Top Customers",
campaign_id: "120210123456789",
daily_budget: 50.00,
targeting: {
custom_audiences: [{ id: "23851234567890" }],
age_min: 18,
age_max: 65,
genders: [0], // 0 = all
},
status: "paused",
}),
});
Audience Strategy Patterns
Exclusion Audiences
Exclude existing customers from prospecting campaigns to avoid wasting spend:
targeting: {
excluded_custom_audiences: [{ id: "existing_customers_audience_id" }],
interests: [{ id: "6003139266461" }], // broad interest targeting
}
Layered Audiences
Combine custom audiences with demographic targeting for precision:
targeting: {
custom_audiences: [{ id: "website_visitors_30d" }],
age_min: 25,
age_max: 44,
genders: [2], // female
geo_locations: { countries: ["US"] },
}
Funnel-Based Audiences
Create audiences for each stage of your funnel:
| Audience | Source | Use Case |
|---|---|---|
| All website visitors (180 days) | Website pixel | Broad retargeting |
| Product page viewers (30 days) | Website pixel | Product interest |
| Cart abandoners (14 days) | Website pixel | High intent retargeting |
| Purchasers (365 days) | Customer list | Upsell / cross-sell |
| Purchasers (365 days) - excluded | Customer list | Exclude from prospecting |
| Lookalike - Purchasers 1% | Lookalike | Prospecting |
Data Freshness and Audience Size
A few important details about custom audiences:
- Minimum size. Meta requires at least 100 matched users before an audience can be used for targeting. For lookalikes, the source audience should ideally have 1,000+ matched users.
- Processing time. After uploading customer data, it takes 30 minutes to several hours for the audience to be fully populated.
- Match rates. Typical match rates for email-based uploads are 50-70%. Providing multiple identifiers (email + phone + name) improves match rates.
- Retention periods. Website and engagement audiences automatically remove users after the retention period expires (configurable, max 180 days for website, 365 days for engagement).
Getting Started
- Identify your audiences. Start with high-value segments: purchasers, high-LTV customers, recent website visitors.
- Upload via Xylo. Use the audiences API to create and populate customer list audiences.
- Set up retargeting. Create ad sets targeting your website visitor audiences.
- Build lookalikes. Create lookalike audiences from your best customer segments.
- Automate syncing. Set up a daily or weekly job to sync audience membership as your customer data changes.
For more on how audiences fit into AI-driven ad management, read our guide on building AI agents for ads. Check the API documentation for complete audience endpoint details.
Sign up for Xylo to get started with programmatic audience management.
Ready to simplify your ads API integration?
Get started with Xylo in minutes. One API key for every ad platform.