Référence de l'API
Copilote Meta
L'état du copilote Meta sur le compte publicitaire de l'entreprise, ses alertes (réactions perdues, refus, pics de dépenses) et l'arrêt d'urgence. Le mandat ne se configure que dans l'application.
Endpoints
-
GET
/meta-copilotObtenir l'état du copilote -
PATCH
/meta-copilot/mandateMettre à jour le mandat du copilote -
GET
/meta-copilot/alertsLister les alertes du copilote -
POST
/meta-copilot/stopExécuter l'arrêt d'urgence -
GET
/meta-copilot/opportunitiesLister les opportunités du copilote -
POST
/meta-copilot/opportunities/{opportunity}/acceptLaisser le copilote agir sur une opportunité -
POST
/meta-copilot/opportunities/{opportunity}/dismissÉcarter une opportunité -
GET
/meta-copilot/approvalsLister les propositions du copilote -
POST
/meta-copilot/approvals/{approval}/approveApprouver une proposition -
POST
/meta-copilot/approvals/{approval}/rejectRejeter une proposition -
GET
/meta-copilot/timelineObtenir la chronologie -
GET
/meta-copilot/digestsLister les bilans hebdomadaires -
GET
/meta-copilot/briefingsLister les briefings du matin -
GET
/meta-copilot/revenueObtenir le pont de revenus -
GET
/meta-copilot/statsObtenir les chiffres des campagnes -
GET
/meta-copilot/crewObtenir l’équipe du copilote -
GET
/meta-copilot/valueObtenir ce que le copilote a rapporté -
GET
/meta-copilot/milestonesLister les jalons -
GET
/meta-copilot/benchmarkVous face aux entreprises comparables -
GET
/meta-copilot/seasonalityObtenir le calendrier saisonnier -
POST
/meta-copilot/tips/{tip}/respondRépondre au conseil du jour -
GET
/meta-copilot/competitorsLister les concurrents suivis -
POST
/meta-copilot/competitorsSuivre un concurrent -
DELETE
/meta-copilot/competitors/{competitor}Ne plus suivre un concurrent -
POST
/meta-copilot/competitors/ads/{ad}/variantCréer une variante sur une publicité d'un concurrent -
GET
/meta-copilot/ads/{ad}/previewAperçu d’une publicité -
GET
/meta-copilot/imagesLister les images de la bibliothèque -
GET
/meta-copilot/starterConsulter l’état d’une nouvelle campagne -
PUT
/meta-copilot/starter/intakeEnregistrer les réponses aux questions de départ -
POST
/meta-copilot/starter/proposeProposer une nouvelle campagne -
POST
/meta-copilot/imagesTéléverser une image -
DELETE
/meta-copilot/images/{image}Supprimer une image
Obtenir l'état du copilote
/api/v1/meta-copilot
Le mode (désactivé, ombre, copilote ou autopilote), le profil, l'objectif, le budget mensuel et les compteurs d'alertes ouvertes et de propositions en attente. 404 si l'entreprise n'a pas de compte publicitaire Meta.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot",
"ad_account_id": "act_123456789",
"ad_account_name": "Veranda BV",
"currency": "EUR",
"mode": "shadow",
"profile": "standard",
"goal_metric": "cost_per_quote",
"goal_value": "45.00",
"monthly_budget": "1500.00",
"autonomous_classes": [],
"open_alerts": 1,
"pending_proposals": 0,
"enabled_at": null,
"tier": "autopilot",
"ad_budget_ceiling": "7500.00",
"on_expiry": "lapse",
"stopped_at": null,
"connection_active": true,
"running": {
"state": "running",
"since": null,
"kind": "operational"
}
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Mettre à jour le mandat du copilote
/api/v1/meta-copilot/mandate
Définit le profil, l’objectif, le budget mensuel, le plafond de budget journalier, les jours de silence, la base pour les données clients et si une proposition non jugée est appliquée quand même après l’échéance. Si le mandat devient PLUS LARGE (plus de classes autonomes, plafond journalier relevé ou supprimé, moins de jours de silence, données clients autorisées, propositions expirées appliquées), confirm_widening: true est obligatoire ; sans cette confirmation, l’appel échoue avec 422 validation_failed et l’explication. Réduire ne demande pas de confirmation. Le budget mensuel ne peut pas dépasser le plafond publicitaire du palier (ad_budget_ceiling). Chaque élargissement apparaît comme alerte dans la chronologie.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
profile
obligatoire
|
string | Le profil de mandat : careful, standard ou broad. l'une des valeurs : careful, standard, broad |
goal_metric
facultatif
|
string | Ce que le copilote optimise. peut être vide (null) · l'une des valeurs : cost_per_quote, cost_per_lead, cost_per_conversion, roas |
goal_value
facultatif
|
number | La valeur cible, en texte à deux décimales. peut être vide (null) · de 0 à 1000000 |
monthly_budget
facultatif
|
number | L'accord de budget publicitaire mensuel. peut être vide (null) · de 0 à 10000000 |
max_daily_budget_euros
facultatif
|
number | Le plafond de budget journalier par campagne en euros ; vide = pas de plafond propre. peut être vide (null) · de 1 à 1000000 |
quiet_days
facultatif
|
array | Les jours de silence (monday … sunday) : le copilote ne change alors rien seul et tout passe en approbation. |
crm_audience_allowed
facultatif
|
boolean | Si les adresses e-mail et numéros de téléphone hachés des clients peuvent aller chez Meta pour les audiences. Omis = le choix enregistré reste. |
on_expiry
facultatif
|
string | Ce qu’il advient d’une proposition non jugée à temps : lapse (expire, par défaut) ou apply (appliquée quand même après l’échéance, dans toutes les limites fixes). l'une des valeurs : lapse, apply |
confirm_widening
facultatif
|
boolean | true pour confirmer en conscience un élargissement du mandat. Obligatoire dès que la saisie rend le mandat plus large qu’aujourd’hui. |
notes
facultatif
|
string | Une note pour le copilote en langage courant, par exemple « ne jamais faire de publicité le dimanche ». peut être vide (null) · au maximum 2000 caractères |
Exemple de requête
curl -X PATCH "https://app.klantly.com/api/v1/meta-copilot/mandate" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"profile": "standard",
"goal_metric": "cost_per_quote",
"goal_value": 45,
"monthly_budget": 1500,
"quiet_days": [
"sunday"
],
"on_expiry": "lapse"
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('PATCH', 'meta-copilot/mandate', [
'json' => [
'profile' => 'standard',
'goal_metric' => 'cost_per_quote',
'goal_value' => 45,
'monthly_budget' => 1500,
'quiet_days' => [
0 => 'sunday',
],
'on_expiry' => 'lapse',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/mandate', {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"profile": "standard",
"goal_metric": "cost_per_quote",
"goal_value": 45,
"monthly_budget": 1500,
"quiet_days": [
"sunday"
],
"on_expiry": "lapse"
}),
});
const { data } = await response.json();import os
import requests
response = requests.patch(
"https://app.klantly.com/api/v1/meta-copilot/mandate",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
json={
"profile": "standard",
"goal_metric": "cost_per_quote",
"goal_value": 45,
"monthly_budget": 1500,
"quiet_days": [
"sunday"
],
"on_expiry": "lapse"
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot",
"ad_account_id": "act_123456789",
"ad_account_name": "Veranda BV",
"currency": "EUR",
"mode": "shadow",
"profile": "standard",
"goal_metric": "cost_per_quote",
"goal_value": "45.00",
"monthly_budget": "1500.00",
"autonomous_classes": [],
"open_alerts": 1,
"pending_proposals": 0,
"enabled_at": null,
"tier": "autopilot",
"ad_budget_ceiling": "7500.00",
"on_expiry": "lapse",
"stopped_at": null,
"connection_active": true,
"running": {
"state": "running",
"since": null,
"kind": "operational"
}
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable.
Lister les alertes du copilote
/api/v1/meta-copilot/alerts
Les alertes des surveillants et du suivi d'engagement, les plus récentes d'abord. Filtre par statut ou urgence. Titre et détail dans la langue d'Accept-Language.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit
|
integer | Nombre de résultats par page. de 1 à 100 · par défaut : 50 |
cursor
|
string | Le next_cursor ou prev_cursor de meta dans la réponse précédente. |
filter[status]
|
string | Uniquement les alertes avec ce statut : open ou resolved. l'une des valeurs : open, resolved |
filter[severity]
|
string | Uniquement les alertes avec cette urgence : info, warning ou critical. l'une des valeurs : info, warning, critical |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/alerts?filter[status]=open" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/alerts', [
'query' => [
'filter[status]' => 'open',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/alerts?filter[status]=open', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/alerts",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"filter[status]": "open"
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "meta_copilot_alert",
"id": "4821",
"kind": "engagement_post_replaced",
"severity": "critical",
"status": "open",
"title": "Advertentie \"Veranda zomer\" hangt aan een andere post: reacties en likes lopen niet meer mee",
"detail": "De post waarop 143 reacties, 27 opmerkingen en 9 keer delen stonden, wordt niet meer geadverteerd.",
"cause": "external",
"target_id": "120210000000000001",
"occurrences": 1,
"first_seen_at": null,
"last_seen_at": null,
"resolved_at": null,
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
Exécuter l'arrêt d'urgence
/api/v1/meta-copilot/stop
Désactive le copilote : les propositions et les opportunités ouvertes sont retirées et les règles qu'il a installées chez Meta sont désactivées. Les campagnes continuent telles qu'elles sont. 409 conflict si le copilote est déjà désactivé.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/stop" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/stop', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/stop', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/stop",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot",
"ad_account_id": "act_123456789",
"ad_account_name": "Veranda BV",
"currency": "EUR",
"mode": "shadow",
"profile": "standard",
"goal_metric": "cost_per_quote",
"goal_value": "45.00",
"monthly_budget": "1500.00",
"autonomous_classes": [],
"open_alerts": 1,
"pending_proposals": 0,
"enabled_at": null,
"tier": "autopilot",
"ad_budget_ceiling": "7500.00",
"on_expiry": "lapse",
"stopped_at": null,
"connection_active": true,
"running": {
"state": "running",
"since": null,
"kind": "operational"
}
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Lister les opportunités du copilote
/api/v1/meta-copilot/opportunities
Ce que le moteur d'opportunités et le copilote lui-même ont trouvé : dépenses gaspillées, publicités usées, audiences saturées, concentration du budget, placements sans résultat, devis jamais gagnés, un entonnoir qui décroche, un CPL au-dessus de la médiane Klantly. Les plus récentes d'abord ; tous les statuts par défaut. Titre et explication dans la langue d'Accept-Language.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit
|
integer | Nombre de résultats par page. de 1 à 100 · par défaut : 50 |
cursor
|
string | Le next_cursor ou prev_cursor de meta dans la réponse précédente. |
filter[status]
|
string | Uniquement les opportunités avec ce statut : open, accepted, done, dismissed ou expired. l'une des valeurs : open, accepted, done, dismissed, expired |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/opportunities?filter[status]=open" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/opportunities', [
'query' => [
'filter[status]' => 'open',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/opportunities?filter[status]=open', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/opportunities",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"filter[status]": "open"
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "meta_copilot_opportunity",
"id": "318",
"source": "signal",
"kind": "wasted_spend",
"status": "open",
"title": "\"Retargeting winter\" gaf € 184,20 uit zonder één conversie",
"body": "In de laatste 30 dagen is er € 184,20 besteed en zijn er 212 klikken geweest, maar geen enkele conversie.",
"impact_cents": 18420,
"confidence": "high",
"reversible": true,
"actionable": true,
"reuse_post": null,
"image_id": null,
"target_level": "adset",
"target_id": "120210000000000001",
"target_name": "Retargeting winter",
"dismissed_reason": null,
"action_id": null,
"variant": {
"reference_ad_id": "120210000000000009",
"headline": "Veranda op maat, binnen 4 weken geplaatst",
"primary_text": "Langer buiten zitten zonder gedoe? Onze aluminium veranda wordt op maat gemaakt en binnen vier weken geplaatst. Vraag vandaag een vrijblijvende offerte aan.",
"description": "Op maat gemaakt",
"cta_type": "GET_QUOTE"
},
"blueprint": {
"branch": "veranda",
"city": "Nijmegen",
"radius_km": 40,
"age_min": 30,
"age_max": 65,
"daily_budget_cents": 1500,
"has_pixel": true,
"landing_url": "https://configurator.klantly.com/offerte-aanvragen/01k7x?utm_source=facebook",
"image_id": "12",
"headline": "Veranda op maat van Veranda Boys",
"primary_text": "Langer buiten zitten, ook in het najaar? Veranda Boys maakt veranda's op maat. Vraag vrijblijvend een offerte aan.",
"description": "Vrijblijvende offerte",
"cta_type": "GET_QUOTE",
"peer_accounts": 7,
"peer_median_cpl": "31.20"
},
"decided_at": null,
"expires_at": null,
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
Laisser le copilote agir sur une opportunité
/api/v1/meta-copilot/opportunities/{opportunity}/accept
« Laisser le copilote s'en occuper. » Si l'opportunité porte une action et que le copilote n'est pas en mode ombre, l'action est appliquée aussitôt dans les limites du mandat ; sinon elle devient la prochaine étape de la stratégie. 409 conflict si l'opportunité n'est plus ouverte.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
opportunity obligatoire |
string | L'id de l'opportunité. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/opportunities/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/accept" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/opportunities/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/accept', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/opportunities/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/accept', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/opportunities/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/accept",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_opportunity",
"id": "318",
"source": "signal",
"kind": "wasted_spend",
"status": "open",
"title": "\"Retargeting winter\" gaf € 184,20 uit zonder één conversie",
"body": "In de laatste 30 dagen is er € 184,20 besteed en zijn er 212 klikken geweest, maar geen enkele conversie.",
"impact_cents": 18420,
"confidence": "high",
"reversible": true,
"actionable": true,
"reuse_post": null,
"image_id": null,
"target_level": "adset",
"target_id": "120210000000000001",
"target_name": "Retargeting winter",
"dismissed_reason": null,
"action_id": null,
"variant": {
"reference_ad_id": "120210000000000009",
"headline": "Veranda op maat, binnen 4 weken geplaatst",
"primary_text": "Langer buiten zitten zonder gedoe? Onze aluminium veranda wordt op maat gemaakt en binnen vier weken geplaatst. Vraag vandaag een vrijblijvende offerte aan.",
"description": "Op maat gemaakt",
"cta_type": "GET_QUOTE"
},
"blueprint": {
"branch": "veranda",
"city": "Nijmegen",
"radius_km": 40,
"age_min": 30,
"age_max": 65,
"daily_budget_cents": 1500,
"has_pixel": true,
"landing_url": "https://configurator.klantly.com/offerte-aanvragen/01k7x?utm_source=facebook",
"image_id": "12",
"headline": "Veranda op maat van Veranda Boys",
"primary_text": "Langer buiten zitten, ook in het najaar? Veranda Boys maakt veranda's op maat. Vraag vrijblijvend een offerte aan.",
"description": "Vrijblijvende offerte",
"cta_type": "GET_QUOTE",
"peer_accounts": 7,
"peer_median_cpl": "31.20"
},
"decided_at": null,
"expires_at": null,
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Écarter une opportunité
/api/v1/meta-copilot/opportunities/{opportunity}/dismiss
Avec self=true, vous indiquez que vous vous en occupez vous-même ; sinon c'est « pas pertinent ». La raison est transmise au copilote comme apprentissage, et la même opportunité reste muette trente jours. 409 conflict si l'opportunité n'est plus ouverte.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
opportunity obligatoire |
string | L'id de l'opportunité. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/opportunities/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/dismiss" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f" \
-d '{
"reason": "Deze campagne stopt eind van de maand toch.",
"self": false
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/opportunities/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/dismiss', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
'json' => [
'reason' => 'Deze campagne stopt eind van de maand toch.',
'self' => false,
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/opportunities/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/dismiss', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
body: JSON.stringify({
"reason": "Deze campagne stopt eind van de maand toch.",
"self": false
}),
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/opportunities/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/dismiss",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
json={
"reason": "Deze campagne stopt eind van de maand toch.",
"self": False
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_opportunity",
"id": "318",
"source": "signal",
"kind": "wasted_spend",
"status": "open",
"title": "\"Retargeting winter\" gaf € 184,20 uit zonder één conversie",
"body": "In de laatste 30 dagen is er € 184,20 besteed en zijn er 212 klikken geweest, maar geen enkele conversie.",
"impact_cents": 18420,
"confidence": "high",
"reversible": true,
"actionable": true,
"reuse_post": null,
"image_id": null,
"target_level": "adset",
"target_id": "120210000000000001",
"target_name": "Retargeting winter",
"dismissed_reason": null,
"action_id": null,
"variant": {
"reference_ad_id": "120210000000000009",
"headline": "Veranda op maat, binnen 4 weken geplaatst",
"primary_text": "Langer buiten zitten zonder gedoe? Onze aluminium veranda wordt op maat gemaakt en binnen vier weken geplaatst. Vraag vandaag een vrijblijvende offerte aan.",
"description": "Op maat gemaakt",
"cta_type": "GET_QUOTE"
},
"blueprint": {
"branch": "veranda",
"city": "Nijmegen",
"radius_km": 40,
"age_min": 30,
"age_max": 65,
"daily_budget_cents": 1500,
"has_pixel": true,
"landing_url": "https://configurator.klantly.com/offerte-aanvragen/01k7x?utm_source=facebook",
"image_id": "12",
"headline": "Veranda op maat van Veranda Boys",
"primary_text": "Langer buiten zitten, ook in het najaar? Veranda Boys maakt veranda's op maat. Vraag vrijblijvend een offerte aan.",
"description": "Vrijblijvende offerte",
"cta_type": "GET_QUOTE",
"peer_accounts": 7,
"peer_median_cpl": "31.20"
},
"decided_at": null,
"expires_at": null,
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Lister les propositions du copilote
/api/v1/meta-copilot/approvals
Les propositions en attente d'une décision (par défaut filter[status]=proposed), ou avec un filtre les intentions du mode ombre et ce qui a été appliqué, écarté, expiré ou échoué. Sans payload et sans nom de collaborateur.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit
|
integer | Nombre de résultats par page. de 1 à 100 · par défaut : 50 |
cursor
|
string | Le next_cursor ou prev_cursor de meta dans la réponse précédente. |
filter[status]
|
string | Uniquement les propositions avec ce statut : proposed, simulated, applied, dismissed, expired ou failed. Sans filtre : proposed. l'une des valeurs : proposed, simulated, applied, dismissed, expired, failed |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/approvals?filter[status]=proposed" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/approvals', [
'query' => [
'filter[status]' => 'proposed',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/approvals?filter[status]=proposed', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/approvals",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"filter[status]": "proposed"
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "meta_copilot_approval",
"id": "2077",
"status": "proposed",
"action_type": "adjust_budget",
"target_level": "adset",
"target_id": "120210000000000001",
"target_name": "Retargeting winter",
"title": "Budget van \"Retargeting winter\" verlagen van € 40 naar € 30 per dag",
"rationale": "De kosten per offerte liggen hier 60% boven het accountgemiddelde.",
"risk": "low",
"impact_estimate_cents": 30000,
"change": {
"kind": "budget",
"level": "adset",
"manual": false,
"from_cents": 4000,
"to_cents": 3000,
"placements": [
"audience_network"
],
"devices": [
"mobile"
],
"min": 30,
"max": 65,
"genders": [
"female"
],
"audience_name": null,
"headline": null,
"days": 14,
"template": null,
"purpose": null,
"percent": 1,
"country": "NL",
"strategy": "cost_cap",
"cap_cents": null,
"daily_budget_cents": null
},
"simulated": false,
"reuse_post": null,
"image_id": null,
"approval_deadline_at": null,
"applied_at": null,
"outcome": null,
"error": null,
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
Approuver une proposition
/api/v1/meta-copilot/approvals/{approval}/approve
Applique la proposition chez Meta, dans le mandat du compte. Uniquement pour une proposition au statut proposed ; sinon 409 conflict. En mode ombre, l’exécuteur refuse. Sur une variante d’annonce avec le même texte que l’original, reuse_post choisit si la publication existante est réutilisée (true par défaut).
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
approval obligatoire |
string | L'id de la proposition. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/approvals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/approve" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/approvals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/approve', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/approvals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/approve', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/approvals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/approve",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_approval",
"id": "2077",
"status": "proposed",
"action_type": "adjust_budget",
"target_level": "adset",
"target_id": "120210000000000001",
"target_name": "Retargeting winter",
"title": "Budget van \"Retargeting winter\" verlagen van € 40 naar € 30 per dag",
"rationale": "De kosten per offerte liggen hier 60% boven het accountgemiddelde.",
"risk": "low",
"impact_estimate_cents": 30000,
"change": {
"kind": "budget",
"level": "adset",
"manual": false,
"from_cents": 4000,
"to_cents": 3000,
"placements": [
"audience_network"
],
"devices": [
"mobile"
],
"min": 30,
"max": 65,
"genders": [
"female"
],
"audience_name": null,
"headline": null,
"days": 14,
"template": null,
"purpose": null,
"percent": 1,
"country": "NL",
"strategy": "cost_cap",
"cap_cents": null,
"daily_budget_cents": null
},
"simulated": false,
"reuse_post": null,
"image_id": null,
"approval_deadline_at": null,
"applied_at": null,
"outcome": null,
"error": null,
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Rejeter une proposition
/api/v1/meta-copilot/approvals/{approval}/reject
Passe la proposition (ou une intention du mode ombre) à dismissed. Rien ne change chez Meta.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
approval obligatoire |
string | L'id de la proposition. |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/approvals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/reject" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/approvals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/reject', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/approvals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/reject', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/approvals/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/reject",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_approval",
"id": "2077",
"status": "proposed",
"action_type": "adjust_budget",
"target_level": "adset",
"target_id": "120210000000000001",
"target_name": "Retargeting winter",
"title": "Budget van \"Retargeting winter\" verlagen van € 40 naar € 30 per dag",
"rationale": "De kosten per offerte liggen hier 60% boven het accountgemiddelde.",
"risk": "low",
"impact_estimate_cents": 30000,
"change": {
"kind": "budget",
"level": "adset",
"manual": false,
"from_cents": 4000,
"to_cents": 3000,
"placements": [
"audience_network"
],
"devices": [
"mobile"
],
"min": 30,
"max": 65,
"genders": [
"female"
],
"audience_name": null,
"headline": null,
"days": 14,
"template": null,
"purpose": null,
"percent": 1,
"country": "NL",
"strategy": "cost_cap",
"cap_cents": null,
"daily_budget_cents": null
},
"simulated": false,
"reuse_post": null,
"image_id": null,
"approval_deadline_at": null,
"applied_at": null,
"outcome": null,
"error": null,
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Obtenir la chronologie
/api/v1/meta-copilot/timeline
Tours, modifications et intentions, alertes et changements de mode dans une seule liste, les plus récents d'abord. Pas de curseur : au plus 100 lignes.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit
|
integer | Nombre de lignes, au plus 100 (50 par défaut). de 1 à 100 · par défaut : 50 |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/timeline" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/timeline');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/timeline', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/timeline",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "meta_copilot_timeline_entry",
"id": "action-2077",
"type": "action",
"at": null,
"kind": "adjust_budget",
"status": "applied",
"title": "Budget van \"Retargeting winter\" verlaagd naar € 30 per dag",
"rationale": "De kosten per offerte liggen hier 60% boven het accountgemiddelde.",
"target_name": "Retargeting winter",
"actor": "copilot",
"cause": null,
"severity": null,
"simulated": false,
"action_id": "2077",
"alert_id": null
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
Lister les bilans hebdomadaires
/api/v1/meta-copilot/digests
Les bilans que le copilote rédige le lundi : dépenses, résultats, ce qu'il a fait et ce qu'il propose. Sous forme de données, pas de texte.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit
|
integer | Nombre de résultats par page. de 1 à 100 · par défaut : 50 |
cursor
|
string | Le next_cursor ou prev_cursor de meta dans la réponse précédente. |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/digests" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/digests');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/digests', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/digests",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "meta_copilot_digest",
"id": "56",
"period_start": "2026-10-12",
"period_end": "2026-10-18",
"language": "nl",
"spend": "412.80",
"previous_spend": "398.10",
"conversions": 9,
"cost_per_conversion": "45.87",
"copilot_runs": 7,
"copilot_applied": 2,
"copilot_intentions": 0,
"outcomes": {
"improved": 1,
"neutral": 1,
"worsened": 0
},
"waiting": {
"proposals": 1,
"alerts": 0,
"opportunities": 3
},
"next_steps": [
"Nieuwe variant naast \"Veranda zomer\" testen"
],
"sent_at": null,
"created_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
Lister les briefings du matin
/api/v1/meta-copilot/briefings
Un briefing par jour sur la veille : dépenses, leads, devis et affaires gagnées dans Klantly comparés à la moyenne quotidienne de la semaine précédente, avec le type de journée et les jalons du matin. Titre et texte suivent Accept-Language.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit
|
integer | Nombre de résultats par page. de 1 à 100 · par défaut : 50 |
cursor
|
string | Le next_cursor ou prev_cursor de meta dans la réponse précédente. |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/briefings" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/briefings');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/briefings', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/briefings",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "meta_copilot_briefing",
"id": "412",
"date": "2026-10-22",
"kind": "quotes",
"headline": "Twee offerteaanvragen uit Meta gisteren.",
"body": "Besteed € 38,20 (gemiddeld € 41,10 per dag), 3 leads (gemiddeld 2,4), 2 offertes, 0 gewonnen.",
"spend": "38.20",
"avg_spend": "41.10",
"leads": 3,
"avg_leads": 2.4,
"clicks": 61,
"quotes": 2,
"won": 0,
"won_value": "0.00",
"cost_per_lead": "12.73",
"mtd_spend": "812.40",
"milestone_ids": [
"18"
],
"tip": {
"key": "frequency_high",
"category": "audience",
"actor": "copilot",
"title": "Je doelgroep ziet elke advertentie 3,4 keer",
"body": "Boven de 3 vertoningen per persoon stijgen de kosten per lead.",
"action": "Laat de co-pilot dit oppakken"
},
"pushed_at": null,
"created_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
Obtenir le pont de revenus
/api/v1/meta-copilot/revenue
Dépenses publicitaires → leads → devis → gagnés → chiffre d'affaires sur les `days` derniers jours (30 par défaut), par campagne et par mois civil, sur le vrai chiffre d'affaires Klantly. Les devis ne comptent que si la macro de campagne les relie à une campagne de ce compte.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
days
|
integer | Nombre de jours en arrière, de 7 à 365 (30 par défaut). La série mensuelle couvre toujours les six derniers mois civils. de 7 à 365 · par défaut : 30 |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/revenue?days=30" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/revenue', [
'query' => [
'days' => '30',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/revenue?days=30', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/revenue",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"days": "30"
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_revenue",
"since": "2026-09-24",
"until": "2026-10-23",
"uses_quotes": true,
"spend": "1240.50",
"clicks": 1830,
"impressions": 92400,
"leads": 74,
"quotes": 31,
"quotes_value": "142300.00",
"won": 6,
"won_value": "27850.00",
"cost_per_lead": "16.76",
"cost_per_quote": "40.02",
"cost_per_won": "206.75",
"roas": 22.45,
"revenue_source": "quotes",
"purchases": 0,
"purchase_value": "0.00",
"cost_per_purchase": null,
"meta_roas": null,
"copilot_impact": "412.00",
"campaigns": [
{
"campaign_id": "120210000000001",
"name": "Veranda voorjaar",
"spend": "812.00",
"leads": 51,
"quotes": 22,
"quotes_value": "98400.00",
"won": 4,
"won_value": "19200.00",
"cost_per_lead": "15.92",
"roas": 23.65,
"purchases": 0,
"purchase_value": "0.00",
"meta_roas": null
}
],
"months": [
{
"month": "2026-10",
"spend": "1240.50",
"leads": 74,
"quotes": 31,
"quotes_value": "142300.00",
"won": 6,
"won_value": "27850.00",
"cost_per_lead": "16.76",
"roas": 22.45,
"purchases": 0,
"purchase_value": "0.00",
"meta_roas": null
}
]
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
Obtenir les chiffres des campagnes
/api/v1/meta-copilot/stats
Dépense, impressions, clics et résultats sur les `days` derniers jours (7, 14, 30 ou 90 ; 30 par défaut) : totaux, la même période avant, par jour et par campagne. Adapté aux graphiques. Le copilote met les chiffres à jour chaque matin et chaque après-midi.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
days
|
integer | Combien de jours en arrière : 7, 14, 30 ou 90 (30 par défaut). l'une des valeurs : 7, 14, 30, 90 · par défaut : 30 |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/stats?days=30" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/stats', [
'query' => [
'days' => '30',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/stats?days=30', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/stats",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
params={
"days": "30"
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_stats",
"since": "2026-09-26",
"until": "2026-10-25",
"days": 30,
"currency": "EUR",
"result_kind": "leads",
"latest_date": "2026-10-04",
"synced_at": null,
"totals": {
"spend": "412.30",
"impressions": 31840,
"clicks": 612,
"results": 23,
"leads": 23,
"purchases": 0,
"purchase_value": "0.00",
"ctr": 1.92,
"cpc": "0.67",
"cpm": "12.95",
"cost_per_result": "17.93",
"roas": null
},
"previous": {
"spend": "412.30",
"impressions": 31840,
"clicks": 612,
"results": 23,
"leads": 23,
"purchases": 0,
"purchase_value": "0.00",
"ctr": 1.92,
"cpc": "0.67",
"cpm": "12.95",
"cost_per_result": "17.93",
"roas": null
},
"daily": [
{
"date": "2026-10-25",
"spend": "14.20",
"impressions": 1080,
"clicks": 21,
"results": 1,
"leads": 1,
"purchases": 0,
"purchase_value": "0.00",
"ctr": 1.94,
"cpc": "0.68",
"cpm": "13.15",
"cost_per_result": "14.20"
}
],
"campaigns": [
{
"campaign_id": "120210000000001",
"name": "Veranda voorjaar",
"status": "ACTIVE",
"share": 64.2,
"daily_spend": [
"12.40",
"14.10"
],
"spend": "264.70",
"impressions": 20410,
"clicks": 402,
"results": 16,
"leads": 16,
"purchases": 0,
"purchase_value": "0.00",
"ctr": 1.97,
"cpc": "0.66",
"cpm": "12.97",
"cost_per_result": "16.54",
"roas": null
}
]
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
Obtenir l’équipe du copilote
/api/v1/meta-copilot/crew
Ce que chaque agent du copilote a fait en dernier, quand il se remet au travail selon le planning, et les compteurs du jour et de la semaine. Tout provient d’actions réelles et du planning réel.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/crew" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/crew');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/crew', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/crew",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_crew",
"state": "active",
"mode": "copilot",
"agents": [
{
"role": "optimizer",
"status": "ready",
"last_at": "2026-10-25T05:03:11Z",
"last_kind": "run_operational",
"last_facts": {
"status": "completed",
"tool_calls": 14,
"proposals": 2
},
"next_at": "2026-10-28T06:00:00Z",
"next_kind": "operational",
"count_7d": 3,
"week": [
0,
1,
0,
0,
1,
0,
1
]
}
],
"today": {
"checks": 14,
"campaigns": 4,
"opportunities": 1,
"proposals": 2
},
"week": {
"checks": 98,
"rounds": 3,
"proposals": 5,
"applied": 2
},
"next": {
"role": "guard",
"at": "2026-10-26T05:45:00Z"
},
"feed": [
{
"role": "analyst",
"kind": "stats_synced",
"at": "2026-10-25T04:45:12Z",
"facts": {
"campaigns": 4,
"days": 14,
"rows": 56
}
}
]
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Obtenir ce que le copilote a rapporté
/api/v1/meta-copilot/value
Ce que le copilote a fait depuis son activation et ce que cela a rapporté : améliorations appliquées (seul ou après accord), la mesure une semaine plus tard (mieux, pareil, moins bien, encore en mesure), la valeur estimée, ce qu’il a surveillé, et le coût par résultat les jours avant et depuis l’activation. L’estimation est l’attente pour chaque proposition, pas une mesure ; la comparaison n’apparaît qu’après sept jours et cinq résultats de chaque côté.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/value" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/value');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/value', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/value",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_value",
"since": "2026-10-02T08:14:00Z",
"days_on": 26,
"mode": "autopilot",
"currency": "EUR",
"actions": {
"applied": 9,
"by_itself": 7,
"approved": 2,
"rolled_back": 0
},
"outcomes": {
"improved": 5,
"neutral": 1,
"worsened": 1,
"measuring": 2
},
"estimated_value": "640.00",
"watch": {
"checks_30d": 412,
"alerts": 6,
"alerts_resolved": 5
},
"comparison": {
"available": true,
"days": 26,
"result_kind": "leads",
"before": {
"spend": "812.40",
"results": 31,
"cost_per_result": "26.21"
},
"after": {
"spend": "790.10",
"results": 42,
"cost_per_result": "18.81"
},
"change_pct": -28.2
},
"recent": [
{
"id": 4182,
"title": "Budget van Veranda voorjaar met 15% verhoogd",
"action_type": "update_campaign_budget",
"at": "2026-10-24T05:12:00Z",
"by_itself": true,
"outcome": "measuring",
"rollback": false,
"impact_estimate": "120.00"
}
],
"generated_at": "2026-10-28T09:30:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Lister les jalons
/api/v1/meta-copilot/milestones
Jalons célébrés (la mesure de référence enregistrée en silence d'un compte existant n'y figure pas), les plus récents d'abord : leads issus de Meta, affaires gagnées, meilleure semaine et semaines consécutives sans gaspillage. Titre et détail suivent Accept-Language.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de requête
| Nom | Type | Description |
|---|---|---|
limit
|
integer | Nombre de résultats par page. de 1 à 100 · par défaut : 50 |
cursor
|
string | Le next_cursor ou prev_cursor de meta dans la réponse précédente. |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/milestones" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/milestones');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/milestones', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/milestones",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "meta_copilot_milestone",
"id": "18",
"kind": "leads",
"threshold": 100,
"period": "",
"value": "104.00",
"title": "De 100e lead uit Meta",
"detail": "Sinds het begin van de meting kwamen er 104 leads uit je Meta-advertenties.",
"reached_on": "2026-10-22",
"created_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
422
validation_failed— Les données saisies ne sont pas valides.
Vous face aux entreprises comparables
/api/v1/meta-copilot/benchmark
Coût par lead, CTR, CPC et CPM de ce compte sur 30 jours face à la médiane et au meilleur quart de tous les comptes suivis avec du volume, anonyme et seulement à partir de cinq comptes. position = la part des comptes qui font moins bien.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/benchmark" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/benchmark');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/benchmark', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/benchmark",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_benchmark",
"available": true,
"accounts": 12,
"min_accounts": 5,
"period_days": 30,
"metrics": [
{
"metric": "cost_per_lead",
"own": 14.2,
"median": 19.8,
"best_quartile": 11.5,
"position": 71,
"higher_is_better": false
}
]
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Obtenir le calendrier saisonnier
/api/v1/meta-copilot/seasonality
Combien de demandes de devis reçoivent les entreprises Klantly comparables par mois civil (la branche de l'agent IA, sinon toute la plateforme), en facteur par rapport à la moyenne sur deux ans. Anonyme et seulement au-dessus du seuil de volume ; sinon available=false.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/seasonality" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/seasonality');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/seasonality', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/seasonality",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_seasonality",
"available": true,
"scope": "branch",
"label": "Veranda en overkappingen",
"companies": 23,
"quotes_per_month": 410,
"months": [
{
"month": 3,
"factor": 1.42
}
],
"current_month": 10,
"current_factor": 0.84,
"next_month": 11,
"next_factor": 0.61,
"peak_month": 3,
"low_month": 12
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Répondre au conseil du jour
/api/v1/meta-copilot/tips/{tip}/respond
accept = le copilote s'en charge (le conseil devient une opportunité et une prochaine étape de sa stratégie), self = vous vous en chargez, dismiss = pas pertinent. Le même conseil ne revient ensuite pas pendant quatre-vingt-dix jours. 404 si la clé du conseil est inconnue.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
tip obligatoire |
string | La clé du conseil telle qu'elle figure dans le briefing (par exemple frequency_high). |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/tips/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/respond" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/tips/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/respond', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/tips/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/respond', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/tips/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/respond",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_tip_response",
"tip": "frequency_high",
"category": "audience",
"actor": "copilot",
"title": "Je doelgroep ziet elke advertentie 3,4 keer",
"vars": {
"spend": "€ 600.00"
},
"response": "accept",
"opportunity_id": "321",
"responded_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Lister les concurrents suivis
/api/v1/meta-copilot/competitors
Les pages Facebook que l'entreprise suit (cinq au plus), chacune avec ses publicités issues de la bibliothèque publicitaire publique de Meta (25 au plus, en cours et nouvelles d'abord) : titre, texte, plateformes, durée et portée dans l'UE. Le copilote lit la bibliothèque chaque semaine ; is_new reste quatorze jours. Pas de curseur.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/competitors" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/competitors');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/competitors', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/competitors",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "meta_copilot_competitor",
"id": "7",
"page_id": "115115300320906",
"page_name": "Veranda Boys",
"library_url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&view_all_page_id=115115300320906",
"ads_active": 6,
"ads_total": 14,
"last_scanned_at": null,
"ads": [],
"created_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Suivre un concurrent
/api/v1/meta-copilot/competitors
Par l'identifiant numérique de la page Facebook (visible dans la bibliothèque publicitaire, ou dans le tableau de bord via la recherche par nom). La mesure de référence de ses publicités se fait tout de suite ; ce qui tourne déjà alors ne compte pas comme nouveau. 409 conflict pour une page déjà suivie, au-delà du maximum de cinq, ou sans connexion Meta active.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/competitors" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/competitors', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/competitors', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/competitors",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 201
{
"data": {
"object": "meta_copilot_competitor",
"id": "7",
"page_id": "115115300320906",
"page_name": "Veranda Boys",
"library_url": "https://www.facebook.com/ads/library/?active_status=all&ad_type=all&view_all_page_id=115115300320906",
"ads_active": 6,
"ads_total": 14,
"last_scanned_at": null,
"ads": [],
"created_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Ne plus suivre un concurrent
/api/v1/meta-copilot/competitors/{competitor}
Supprime la page et ses publicités enregistrées.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
competitor obligatoire |
string | L'identifiant du concurrent suivi. |
Exemple de requête
curl -X DELETE "https://app.klantly.com/api/v1/meta-copilot/competitors/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('DELETE', 'meta-copilot/competitors/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/competitors/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.delete(
"https://app.klantly.com/api/v1/meta-copilot/competitors/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "note",
"id": "9d3f7b41-2d6f-4e8c-9b3a-4f5d6e7a8b92",
"deleted": true
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Créer une variante sur une publicité d'un concurrent
/api/v1/meta-copilot/competitors/ads/{ad}/variant
Le copilote écrit une variante de votre meilleure publicité avec l'ANGLE de cette publicité du concurrent — pas son texte : aucune phrase n'est reprise, votre image reste et aucune promesse absente de votre original n'est ajoutée. Le résultat est une opportunité de type creative_advice avec la variante prête à approuver (statut 201). 409 conflict si le copilote est éteint, s'il n'y a pas de publicité active à vous avec du texte, si la même publicité source a déjà reçu une variante ces soixante derniers jours, ou si aucune variante utilisable n'en est sortie. Coûte un appel au modèle.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
ad obligatoire |
string | L'identifiant de la publicité du concurrent (dans la liste des concurrents suivis). |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/competitors/ads/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/variant" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/competitors/ads/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/variant', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/competitors/ads/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/variant', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/competitors/ads/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/variant",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 201
{
"data": {
"object": "meta_copilot_opportunity",
"id": "318",
"source": "signal",
"kind": "wasted_spend",
"status": "open",
"title": "\"Retargeting winter\" gaf € 184,20 uit zonder één conversie",
"body": "In de laatste 30 dagen is er € 184,20 besteed en zijn er 212 klikken geweest, maar geen enkele conversie.",
"impact_cents": 18420,
"confidence": "high",
"reversible": true,
"actionable": true,
"reuse_post": null,
"image_id": null,
"target_level": "adset",
"target_id": "120210000000000001",
"target_name": "Retargeting winter",
"dismissed_reason": null,
"action_id": null,
"variant": {
"reference_ad_id": "120210000000000009",
"headline": "Veranda op maat, binnen 4 weken geplaatst",
"primary_text": "Langer buiten zitten zonder gedoe? Onze aluminium veranda wordt op maat gemaakt en binnen vier weken geplaatst. Vraag vandaag een vrijblijvende offerte aan.",
"description": "Op maat gemaakt",
"cta_type": "GET_QUOTE"
},
"blueprint": {
"branch": "veranda",
"city": "Nijmegen",
"radius_km": 40,
"age_min": 30,
"age_max": 65,
"daily_budget_cents": 1500,
"has_pixel": true,
"landing_url": "https://configurator.klantly.com/offerte-aanvragen/01k7x?utm_source=facebook",
"image_id": "12",
"headline": "Veranda op maat van Veranda Boys",
"primary_text": "Langer buiten zitten, ook in het najaar? Veranda Boys maakt veranda's op maat. Vraag vrijblijvend een offerte aan.",
"description": "Vrijblijvende offerte",
"cta_type": "GET_QUOTE",
"peer_accounts": 7,
"peer_median_cpl": "31.20"
},
"decided_at": null,
"expires_at": null,
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Aperçu d’une publicité
/api/v1/meta-copilot/ads/{ad}/preview
L’adresse de l’aperçu tel que Meta affiche la publicité (format : MOBILE_FEED_STANDARD, INSTAGRAM_STANDARD, INSTAGRAM_STORY ou DESKTOP_FEED_STANDARD ; par défaut le fil sur mobile). Placez l’adresse dans un iframe. Uniquement pour une publicité du propre compte publicitaire (sinon 404) ; si Meta ne peut pas créer d’aperçu, 409. L’adresse est valable quelques heures.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
ad obligatoire |
string | L'identifiant de la publicité du concurrent (dans la liste des concurrents suivis). |
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/ads/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/preview" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/ads/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/preview');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/ads/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/preview', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/ads/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/preview",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_ad_preview",
"ad_id": "120211234567890",
"format": "MOBILE_FEED_STANDARD",
"url": "https://www.facebook.com/ads/api/preview_iframe.php?d=AQ...&t=AQ..."
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
validation_failed— Les données saisies ne sont pas valides.
Lister les images de la bibliothèque
/api/v1/meta-copilot/images
Les images et vidéos que l'entreprise a téléversées pour les variantes publicitaires, les plus récentes d'abord, chacune avec un lien de téléchargement signé. L'état d'une vidéo encore traitée par Meta est rafraîchi à la demande. Pas de curseur.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/images" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/images');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/images', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/images",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
La réponse est une liste avec pagination par curseur : data contient les objets, meta la pagination.
{
"data": [
{
"object": "meta_copilot_image",
"id": "12",
"kind": "image",
"video_status": null,
"name": "Veranda antraciet avond",
"width": 1200,
"height": 1200,
"size": 348211,
"usable": true,
"download_url": "https://app.klantly.com/api/files/quote-attachment/9d3f9e56-af10-4123-b345-e6f7a8b9c0d5?expires=1789000000&signature=8f1c…",
"created_at": "2026-09-14T10:15:00Z"
}
],
"meta": {
"limit": 50,
"next_cursor": "eyJpZCI6IjlkM2Y2YzFlIn0",
"prev_cursor": null
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Consulter l’état d’une nouvelle campagne
/api/v1/meta-copilot/starter
Le métier reconnu (à partir de l’agent IA, des devis et du profil de l’entreprise), les questions de départ avec, pour chacune, la réponse de l’entreprise et la suggestion du copilote (que vendez-vous, dans quelle zone, où arrive un client, combien par jour, quelle image, quelle page), si tout est complet et ce qui manque sinon (blocked : no_image, no_page ou no_landing). Fonctionne aussi sur un compte sans campagnes.
- Scope
-
meta_copilot.read— Lire l'état et les alertes du copilote Meta - Fonctionnalité requise
meta_copilot
Exemple de requête
curl "https://app.klantly.com/api/v1/meta-copilot/starter" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('GET', 'meta-copilot/starter');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/starter', {
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.get(
"https://app.klantly.com/api/v1/meta-copilot/starter",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_starter",
"branch": "veranda",
"branch_label": "veranda's en overkappingen",
"branch_confidence": "high",
"complete": false,
"blocked": "no_image",
"has_active_campaign": false,
"questions": []
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
Enregistrer les réponses aux questions de départ
/api/v1/meta-copilot/starter/intake
Chaque champ peut être envoyé séparément ; null retire une réponse pour que la suggestion du copilote s’applique à nouveau. product est un métier de la liste ; landing une clé des options (form:<id> ou website) ou url:https://… ; daily_budget_cents entre 500 et 20000 et jamais au-dessus du plafond journalier du mandat (sinon 422) ; image_id une image de la bibliothèque. Renvoie l’état mis à jour.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
product
facultatif
|
string | Le métier : veranda, dakkapel, aanbouw, kozijnen, zonwering, vloeren, badkamer, keuken ou generic. peut être vide (null) · l'une des valeurs : veranda, dakkapel, aanbouw, kozijnen, zonwering, vloeren, badkamer, keuken, generic |
area_city
facultatif
|
string | La localité au centre de la zone d’intervention. peut être vide (null) · au maximum 120 caractères |
area_radius_km
facultatif
|
integer | Le rayon en kilomètres (5–80). peut être vide (null) · de 5 à 80 |
landing
facultatif
|
string | Où arrive un client : une clé des options (form:<id> ou website) ou url:https://… pour une adresse propre. peut être vide (null) · au maximum 600 caractères |
daily_budget_cents
facultatif
|
integer | Le budget journalier en centimes (500–20000), jamais au-dessus du plafond journalier du mandat. peut être vide (null) · de 500 à 20000 |
image_id
facultatif
|
integer | Une image ou vidéo de la bibliothèque. peut être vide (null) |
page_id
facultatif
|
string | La page Facebook qui sert d’expéditeur. peut être vide (null) · au maximum 40 caractères |
Exemple de requête
curl -X PUT "https://app.klantly.com/api/v1/meta-copilot/starter/intake" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"product": "veranda",
"area_city": "Nijmegen",
"area_radius_km": 40,
"daily_budget_cents": 1500
}'$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('PUT', 'meta-copilot/starter/intake', [
'json' => [
'product' => 'veranda',
'area_city' => 'Nijmegen',
'area_radius_km' => 40,
'daily_budget_cents' => 1500,
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/starter/intake', {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
"product": "veranda",
"area_city": "Nijmegen",
"area_radius_km": 40,
"daily_budget_cents": 1500
}),
});
const { data } = await response.json();import os
import requests
response = requests.put(
"https://app.klantly.com/api/v1/meta-copilot/starter/intake",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
json={
"product": "veranda",
"area_city": "Nijmegen",
"area_radius_km": 40,
"daily_budget_cents": 1500
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "meta_copilot_starter",
"branch": "veranda",
"branch_label": "veranda's en overkappingen",
"branch_confidence": "high",
"complete": false,
"blocked": "no_image",
"has_active_campaign": false,
"questions": []
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel.
Proposer une nouvelle campagne
/api/v1/meta-copilot/starter/propose
Le copilote construit le plan d’une campagne complète (campagne, ensemble de publicités et publicité) à partir des réponses, de la configuration qui a donné aux entreprises comparables du même métier les demandes les moins chères (sinon le playbook du métier) et d’un texte publicitaire du modèle, et le dépose comme opportunité de type campaign_blueprint (statut 201, avec blueprint). Accepter cette opportunité vaut approbation : tout est créé en pause puis seulement mis en ligne. Jamais autonome. 409 si les questions sont incomplètes, s’il n’y a ni image ni page, ou si le copilote est éteint. Coûte un appel au modèle.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Envoyez une Idempotency-Key : une nouvelle tentative après un délai d'attente ne crée alors jamais de doublon.
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/starter/propose" \
-H "Authorization: Bearer $KLANTLY_API_KEY" \
-H "Idempotency-Key: 6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/starter/propose', [
'headers' => [
'Idempotency-Key' => '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
],
]);
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/starter/propose', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
'Idempotency-Key': '6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f',
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/starter/propose",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
"Idempotency-Key": "6f1c2d3e-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
},
)
data = response.json()["data"]Réponse 201
{
"data": {
"object": "meta_copilot_opportunity",
"id": "318",
"source": "signal",
"kind": "wasted_spend",
"status": "open",
"title": "\"Retargeting winter\" gaf € 184,20 uit zonder één conversie",
"body": "In de laatste 30 dagen is er € 184,20 besteed en zijn er 212 klikken geweest, maar geen enkele conversie.",
"impact_cents": 18420,
"confidence": "high",
"reversible": true,
"actionable": true,
"reuse_post": null,
"image_id": null,
"target_level": "adset",
"target_id": "120210000000000001",
"target_name": "Retargeting winter",
"dismissed_reason": null,
"action_id": null,
"variant": {
"reference_ad_id": "120210000000000009",
"headline": "Veranda op maat, binnen 4 weken geplaatst",
"primary_text": "Langer buiten zitten zonder gedoe? Onze aluminium veranda wordt op maat gemaakt en binnen vier weken geplaatst. Vraag vandaag een vrijblijvende offerte aan.",
"description": "Op maat gemaakt",
"cta_type": "GET_QUOTE"
},
"blueprint": {
"branch": "veranda",
"city": "Nijmegen",
"radius_km": 40,
"age_min": 30,
"age_max": 65,
"daily_budget_cents": 1500,
"has_pixel": true,
"landing_url": "https://configurator.klantly.com/offerte-aanvragen/01k7x?utm_source=facebook",
"image_id": "12",
"headline": "Veranda op maat van Veranda Boys",
"primary_text": "Langer buiten zitten, ook in het najaar? Veranda Boys maakt veranda's op maat. Vraag vrijblijvend een offerte aan.",
"description": "Vrijblijvende offerte",
"cta_type": "GET_QUOTE",
"peer_accounts": 7,
"peer_median_cpl": "31.20"
},
"decided_at": null,
"expires_at": null,
"created_at": "2026-09-14T10:15:00Z",
"updated_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
422
idempotency_key_reused— Cette Idempotency-Key a déjà été utilisée pour une autre requête. -
409
idempotency_in_progress— Une requête avec cette Idempotency-Key est encore en cours.
Téléverser une image
/api/v1/meta-copilot/images
Ajoute une image ou une vidéo à la bibliothèque du copilote et l'enregistre chez Meta (adimages ou advideos) dans le même appel. Envoyez-la en multipart/form-data avec le champ file : une image (jpg, png ou webp, au moins 600 × 600 pixels, jusqu'à 10 Mo) ou une vidéo (mp4 ou mov, jusqu'à 30 Mo) ; 30 au plus par compte. Une variante (proposition ou opportunité avec create_ad_variant) peut ensuite la porter via image_id lors de approve ou accept ; une vidéo seulement une fois traitée par Meta (video_status ready). 409 conflict si l'image est trop petite ou la vidéo trop grande, si le maximum est atteint, si Meta la refuse ou s'il n'y a pas de connexion Meta active.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Corps (JSON)
| Champ | Type | Description |
|---|---|---|
file
obligatoire
|
string (binary) | L'image ou la vidéo elle-même, en multipart/form-data. Image : jpg, png ou webp, au moins 600 × 600 pixels, 10 Mo au plus. Vidéo : mp4 ou mov, 30 Mo au plus ; Meta la traite encore un instant (video_status). |
name
facultatif
|
string | Le nom (nom de fichier sans extension, ou le name fourni). peut être vide (null) · au maximum 255 caractères |
Exemple de requête
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/images" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('POST', 'meta-copilot/images');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/images', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.post(
"https://app.klantly.com/api/v1/meta-copilot/images",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 201
{
"data": {
"object": "meta_copilot_image",
"id": "12",
"kind": "image",
"video_status": null,
"name": "Veranda antraciet avond",
"width": 1200,
"height": 1200,
"size": 348211,
"usable": true,
"download_url": "https://app.klantly.com/api/files/quote-attachment/9d3f9e56-af10-4123-b345-e6f7a8b9c0d5?expires=1789000000&signature=8f1c…",
"created_at": "2026-09-14T10:15:00Z"
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
422
validation_failed— Les données saisies ne sont pas valides. -
422
unknown_field— Les données contiennent un champ inconnu. -
415
unsupported_media_type— Ce format n'est pas pris en charge. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
404
not_found— Introuvable. -
409
conflict— Ceci est en conflit avec l'état actuel. -
413
payload_too_large— Le corps de la requête est trop volumineux. -
415
unsupported_media_type— Ce format n'est pas pris en charge.
Supprimer une image
/api/v1/meta-copilot/images/{image}
Retire l'image de la bibliothèque ; une publicité déjà créée garde son image chez Meta.
- Scope
-
meta_copilot.write— Arrêter le copilote Meta avec l'arrêt d'urgence, laisser agir ou écarter des opportunités et approuver ou rejeter des propositions (le mandat ne se configure que dans l'application) - Fonctionnalité requise
meta_copilot
Paramètres de chemin
| Nom | Type | Description |
|---|---|---|
image obligatoire |
string | L'identifiant de l'image dans la bibliothèque. |
Exemple de requête
curl -X DELETE "https://app.klantly.com/api/v1/meta-copilot/images/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
-H "Authorization: Bearer $KLANTLY_API_KEY"$client = new \GuzzleHttp\Client([
'base_uri' => 'https://app.klantly.com/api/v1/',
'headers' => ['Authorization' => 'Bearer ' . getenv('KLANTLY_API_KEY')],
]);
$response = $client->request('DELETE', 'meta-copilot/images/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70');
$data = json_decode((string) $response->getBody(), true)['data'];const response = await fetch('https://app.klantly.com/api/v1/meta-copilot/images/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70', {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.KLANTLY_API_KEY}`,
},
});
const { data } = await response.json();import os
import requests
response = requests.delete(
"https://app.klantly.com/api/v1/meta-copilot/images/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70",
headers={
"Authorization": f"Bearer {os.environ['KLANTLY_API_KEY']}",
},
)
data = response.json()["data"]Réponse 200
{
"data": {
"object": "note",
"id": "9d3f7b41-2d6f-4e8c-9b3a-4f5d6e7a8b92",
"deleted": true
}
}Erreurs possibles
-
403
insufficient_scope— Cette clé API n'a pas accès à cette action. -
404
not_found— Introuvable.
L'objet
Tous les champs sont toujours présents ; un champ sans valeur vaut null.
| Champ | Type | Description |
|---|---|---|
object |
string | Toujours "meta_copilot". |
ad_account_id |
string | Le compte publicitaire Meta, sous la forme act_. |
ad_account_name |
string | Le nom du compte publicitaire chez Meta. peut être vide (null) |
currency |
string | La devise du compte. |
mode |
string | Le mode : off, shadow (observer sans rien changer), copilot (tout pour approbation) ou autopilot (applique dans le cadre du mandat). l'une des valeurs : off, shadow, copilot, autopilot |
profile |
string | Le profil de mandat : careful, standard ou broad. peut être vide (null) · l'une des valeurs : careful, standard, broad |
goal_metric |
string | Ce que le copilote optimise. peut être vide (null) · l'une des valeurs : cost_per_quote, cost_per_lead, cost_per_conversion, roas |
goal_value |
string | La valeur cible, en texte à deux décimales. peut être vide (null) |
monthly_budget |
string | L'accord de budget publicitaire mensuel. peut être vide (null) |
autonomous_classes |
array<string> | Les classes d'actions que le copilote peut appliquer seul ; vide en mode ombre. |
open_alerts |
integer | Nombre d'alertes ouvertes. |
pending_proposals |
integer | Nombre de propositions en attente de décision. |
enabled_at |
string (date-time) | Quand le copilote a été activé. peut être vide (null) |
tier |
string | Le palier de l’abonnement : copilot (ombre et copilote, budget publicitaire jusqu’à 2 500 € par mois), autopilot (aussi l’autopilote, jusqu’à 7 500 €) ou plus (illimité, tour opérationnel quotidien) ; null sans copilote. peut être vide (null) · l'une des valeurs : copilot, autopilot, plus |
ad_budget_ceiling |
string | Le budget publicitaire mensuel jusqu’auquel le copilote déplace du budget sur ce palier, en texte à deux décimales ; null = illimité. peut être vide (null) |
on_expiry |
string | Ce qu’il advient d’une proposition non jugée à temps : lapse (expire, par défaut) ou apply (appliquée quand même après l’échéance, dans toutes les limites fixes). l'une des valeurs : lapse, apply |
stopped_at |
string (date-time) | Quand le copilote a été arrêté pour la dernière fois. peut être vide (null) |
connection_active |
boolean | Si la connexion Meta fonctionne. |
running |
object | Si le copilote travaille en ce moment : null si rien ne tourne. peut être vide (null) |
running.state |
string | queued (la tournée est demandée et attend son tour) ou running (la tournée est en cours). l'une des valeurs : queued, running |
running.since |
string (date-time) | Depuis quand. peut être vide (null) |
running.kind |
string | Type de tournée : operational ou strategy ; null tant qu’elle attend. peut être vide (null) · l'une des valeurs : operational, strategy |