GetAff
Article

Automatiser le recrutement d’affiliés avec l’API REST de GetAff

L’API REST de GetAff expose les mêmes opérations que les écrans de recrutement de partenaires : critères de recherche, une seule recherche dans toutes les sources, la sélection, les prospects et leurs e-mails, et l’inscription dans une séquence de prospection. Une tâche nocturne peut donc actualiser une recherche, garder les meilleurs nouveaux créateurs et préparer leur prospection sans que personne n’ouvre l’application.

Cet article suit cette tâche de la première requête à la dernière, avec les trois règles qui rendent une automatisation sûre : les appels payants sont confirmés par un chiffre, les écritures portent une clé d’idempotence, et le client lit les en-têtes de limite de débit au lieu de deviner.

Mis à jour le

Créer une clé avec les bons scopes

Connectez-vous, ouvrez la page Clés d’API et créez une clé par intégration — c’est ce qui permet d’en révoquer une sans arrêter les autres. La valeur n’est affichée qu’une seule fois : GetAff n’en conserve qu’une empreinte.

  • read est toujours inclus : sites, critères, résultats, prospects, séquences.
  • search pour les recherches qui ne dépensent aucun crédit (index, créateurs similaires, concurrents).
  • write pour modifier les critères, la sélection, les prospects et inscrire dans une séquence.
  • spend pour les recherches en direct chez les fournisseurs et les recherches d’e-mails payantes — uniquement pour une intégration à laquelle vous faites confiance pour respecter un budget.

Gardez la clé côté serveur, dans un gestionnaire de secrets ou une variable d’environnement. L’API refuse par conception toute origine navigateur : une clé dans le JavaScript d’une page est une clé publiée. Détails dans Authentification.

Premier appel : vos sites

L’URL de base est https://www.getaff.org/api/v1. Chaque recherche de partenaires appartient à un site ; commencez donc par les lister :

curl -s https://www.getaff.org/api/v1/sites \
  -H "Authorization: Bearer $GETAFF_API_KEY"

Chaque site est accompagné du programme qu’il gère. GET /v1/sites/{id}/criteria renvoie les critères qu’utilisera la prochaine recherche et ceux que GetAff déduit du site ; PATCH sur le même chemin remplace les champs envoyés et conserve les autres.

POST /v1/sites/{id}/partner-search lance la même recherche que l’application : l’index de créateurs GetAff classé pour votre programme, les créateurs similaires à votre sélection, ceux qui promeuvent vos concurrents et — avec includeLive — les fournisseurs de données de créateurs en direct. Les résultats sont fusionnés, dédoublonnés et classés, chacun avec un score d’adéquation et ses raisons ; statuses indique ce qu’a fait chaque source.

Sources gratuites uniquement
SITE_ID=Wq3b9ZK1
curl -s -X POST https://www.getaff.org/api/v1/sites/$SITE_ID/partner-search \
  -H "Authorization: Bearer $GETAFF_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: nightly-$SITE_ID-$(date +%F)" \
  -d '{"limit": 50}'

L’exécution remplace la dernière recherche (conservée 30 jours) et s’ajoute aux recherches enregistrées : GET /v1/sites/{id}/partner-search/latest et les points d’accès de l’historique peuvent donc la relire plus tard sans rien relancer.

Appels payants : l’échange en 402

Deux opérations dépensent des crédits fournisseurs : la recherche de partenaires avec includeLive: true et POST /v1/prospects/find-emails. Toutes deux exigent le scope spend ET un confirmCost au moins égal à l’estimation. Sans lui, rien n’est dépensé et l’API répond 402 cost_confirmation_required, avec l’estimation exacte dans error.details.estimate.

  1. Envoyez la requête sans confirmCost.
  2. Lisez error.details.estimate.credits dans la réponse 402.
  3. Comparez ce chiffre à votre budget — ou montrez-le à un humain.
  4. Renvoyez la même requête avec confirmCost égal à ce chiffre ou à un plafond supérieur.
Node — confirmer dans la limite d’un budget
async function confirmed(url, body) {
  const call = (b) =>
    fetch(url, {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.GETAFF_API_KEY}`,
        'Content-Type': 'application/json',
        'Idempotency-Key': crypto.randomUUID(),
      },
      body: JSON.stringify(b),
    });
  let res = await call(body);
  if (res.status === 402) {
    const { error } = await res.json();
    const credits = error.details.estimate.credits;
    if (credits > MAX_CREDITS_PER_RUN) throw new Error(`Over budget: ${credits}`);
    res = await call({ ...body, confirmCost: credits });
  }
  return res.json();
}

Chaque dépense confirmée est consignée dans un journal d’audit (clé, action, crédits — jamais les données d’un créateur). Les allocations quotidiennes de votre plan s’appliquent en plus de tout budget que vous fixez.

Des résultats aux prospects

Chaque résultat porte une key comme instagram:1784140. Gardez ceux que vos règles retiennent — un score d’adéquation minimal, un pays, une audience plancher — et enchaînez trois appels :

  1. POST /v1/sites/{id}/shortlist avec {"keys": [...]} les ajoute à la sélection (elle en contient 100).
  2. POST /v1/sites/{id}/shortlist/to-prospects les transforme en prospects privés. Gratuit ; compte dans le quota de découverte de votre plan.
  3. POST /v1/prospects/find-emails avec les ids des prospects recherche les adresses manquantes (Pro, payant, confirmé comme ci-dessus). Il ne remplace jamais une adresse existante, et la liste d’opposition s’applique.

GET /v1/prospects?siteId=…&hasEmail=false liste ce qui manque encore ; la collection est paginée par curseur — renvoyez page.nextCursor tel quel dans cursor.

Inscrire dans une séquence de prospection

POST /v1/outreach/sequences programme la séquence en trois étapes (premier message et deux relances) pour un prospect, depuis une boîte connectée, avec tous les contrôles de l’application : réglages d’expéditeur complets, programme publié, adresse valide et absente de la liste d’opposition, et régime de conformité du pays du destinataire.

{
  "prospectId": "kJ2p8wQxYb_ig_1784140",
  "attestations": ["b2b_role_relevant", "legitimate_interest_assessed"]
}

Sans draft, c’est le brouillon enregistré pour ce prospect dans GetAff qui est utilisé. Chaque refus a son propre code — mailbox_required, draft_required, recipient_suppressed, compliance_blocked (avec details.missing), etc. — pour que votre tâche puisse consigner précisément pourquoi un prospect a été écarté. Aucun point d’accès n’envoie d’e-mail directement : l’envoi a lieu plus tard, depuis votre boîte, aux horaires programmés.

Relancer sans payer deux fois

Les écritures acceptent un en-tête Idempotency-Key. Une nouvelle tentative avec la même clé et le même corps dans les 24 heures rejoue le premier succès (Idempotent-Replayed: true) au lieu de s’exécuter à nouveau — ce qui compte pour une recherche qui a dépensé des crédits. Les erreurs ne sont pas conservées : corrigez la requête et relancez avec la même clé.

  • Dérivez la clé du sens de la tâche : nightly-<siteId>-<date>, pas une valeur aléatoire à chaque tentative.
  • La même clé avec un corps différent répond idempotency_conflict ; une requête encore en cours répond idempotency_in_progress.

Limites de débit et erreurs

Le débit est compté par clé sur une minute : 60 requêtes en gratuit, 600 en Pro, avec un plafond commun au compte, partagé par toutes les clés et le serveur MCP. Chaque réponse porte X-RateLimit-Limit, X-RateLimit-Remaining et les en-têtes IETF RateLimit-Policy / RateLimit ; une 429 ajoute Retry-After. Les plafonds propres à l’application s’appliquent aussi, comme six recherches de partenaires par minute.

Les erreurs sont des documents de problème RFC 9457 avec un error.code stable : branchez votre logique sur le code, jamais sur le message. Relancez les 429 et 503 (en respectant Retry-After) ; les 400, 401, 403 et 404 ne changeront pas en relançant. Les listes complètes sont dans Limites de débit et Erreurs.

Étapes suivantes

La page de démarrage présente le premier appel et les règles de versionnage, et la référence documente chaque point d’accès, générée à partir des schémas qu’appliquent les routes. Pour réagir quand un prospect répond plutôt que d’interroger l’API en boucle, ajoutez un webhook signé.

Documentation

Le contrat exact, généré à partir des schémas que les routes appliquent :

À lire ensuite