Klantly Developers

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

Obtenir l'état du copilote

GET /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
curl "https://app.klantly.com/api/v1/meta-copilot" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Mettre à jour le mandat du copilote

PATCH /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)

ChampTypeDescription
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
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"
}'
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Lister les alertes du copilote

GET /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

NomTypeDescription
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
curl "https://app.klantly.com/api/v1/meta-copilot/alerts?filter[status]=open" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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.

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Exécuter l'arrêt d'urgence

POST /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
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"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Lister les opportunités du copilote

GET /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

NomTypeDescription
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
curl "https://app.klantly.com/api/v1/meta-copilot/opportunities?filter[status]=open" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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.

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Laisser le copilote agir sur une opportunité

POST /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

NomTypeDescription
opportunity obligatoire string L'id de l'opportunité.

Exemple de requête

cURL
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"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Écarter une opportunité

POST /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

NomTypeDescription
opportunity obligatoire string L'id de l'opportunité.

Exemple de requête

cURL
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
}'
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Lister les propositions du copilote

GET /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

NomTypeDescription
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
curl "https://app.klantly.com/api/v1/meta-copilot/approvals?filter[status]=proposed" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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.

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Approuver une proposition

POST /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

NomTypeDescription
approval obligatoire string L'id de la proposition.

Exemple de requête

cURL
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"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Rejeter une proposition

POST /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

NomTypeDescription
approval obligatoire string L'id de la proposition.

Exemple de requête

cURL
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"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Obtenir la chronologie

GET /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

NomTypeDescription
limit integer Nombre de lignes, au plus 100 (50 par défaut). de 1 à 100 · par défaut : 50

Exemple de requête

cURL
curl "https://app.klantly.com/api/v1/meta-copilot/timeline" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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.

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Lister les bilans hebdomadaires

GET /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

NomTypeDescription
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
curl "https://app.klantly.com/api/v1/meta-copilot/digests" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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.

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Lister les briefings du matin

GET /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

NomTypeDescription
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
curl "https://app.klantly.com/api/v1/meta-copilot/briefings" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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.

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Obtenir le pont de revenus

GET /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

NomTypeDescription
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
curl "https://app.klantly.com/api/v1/meta-copilot/revenue?days=30" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Obtenir les chiffres des campagnes

GET /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

NomTypeDescription
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
curl "https://app.klantly.com/api/v1/meta-copilot/stats?days=30" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Obtenir l’équipe du copilote

GET /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
curl "https://app.klantly.com/api/v1/meta-copilot/crew" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Obtenir ce que le copilote a rapporté

GET /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
curl "https://app.klantly.com/api/v1/meta-copilot/value" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Lister les jalons

GET /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

NomTypeDescription
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
curl "https://app.klantly.com/api/v1/meta-copilot/milestones" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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.

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Vous face aux entreprises comparables

GET /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
curl "https://app.klantly.com/api/v1/meta-copilot/benchmark" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Obtenir le calendrier saisonnier

GET /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
curl "https://app.klantly.com/api/v1/meta-copilot/seasonality" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Répondre au conseil du jour

POST /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

NomTypeDescription
tip obligatoire string La clé du conseil telle qu'elle figure dans le briefing (par exemple frequency_high).

Exemple de requête

cURL
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"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Lister les concurrents suivis

GET /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
curl "https://app.klantly.com/api/v1/meta-copilot/competitors" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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.

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Suivre un concurrent

POST /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
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"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Ne plus suivre un concurrent

DELETE /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

NomTypeDescription
competitor obligatoire string L'identifiant du concurrent suivi.

Exemple de requête

cURL
curl -X DELETE "https://app.klantly.com/api/v1/meta-copilot/competitors/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "data": {
    "object": "note",
    "id": "9d3f7b41-2d6f-4e8c-9b3a-4f5d6e7a8b92",
    "deleted": true
  }
}

Erreurs possibles

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Créer une variante sur une publicité d'un concurrent

POST /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

NomTypeDescription
ad obligatoire string L'identifiant de la publicité du concurrent (dans la liste des concurrents suivis).

Exemple de requête

cURL
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"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Aperçu d’une publicité

GET /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

NomTypeDescription
ad obligatoire string L'identifiant de la publicité du concurrent (dans la liste des concurrents suivis).

Exemple de requête

cURL
curl "https://app.klantly.com/api/v1/meta-copilot/ads/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70/preview" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Lister les images de la bibliothèque

GET /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
curl "https://app.klantly.com/api/v1/meta-copilot/images" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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.

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Consulter l’état d’une nouvelle campagne

GET /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
curl "https://app.klantly.com/api/v1/meta-copilot/starter" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Enregistrer les réponses aux questions de départ

PUT /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)

ChampTypeDescription
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
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
}'
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Proposer une nouvelle campagne

POST /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
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"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Téléverser une image

POST /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)

ChampTypeDescription
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
curl -X POST "https://app.klantly.com/api/v1/meta-copilot/images" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "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

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

Supprimer une image

DELETE /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

NomTypeDescription
image obligatoire string L'identifiant de l'image dans la bibliothèque.

Exemple de requête

cURL
curl -X DELETE "https://app.klantly.com/api/v1/meta-copilot/images/9d3f6c1e-4b2a-4c8e-9f1a-2b3c4d5e6f70" \
  -H "Authorization: Bearer $KLANTLY_API_KEY"
PHP
$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'];
JavaScript
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();
Python
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

Exemple de réponse
{
  "data": {
    "object": "note",
    "id": "9d3f7b41-2d6f-4e8c-9b3a-4f5d6e7a8b92",
    "deleted": true
  }
}

Erreurs possibles

En outre, chaque endpoint peut renvoyer les erreurs générales, comme une clé invalide ou une limite atteinte. Voir tous les codes d'erreur.

L'objet

Tous les champs sont toujours présents ; un champ sans valeur vaut null.

ChampTypeDescription
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