All docs
Start here
API basics
Agent setups
Resources
- Contacts
- Companies
- Lists
- Deals
- Tasks
- Notes
- Fields
- Quotes
- Stage Checklist Pipelines
- Sequences
- Sequence Lifecycle
- Inbox
- Meetings
- Appointments Management
- Voice & Dialer
- Skills (LLM + API)
- Workflows
- GTM Campaigns
- GTM Context
- GTM Knowledge Base
- Launch Helpers
- Landing Pages
- Intent & Signals
- Search
- Enrichment
- Assert / Upsert
- Agency Keys & Cross-Org Targeting
- CRM Syncs
- Audience Syncs
- Destinations
- Snippet
- Functions
Data pipeline
Webhooks
What's new
Audience Syncs
Mirror contact lists to ad platforms (Meta, LinkedIn, Google Ads, X) on a recurring schedule
Audience syncs push a graph8 audience (contact list) to an ad platform and keep it in sync on a cadence. graph8 supports four platforms: Meta (Facebook/Instagram custom audiences), LinkedIn (Matched Audiences), Google Ads (Customer Match), and X (Tailored Audiences).
Each sync config has a mode:
mirror- keep the platform audience exactly in sync with the source list (adds new members, removes dropped members).append_only- only add new members; never remove.
A worker re-runs each sync on its refresh_cadence_hours. You can also trigger a sync manually.
| Endpoint | Method | Description |
|---|---|---|
/audience-syncs | GET | List all sync configs for the org |
/audience-syncs | POST | Create a new sync config |
/audience-syncs/{id} | GET | Get a single sync config |
/audience-syncs/{id} | PATCH | Update a sync config |
/audience-syncs/{id} | DELETE | Soft delete a sync config |
/audience-syncs/{id}/trigger | POST | Manually trigger a sync run |
/audience-syncs/{id}/runs | GET | List recent sync runs |
/audience-syncs/{id}/errors | GET | List failed sync runs only |
For machine-readable schemas see the interactive API docs.
List Audience Syncs
GET /audience-syncs
Returns every sync config for the authenticated org.
Example
cURL
curl "https://be.graph8.com/api/v1/audience-syncs" \
-H "Authorization: Bearer $API_KEY" Python
response = requests.get(
f"{BASE_URL}/audience-syncs",
headers=HEADERS,
)
configs = response.json()["data"] Response
{
"data": [
{
"id": 12,
"audience_id": 5,
"platform": "meta",
"platform_audience_name": "Q2 Outbound - Mirror",
"mode": "mirror",
"refresh_cadence_hours": 24,
"is_active": true,
"status": "active",
"last_sync_at": "2026-04-15T08:00:00Z",
"created_at": "2026-04-01T10:00:00Z"
}
]
}
Create Audience Sync
POST /audience-syncs
Create a new sync config. Returns 409 Conflict if a config already exists for the same audience_id + platform.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
audience_id | integer | Yes | Source list ID (must be > 0) |
platform | string | Yes | One of meta, linkedin, google, x |
platform_audience_name | string | No | Display name on the ad platform (max 255) |
mode | string | No | mirror (default) or append_only |
refresh_cadence_hours | integer | No | 0-720, default 24 |
platform_config | object | No | Platform-specific config (e.g. ad account ID, OAuth scopes) |
suppression_list_ids | integer[] | No | Lists whose members should be excluded |
Example
cURL
curl -X POST "https://be.graph8.com/api/v1/audience-syncs" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"audience_id": 5,
"platform": "meta",
"platform_audience_name": "Q2 Outbound",
"mode": "mirror",
"refresh_cadence_hours": 24,
"platform_config": {"ad_account_id": "act_1234567890"}
}' Python
response = requests.post(
f"{BASE_URL}/audience-syncs",
headers=HEADERS,
json={
"audience_id": 5,
"platform": "meta",
"platform_audience_name": "Q2 Outbound",
"mode": "mirror",
"refresh_cadence_hours": 24,
"platform_config": {"ad_account_id": "act_1234567890"},
},
) Response 201 Created
Returns the same shape as a list item.
Errors
| Status | Meaning |
|---|---|
409 | A sync config already exists for this audience + platform |
422 | platform not in allowed set, or mode invalid |
Get Audience Sync
GET /audience-syncs/{config_id}
Returns a single sync config by ID.
Example
cURL
curl "https://be.graph8.com/api/v1/audience-syncs/12" \
-H "Authorization: Bearer $API_KEY" Errors
| Status | Meaning |
|---|---|
404 | Sync config not found |
Update Audience Sync
PATCH /audience-syncs/{config_id}
Partial update. Send only the fields you want to change.
Request Body
| Field | Type | Description |
|---|---|---|
mode | string | mirror or append_only |
refresh_cadence_hours | integer | 0-720 |
is_active | boolean | Pause/unpause without deleting |
suppression_list_ids | integer[] | Replace suppression list set |
Example
cURL
curl -X PATCH "https://be.graph8.com/api/v1/audience-syncs/12" \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d '{"is_active": false}' Delete Audience Sync
DELETE /audience-syncs/{config_id}
Soft delete. The platform audience is not removed from the ad platform - graph8 simply stops syncing.
Response
{ "data": { "status": "deleted", "id": 12 } }
Trigger Audience Sync
POST /audience-syncs/{config_id}/trigger
Run the sync immediately, outside of its scheduled cadence. Returns the sync result payload (members added/removed counts).
Example
cURL
curl -X POST "https://be.graph8.com/api/v1/audience-syncs/12/trigger" \
-H "Authorization: Bearer $API_KEY" Errors
| Status | Meaning |
|---|---|
500 | Underlying ad platform returned an error - check /runs or /errors for the message |
List Sync Runs
GET /audience-syncs/{config_id}/runs
Returns recent runs for a config (success and failure both).
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 20 | Max runs to return (1-100) |
Response
{
"data": [
{
"id": 4521,
"started_at": "2026-04-15T08:00:00Z",
"finished_at": "2026-04-15T08:00:14Z",
"status": "success",
"members_added": 12,
"members_removed": 3,
"total_members": 1450,
"error_message": null
}
]
}
List Sync Errors
GET /audience-syncs/{config_id}/errors
Same shape as /runs, filtered to status = "failed". Use this when surfacing failures in your dashboard.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
limit | integer | 20 | Max errors to return (1-100) |
Response
{
"data": [
{
"id": 4520,
"started_at": "2026-04-15T07:30:00Z",
"error_message": "Meta API: invalid access token",
"details": { "config_id": 12, "status": "failed" }
}
]
}