GET /v1/campaigns
Every campaign carries what was asked for and what is actually happening: effectiveStatus says whether Meta is reviewing, the budget is spent, or delivery is running.
The request
curl "https://api-sia54tw5uq-uc.a.run.app/v1/campaigns" \
-H "x-api-key: trp_..."
The response
{
"data": [
{
"id": "cmp_4b7e02",
"object": "campaign",
"name": "Mariage - printemps",
"objective": "LEAD_GENERATION",
"status": "ACTIVE",
"effectiveStatus": {
"key": "running",
"reason": null,
"action": null
},
"budget": {
"currency": "EUR",
"amountCents": 45000
},
"destination": "LANDING"
}
],
"nextCursor": null
}
POST /v1/campaigns/cmp_4b7e02/activate
A transition is an action, never a field to edit. The response says immediately which real state the campaign is in.
The request
curl -X POST "https://api-sia54tw5uq-uc.a.run.app/v1/campaigns/cmp_4b7e02/activate" \
-H "x-api-key: trp_..."
The response
{
"data": {
"id": "cmp_4b7e02",
"object": "campaign",
"status": "ACTIVE",
"effectiveStatus": {
"key": "reviewing",
"reason": null,
"action": null
}
}
}
GET /v1/stats?level=campaign
Meta spend, net cost, leads received, impressions and reach, by day, at business, campaign or ad level.
The request
curl "https://api-sia54tw5uq-uc.a.run.app/v1/stats?level=campaign" \
-H "x-api-key: trp_..."
The response
{
"data": [
{
"id": "cmp_4b7e02",
"dayString": "2026-10-05",
"currency": "EUR",
"metaSpend": 41.2,
"netCost": 48.6,
"forms": 9,
"impressions": 7312,
"linkClicks": 164,
"reach": 5890
}
],
"totals": {
"forms": 9,
"netCost": 48.6
},
"range": {
"level": "campaign",
"sinceDayString": "2026-10-05",
"untilDayString": "2026-10-05",
"ids": [
"cmp_4b7e02"
]
}
}
POST /v1/campaigns/cmp_4b7e02/adGenerations
The work is asynchronous: you get a jobId to follow, and the ad ids as they arrive. The Idempotency-Key header makes the call safe to replay.
The request
curl -X POST "https://api-sia54tw5uq-uc.a.run.app/v1/campaigns/cmp_4b7e02/adGenerations" \
-H "x-api-key: trp_..." \
-H "Idempotency-Key: 7f3a-2c91"
The response
{
"data": {
"id": "agn_19d4c7",
"object": "ad_generation",
"campaignId": "cmp_4b7e02",
"status": "running",
"outputNumber": 8,
"adIds": [],
"jobId": "job_61ba8f"
}
}
POST /v1/landings/lnd_7c25e1/publish
The page goes live at its own address, ready to take the campaign's clicks.
The request
curl -X POST "https://api-sia54tw5uq-uc.a.run.app/v1/landings/lnd_7c25e1/publish" \
-H "x-api-key: trp_..."
The response
{
"data": {
"id": "lnd_7c25e1",
"object": "landing",
"status": "live",
"url": "https://exemple.fr/mariage-printemps",
"publishedAt": "2026-10-05T11:02:47Z"
}
}
GET /v1/forms?campaignId=cmp_4b7e02
Everyone who filled in a form, with the campaign they came from. isOrganic marks the ones that came from a share outside targeting.
The request
curl "https://api-sia54tw5uq-uc.a.run.app/v1/forms?campaignId=cmp_4b7e02" \
-H "x-api-key: trp_..."
The response
{
"data": [
{
"id": "frm_8f2c1a",
"object": "form",
"campaignId": "cmp_4b7e02",
"firstName": "Camille",
"lastName": "Rousseau",
"email": "camille@example.fr",
"phoneNumberE164": "+33612345678",
"isOrganic": false,
"createdAt": "2026-10-05T09:14:22Z"
}
],
"nextCursor": null
}
GET /v1/contacts
The same person converges on one identity however many forms they filled in: identityKind says on what.
The request
curl "https://api-sia54tw5uq-uc.a.run.app/v1/contacts" \
-H "x-api-key: trp_..."
The response
{
"data": [
{
"id": "ctc_2ae910",
"object": "contact",
"firstName": "Camille",
"lastName": "Rousseau",
"emails": [
"camille@example.fr"
],
"campaignIds": [
"cmp_4b7e02"
],
"formIds": [
"frm_8f2c1a"
],
"identityKind": "email",
"lastInteractionAt": "2026-10-05T09:14:22Z"
}
],
"nextCursor": null
}