Aller au contenu

API REST · JSON · version 1

L'API publique v1.

Pilotez vos achats de liens depuis vos outils : catalogue, commandes payées depuis le solde, suivi de la publication et des contrôles. Les éditeurs traitent aussi leurs commandes par l'API.

Vous passez par un agent comme Claude ou Cursor ? Le catalogue et les commandes existent aussi sous forme d'outils MCP : voir Pour les agents.

Authentification
Clé API
Limite par clé
20 requêtes / 10 s
Clés actives
3 par compte
Paiement
Solde prépayé
URL de base
https://fiablink.fr/api/v1
Fia, la mascotte de Fiablink, tient un ordinateur portable

01

Démarrage rapide

Sommaire

Trois étapes séparent la création de votre compte de votre première réponse.

  1. 01

    Ouvrez un compte

    Un compte Fiablink suffit, que vous soyez annonceur ou éditeur. Les commandes passées par l'API sont réglées avec votre solde prépayé.

    Créer un compte
  2. 02

    Créez une clé

    Dans Paramètres, section Clés API, donnez un nom à la clé puis validez. Elle commence par fbl_ et ne s'affiche qu'une fois : copiez-la aussitôt.

    Ouvrir les paramètres
  3. 03

    Appelez GET /me

    La réponse confirme le compte rattaché à la clé et affiche son solde. Vous pouvez ensuite interroger le catalogue.

Requête
export FIABLINK_KEY="fbl_votre_cle"

curl "https://fiablink.fr/api/v1/me" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200
{
  "user": {
    "id": "cmg8u1x2c0000l5fz3k9d7q1a",
    "name": "Agence Exemple",
    "email": "contact@example.com",
    "companyName": "Agence Exemple SAS",
    "isPublisher": false,
    "isAdvertiser": true,
    "country": "FR"
  },
  "wallet": {
    "available_cents": 50000,
    "pending_cents": 0,
    "currency": "EUR"
  }
}

Dans tous les exemples de cette page, les identifiants, les domaines en .example et les montants sont fictifs.

02

Authentification

Sommaire

Chaque requête doit porter une clé API valide. Une clé agit au nom du compte qui l'a créée : mêmes commandes, même solde, mêmes sites.

En-têtes acceptés
X-Fiablink-Api-Key: fbl_xxxxxxxxxxxx
# ou
Authorization: Bearer fbl_xxxxxxxxxxxx
  • Envoyez l'un ou l'autre. S'ils sont présents tous les deux, X-Fiablink-Api-Key l'emporte.
  • Une clé donne accès à tous les points d'entrée, côté annonceur comme côté éditeur : il n'existe pas de périmètre par clé.
  • La clé n'est pas conservée en clair, seulement son empreinte et ses premiers caractères : elle ne peut pas être réaffichée. En cas de perte ou de fuite, révoquez-la dans Paramètres et créez-en une autre. La révocation prend effet immédiatement.
  • Une clé n'a pas de date d'expiration : révoquez celles qui ne servent plus.

Gardez la clé côté serveur

Stockez-la dans une variable d'environnement, jamais dans du code exécuté par un navigateur. L'API n'émet pas d'en-têtes CORS : elle est prévue pour des appels de serveur à serveur.
Réponses d'authentification
401missing_api_keyAucun des deux en-têtes n'est présent.
401invalid_api_keyClé inconnue ou révoquée.
403account_unavailableLe compte rattaché à la clé est suspendu ou n'existe plus.
429rate_limitedLimite de requêtes atteinte pour cette clé.
Réponse 401
{
  "error": {
    "code": "invalid_api_key",
    "message": "Invalid API key."
  }
}

03

Limites

Sommaire

Deux limites protègent le service : un débit par clé et un nombre de clés par compte. Chaque point d'entrée a aussi une taille de réponse fixe.

20 requêtes par 10 secondes

La limite s'applique à chaque clé. Au-delà, l'API répond 429 avec le code rate_limited, sans exécuter la requête.

Remise à zéro après 10 secondes de pause

Le compteur repart de zéro quand 10 secondes s'écoulent sans appel. Tant que vos appels se suivent à moins de 10 secondes d'intervalle, ils comptent dans la même fenêtre, plafonnée à 20. Après un 429, marquez une pause de 10 secondes.

3 clés actives par compte

Une par environnement ou par outil, par exemple. Pour en créer une de plus, révoquez d'abord une clé existante.

Volumes par appel
GET /sites24 sites par page.
GET /sites/{slug}50 pages positionnées et 90 points quotidiens au plus.
GET /orders50 commandes par page.
GET /orders/{id}Les 10 derniers contrôles du lien.
POST /orders50 lignes par requête, quantité de 1 à 50 par ligne.
GET /publisher/ordersLes 100 commandes les plus récentes, sans pagination.
GET /walletLes 50 derniers mouvements.

04

Idempotence

Sommaire

Un délai dépassé ou une coupure réseau ne doit pas créer deux fois la même commande. Ajoutez un en-tête Idempotency-Key à chaque création : un nouvel essai renverra la première réponse au lieu de recommencer.

Comportement de l'en-tête Idempotency-Key
Première requête avec cette cléExécution normale : 201 et commandes créées.
Même clé et même corps, dans les 24 heuresRéponse d'origine renvoyée à l'identique, avec l'en-tête Idempotent-Replayed: true. Rien n'est recréé ni redébité.
Même clé et même corps, pendant que la première requête s'exécuteLa seconde attend la réponse de la première et la renvoie, avec Idempotent-Replayed: true. Après 15 secondes d'attente : 409 idempotency_in_progress, à rejouer.
Même clé, corps différent422 idempotency_mismatch.
Première requête refusée (400, 402)Rien n'est mémorisé : la clé reste utilisable.
Première requête en erreur 500L'erreur est mémorisée : la même clé renverra 500. Vérifiez vos commandes avec GET /orders avant de recommencer avec une nouvelle clé.
Même clé après 24 heuresLa clé est oubliée : la requête s'exécute à nouveau.
En-tête
Idempotency-Key: 6f1c2a9e-4b7d-4c1e-9a53-2d8e7f0b1c64
Réponse 422
{
  "error": {
    "code": "idempotency_mismatch",
    "message": "Idempotency-Key déjà utilisée avec un corps différent"
  }
}
  • L'en-tête est pris en compte sur POST /orders, le seul appel qui débite votre solde. Il est sans effet sur les autres points d'entrée.
  • La comparaison porte sur le corps brut, au caractère près : renvoyez exactement le même JSON.
  • Une clé d'idempotence vaut pour votre compte, toutes clés API confondues, et ne dépasse pas 128 caractères.

05

Points d'entrée

Sommaire

11 points d'entrée, tous sous la même URL de base. Chaque ligne du tableau renvoie à sa référence détaillée.

URL de base
https://fiablink.fr/api/v1
Format
Requêtes et réponses en JSON. Les réponses portent Cache-Control: no-store : elles ne sont jamais mises en cache.
Montants
Entiers en centimes d'euro, hors taxes : 13800 vaut 138,00 €. La TVA est facturée au rechargement du solde.
Dates
ISO 8601 en UTC, par exemple 2026-10-03T09:12:45.120Z.
Identifiants
Chaînes opaques (id, slug), à réutiliser telles quelles.
Casse des champs
Réponses en snake_case, sauf l'objet user de GET /me. En entrée, les filtres du catalogue et les lignes de POST /orders sont en camelCase (minClicks, siteId) ; les autres champs sont en snake_case (promo_code, published_url).
Pagination
Paramètre page à partir de 1 sur GET /sites et GET /orders, avec une taille de page fixe.
Points d'entrée de l'API v1
GET/meCompte rattaché à la clé et solde.
GET/walletSolde et 50 derniers mouvements.
GET/sitesCatalogue des sites en vente, filtrable et paginé.
GET/sites/{slug}Fiche d'un site : prix, pages positionnées, clics quotidiens.
GET/ordersVos commandes d'annonceur, des plus récentes aux plus anciennes.
POST/ordersCrée et paie une ou plusieurs commandes depuis le solde, en une seule opération.
GET/orders/{id}Détail d'une commande : statut, événements, derniers contrôles du lien.
DELETE/orders/{id}Annule une commande que l'éditeur n'a pas encore acceptée.
GET/publisher/sitesÉditeur : vos sites et leurs prix nets.
GET/publisher/ordersÉditeur : commandes reçues sur vos sites.
POST/publisher/orders/{id}Éditeur : accepter, refuser, proposer un autre prix ou déclarer la publication.

Ce qui se fait depuis votre espace

Recharger le solde, accepter ou refuser une contre-offre, échanger des messages sur une commande, ouvrir un litige, gérer vos sites et leurs prix, demander un retrait : ces actions ne passent pas par l'API.

06

Compte et solde

Sommaire

Deux lectures pour vérifier une clé, connaître le solde disponible avant de commander et rapprocher vos mouvements.

GET/me

Compte rattaché à la clé et solde.

Aucun paramètre.

  • user : le compte rattaché à la clé, avec ses rôles (isAdvertiser, isPublisher) et son pays de facturation.
  • wallet.available_cents : solde utilisable pour vos commandes.
  • wallet.pending_cents : gains d'éditeur en séquestre, pas encore disponibles.
Requête
curl "https://fiablink.fr/api/v1/me" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200
{
  "user": {
    "id": "cmg8u1x2c0000l5fz3k9d7q1a",
    "name": "Agence Exemple",
    "email": "contact@example.com",
    "companyName": "Agence Exemple SAS",
    "isPublisher": false,
    "isAdvertiser": true,
    "country": "FR"
  },
  "wallet": {
    "available_cents": 50000,
    "pending_cents": 0,
    "currency": "EUR"
  }
}

GET/wallet

Solde et 50 derniers mouvements.

Aucun paramètre. Les mouvements sont classés du plus récent au plus ancien.

  • available_delta_cents et pending_delta_cents : variation de chaque solde, négative pour un débit.
  • order_id : renseigné quand le mouvement porte sur une commande précise (remboursement, supplément de contre-offre, vente d'éditeur). Il vaut null sinon, y compris pour le paiement d'une création, qui peut regrouper plusieurs commandes.

Valeurs de type

DEPOSIT
rechargement du solde
PURCHASE
paiement de commandes
REFUND
remboursement d'une commande
SALE_HOLD
vente d'éditeur placée en séquestre
SALE_RELEASE
vente d'éditeur libérée
WITHDRAWAL_HOLD
demande de retrait
WITHDRAWAL_PAID
retrait payé
WITHDRAWAL_CANCELLED
retrait annulé, fonds restitués
WITHDRAWAL_FEE
frais de retrait (valeur réservée, aucun mouvement de ce type aujourd'hui)
GIFT
crédit offert
AFFILIATE_COMMISSION
commission d'affiliation
ADJUSTMENT
ajustement
Requête
curl "https://fiablink.fr/api/v1/wallet" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200 (extrait : 2 mouvements sur 50 au plus)
{
  "available_cents": 36200,
  "pending_cents": 0,
  "currency": "EUR",
  "entries": [
    {
      "id": "cmgb1q90b000bl5fz7d3s8x4n",
      "type": "PURCHASE",
      "available_delta_cents": -13800,
      "pending_delta_cents": 0,
      "description": "Commande 1 ligne",
      "order_id": null,
      "created_at": "2026-10-03T09:12:45.120Z"
    },
    {
      "id": "cmg9k2r7h0003l5fz1v6c9y0m",
      "type": "DEPOSIT",
      "available_delta_cents": 50000,
      "pending_delta_cents": 0,
      "description": "Rechargement du solde",
      "order_id": null,
      "created_at": "2026-10-01T14:02:10.482Z"
    }
  ]
}

07

Catalogue

Sommaire

Le catalogue ne contient que les sites en vente. Les prix renvoyés sont ceux que vous payez, hors taxes, frais de plateforme compris.

GET/sites

Catalogue des sites en vente, filtrable et paginé.

Filtres de GET /sites
qtexteRecherche dans la thématique des sites, sur 120 caractères au plus. Le nom et la description ne sont interrogés que pour les sites dont le domaine est visible.
categorytexteIdentifiant de thématique, parmi la liste donnée plus bas.
countrytexteCode pays du site, en majuscules : FR, BE, CH, CA…
languagetexteCode langue du site, en minuscules : fr, en, es…
minPrice, maxPricenombreBornes du prix de l'article, en euros hors taxes et non en centimes. Le filtre est approché : il s'applique au prix net de l'éditeur, converti au taux de frais de la marketplace.
minClicksentierClics organiques mensuels minimum : le filtre porte sur gsc_clicks_90d divisé par 3.
minTf, minDrentierSeuils minimum de TF et de DR, métriques tierces données à titre indicatif.
gscOnlybooléenSites qui ont connecté leur Search Console (gsc_verified à true).
networkOnlybooléenSites du réseau Fiablink uniquement.
dofollowbooléenSites qui acceptent les liens dofollow.
sorttexteOrdre de tri, parmi les valeurs données plus bas.
pageentierNuméro de page, à partir de 1. 24 sites par page.

Valeurs des filtres

Un filtre booléen s'active avec true ou 1 ; false, 0 ou l'absence du paramètre le laissent inactif. Un paramètre vide est ignoré. Une valeur invalide (booléen mal écrit, tri inconnu, nombre mal formé ou négatif, page inférieure à 1) renvoie 400 validation_error, et message nomme le paramètre en cause.

Valeurs de sort

relevance
sites mis en avant, puis Search Console connectée, puis clics et ventes décroissants
price_asc
prix de l'article croissant, d'après le prix net de l'éditeur
price_desc
prix de l'article décroissant, d'après le prix net de l'éditeur
clicks_desc
clics Search Console décroissants
tf_desc
TF décroissant
newest
sites ajoutés le plus récemment

Search Console : connexion pas encore activée

La connexion Search Console des éditeurs n'est pas encore activée sur la plateforme. gsc_verified, positioned_pages et daily_clicks ne sont renseignés que sur les sites qui ont connecté leur Search Console.
Requête
curl "https://fiablink.fr/api/v1/sites?category=maison-jardin&minClicks=1000&gscOnly=true&sort=clicks_desc" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200 (extrait : un site sur les 24 de la page, valeurs fictives)
{
  "total": 37,
  "page": 1,
  "pages": 2,
  "items": [
    {
      "id": "cmg8v4m2p0007l5fzc1d5t6ru",
      "slug": "cmg8v4m2p0007l5fzc1d5t6ru",
      "name": "Site D5T6RU",
      "domain": null,
      "domain_masked": "••••••.example",
      "country": "FR",
      "language": "fr",
      "categories": ["maison-jardin"],
      "tier": "B",
      "is_network": false,
      "gsc_verified": true,
      "gsc_clicks_90d": 5400,
      "gsc_impressions_90d": 212000,
      "tf": 28,
      "cf": 31,
      "dr": 35,
      "da": 30,
      "referring_domains": 240,
      "allows_dofollow": true,
      "mention_policy": "OPTIONAL",
      "turnaround_days": 3,
      "prices": {
        "article_cents": 13800,
        "insertion_cents": 9200,
        "homepage_month_cents": null,
        "platform_fee_cents": 1800
      }
    }
  ]
}
Champs d'un site
name, slugQuand le domaine est visible, name vaut le domaine ; tant qu'il est masqué, c'est une référence anonyme (« Site A1B2C3 »). Le slug d'un site tiers au domaine masqué est son id, avant comme après la révélation du domaine ; celui d'un site du réseau est un identifiant lisible.
domain, domain_maskeddomain vaut null tant que le domaine est masqué ; domain_masked n'en donne alors que l'extension. Le domaine est visible pour les sites du réseau Fiablink et pour ceux où vous avez déjà une commande publiée.
tierPalier de trafic calculé sur gsc_clicks_90d : AMORCAGE, A, B, C ou D. Sans donnée, le palier est AMORCAGE.
gsc_*gsc_verified vaut true sur les sites qui ont connecté leur Search Console : leurs clics et impressions sur 90 jours en proviennent. Sur les autres sites, ces deux champs valent null ou reprennent une valeur saisie par notre équipe, sans connexion pour la vérifier.
tf, cf, dr, da, referring_domainsMétriques tierces, indicatives ; null si elles ne sont pas renseignées.
allows_dofollow, mention_policy, turnaround_daysRègles de l'éditeur : dofollow accepté ou non, mention « Article partenaire » (ALWAYS, OPTIONAL ou NEVER), délai de publication annoncé en jours.
pricesPrix acheteur hors taxes : prix net de l'éditeur et frais de plateforme compris. platform_fee_cents isole les frais inclus dans article_cents. insertion_cents et homepage_month_cents valent null quand le format n'est pas vendu.

Valeurs de category

  • maison-jardinMaison, travaux & jardin
  • immobilierImmobilier
  • business-b2bBusiness, B2B & entrepreneuriat
  • tech-logicielsTech & logiciels
  • marketing-seoMarketing & SEO
  • finance-assuranceFinance & assurance
  • sante-bien-etreSanté & bien-être
  • sportSport
  • voyage-tourismeVoyage & tourisme
  • auto-motoAuto & moto
  • mode-beauteMode & beauté
  • famille-educationFamille & éducation
  • cuisine-gastronomieCuisine & gastronomie
  • culture-loisirsCulture & loisirs
  • juridiqueJuridique
  • emploi-formationEmploi & formation
  • animauxAnimaux
  • actualites-generalisteActualités & généraliste
  • ecommerce-shoppingE-commerce & shopping
  • energie-environnementÉnergie & environnement
  • transport-logistiqueTransport & logistique
  • jeux-argentJeux d'argent (secteur sensible)

GET/sites/{slug}

Fiche d'un site : prix, pages positionnées, clics quotidiens.

Paramètre de chemin
slug · requistexteChamp slug renvoyé par GET /sites.
  • positioned_pages : les pages ouvertes à l'insertion, classées par impressions décroissantes. Leur id sert de positionedPageId à la commande ; price_cents est le prix acheteur hors taxes d'un lien dans cette page, promotion en cours du site déduite, comme à la commande.
  • url_masked : adresse complète de la page quand le domaine est visible, forme masquée sinon. Tant que le domaine est masqué, title est un simple numéro d'ordre (« Page positionnée n° 1 »).
  • daily_clicks : clics et impressions Search Console jour par jour, sur les 90 jours les plus récents enregistrés, par date croissante. Comme positioned_pages, ce tableau est vide pour un site qui n'a pas connecté sa Search Console.
  • La fiche ne reprend pas tous les champs de la liste : domain_masked, referring_domains, allows_dofollow, mention_policy, turnaround_days et platform_fee_cents n'y figurent pas.
  • Un identifiant inconnu, ou un site qui n'est plus en vente, renvoie 404 not_found.
Requête
curl "https://fiablink.fr/api/v1/sites/cmg8v4m2p0007l5fzc1d5t6ru" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200 (extrait, valeurs fictives)
{
  "id": "cmg8v4m2p0007l5fzc1d5t6ru",
  "slug": "cmg8v4m2p0007l5fzc1d5t6ru",
  "name": "Site D5T6RU",
  "domain": null,
  "country": "FR",
  "language": "fr",
  "categories": ["maison-jardin"],
  "tier": "B",
  "is_network": false,
  "gsc_verified": true,
  "gsc_clicks_90d": 5400,
  "gsc_impressions_90d": 212000,
  "tf": 28,
  "cf": 31,
  "dr": 35,
  "da": 30,
  "prices": {
    "article_cents": 13800,
    "insertion_cents": 9200,
    "homepage_month_cents": null
  },
  "positioned_pages": [
    {
      "id": "cmg8v9q1d000cl5fz8w2n4h7b",
      "title": "Page positionnée n° 1",
      "url_masked": "••••••.example/…",
      "impressions_90d": 18400,
      "clicks_90d": 620,
      "avg_position": 6.4,
      "price_cents": 10350
    }
  ],
  "daily_clicks": [
    {
      "date": "2026-07-05T00:00:00.000Z",
      "clicks": 58,
      "impressions": 2310
    },
    {
      "date": "2026-07-06T00:00:00.000Z",
      "clicks": 63,
      "impressions": 2402
    }
  ]
}

08

Commandes

Sommaire

Une commande correspond à un lien. Sur un site tiers, elle attend la réponse de l'éditeur ; sur le réseau Fiablink et pour les packs, elle est acceptée d'emblée. Viennent ensuite la production, la publication, le contrôle du lien puis la clôture.

POST/orders

Crée et paie une ou plusieurs commandes depuis le solde, en une seule opération.

Corps de POST /orders
items · requistableauDe 1 à 50 lignes de commande, décrites dans le tableau suivant.
payment_methodtexteWALLET, seule valeur acceptée et valeur par défaut : le paiement se fait par le solde.
promo_codetexteCode promo. Refusé, il fait échouer toute la requête ; accepté, sa remise est répartie sur les commandes créées.
Champs d'une ligne de commande
productType · requistexteARTICLE (article sponsorisé), INSERTION (lien inséré dans une page déjà positionnée), HOMEPAGE (lien en page d'accueil, pour un mois), PACK (pack du réseau Fiablink).
siteIdtexteChamp id du site dans le catalogue. Requis pour ARTICLE, INSERTION et HOMEPAGE.
positionedPageIdtextePour INSERTION : identifiant d'une page positionnée du site. Sans lui, le tarif d'insertion du site s'applique, s'il en propose un.
packSlugtexteRequis pour PACK : decouverte, croissance ou autorite.
quantityentierDe 1 à 50, 1 par défaut. Chaque unité crée une commande distincte.
targetUrl · requisURLPage vers laquelle pointe le lien, sur 2 048 caractères au plus.
anchor · requistexteTexte du lien, de 1 à 200 caractères.
reltexteDOFOLLOW (par défaut), SPONSORED (rel="sponsored"), NOFOLLOW (rel="nofollow"). Un lien conforme (SPONSORED ou NOFOLLOW) est remisé de 30 % sur les sites du réseau Fiablink et sur les packs, pas sur les autres sites.
contentModetextePLATFORM_WRITES (par défaut, rédaction incluse), PUBLISHER_WRITES (rédaction par l'éditeur), BUYER_PROVIDES (vous fournissez le texte).
mentionbooléenMention « Article partenaire » sur l'article. true par défaut ; envoyez un booléen JSON, pas une chaîne.
brieftexteConsignes de rédaction, sur 5 000 caractères au plus.
providedContenttexteVotre texte, avec BUYER_PROVIDES, sur 50 000 caractères au plus.
Requête : un article sponsorisé
curl -X POST "https://fiablink.fr/api/v1/orders" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY" \
  -H "Idempotency-Key: 6f1c2a9e-4b7d-4c1e-9a53-2d8e7f0b1c64" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "siteId": "cmg8v4m2p0007l5fzc1d5t6ru",
        "productType": "ARTICLE",
        "targetUrl": "https://www.example.com/assurance-habitation",
        "anchor": "assurance habitation",
        "rel": "DOFOLLOW",
        "contentMode": "PLATFORM_WRITES",
        "mention": true,
        "brief": "Angle : comparer les garanties des contrats multirisques."
      }
    ]
  }'
Réponse 201 (valeurs fictives)
{
  "payment_id": "cmgb1q8yk0009l5fz5r6t1a2c",
  "total_cents": 13800,
  "orders": [
    {
      "id": "cmgb1q8zs000al5fzk2m9v3ep",
      "number": "FBL-2026-000042",
      "status": "AWAITING_PUBLISHER",
      "product_type": "ARTICLE",
      "site_id": "cmg8v4m2p0007l5fzc1d5t6ru",
      "target_url": "https://www.example.com/assurance-habitation",
      "anchor": "assurance habitation",
      "rel": "DOFOLLOW",
      "price_cents": 13800,
      "publisher_net_cents": 12000,
      "platform_fee_cents": 1800,
      "published_url": null,
      "published_at": null,
      "guarantee_until": null,
      "last_check_at": null,
      "last_check_ok": null,
      "created_at": "2026-10-03T09:12:45.120Z"
    }
  ]
}
Autre corps : 3 liens du Pack Découverte en lien conforme, soit 3 commandes à 24,50 € HT chacune
{
  "items": [
    {
      "productType": "PACK",
      "packSlug": "decouverte",
      "quantity": 3,
      "targetUrl": "https://www.example.com/",
      "anchor": "Exemple",
      "rel": "SPONSORED"
    }
  ]
}
  • Tout ou rien : si une ligne est refusée ou si le solde ne couvre pas le total, aucune commande n'est créée et rien n'est débité.
  • Les prix sont calculés au moment de l'appel puis figés dans la commande. total_cents est le montant hors taxes débité du solde ; la facture correspondante est disponible dans votre espace, rubrique Factures.
  • Statut de départ : AWAITING_PUBLISHER sur un site tiers, ACCEPTED sur le réseau Fiablink et pour les packs. Les packs et leur prix par lien sont détaillés sur la page Tarifs.
  • Les règles du site s'appliquent : dofollow refusé, mention imposée, texte fourni ou rédaction par l'éditeur non proposés. L'API ne les expose pas toutes à l'avance ; un refus renvoie 400 order_error avec le motif dans message. PLATFORM_WRITES est accepté partout.
  • Erreurs propres à cet appel : 400 validation_error (champ manquant ou invalide), 400 order_error, 402 insufficient_funds, 409 idempotency_in_progress, 422 idempotency_mismatch.

Le panier de votre compte n'est pas touché

Une création ne passe pas par le panier de votre compte : les lignes que vous y avez ajoutées depuis le site y restent, et le code promo enregistré sur ce panier ne s'applique pas à l'appel. Deux créations envoyées en même temps pour un même compte passent l'une après l'autre.

GET/orders

Vos commandes d'annonceur, des plus récentes aux plus anciennes.

Paramètres de GET /orders
statustexteFiltre sur un statut exact, parmi ceux du tableau des statuts. Toute autre valeur renvoie 400 validation_error.
pageentierNuméro de page, à partir de 1. 50 commandes par page. Une valeur non numérique ou inférieure à 1 renvoie 400 validation_error.
  • price_cents : prix hors taxes de la commande, remise déduite. publisher_net_cents et platform_fee_cents en donnent le détail avant remise.
  • Les champs de publication valent null jusqu'à la publication, ceux du contrôle (last_check_at, last_check_ok) jusqu'au premier contrôle.
  • site_id vaut null pour une commande de pack.
Requête
curl "https://fiablink.fr/api/v1/orders?status=VERIFIED&page=1" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200 (extrait : une commande sur 50 au plus)
{
  "total": 12,
  "page": 1,
  "items": [
    {
      "id": "cmgb1q8zs000al5fzk2m9v3ep",
      "number": "FBL-2026-000042",
      "status": "VERIFIED",
      "product_type": "ARTICLE",
      "site_id": "cmg8v4m2p0007l5fzc1d5t6ru",
      "target_url": "https://www.example.com/assurance-habitation",
      "anchor": "assurance habitation",
      "rel": "DOFOLLOW",
      "price_cents": 13800,
      "publisher_net_cents": 12000,
      "platform_fee_cents": 1800,
      "published_url": "https://habitat-magazine.example/guide-assurance-habitation",
      "published_at": "2026-10-06T08:30:00.000Z",
      "guarantee_until": "2028-10-06T08:30:00.000Z",
      "last_check_at": "2026-10-07T04:31:12.874Z",
      "last_check_ok": true,
      "created_at": "2026-10-03T09:12:45.120Z"
    }
  ]
}

GET/orders/{id}

Détail d'une commande : statut, événements, derniers contrôles du lien.

Paramètre de chemin
id · requistexteChamp id de la commande.
  • events : historique par date croissante. Types possibles : created, paid, accepted, counter_offer, counter_offer_accepted, draft_generated, published, verified, completed, refused, cancelled, refunded, disputed, dispute_resolved.
  • checks : les 10 derniers contrôles, du plus récent au plus ancien. ok est vrai quand la page répond, que le lien vers votre URL est présent avec l'attribut demandé et que la page n'est pas en noindex. rel_found reprend l'attribut rel relevé sur le lien, ou null s'il n'en porte pas.
  • counter_offer_cents : prix net demandé par l'éditeur lors d'une contre-offre, hors frais de plateforme ; null sinon.
  • Une commande inconnue, ou qui n'a pas été passée par votre compte, renvoie 404 not_found.
Requête
curl "https://fiablink.fr/api/v1/orders/cmgb1q8zs000al5fzk2m9v3ep" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200 (valeurs fictives)
{
  "id": "cmgb1q8zs000al5fzk2m9v3ep",
  "number": "FBL-2026-000042",
  "status": "VERIFIED",
  "product_type": "ARTICLE",
  "site_id": "cmg8v4m2p0007l5fzc1d5t6ru",
  "target_url": "https://www.example.com/assurance-habitation",
  "anchor": "assurance habitation",
  "rel": "DOFOLLOW",
  "price_cents": 13800,
  "published_url": "https://habitat-magazine.example/guide-assurance-habitation",
  "published_at": "2026-10-06T08:30:00.000Z",
  "guarantee_until": "2028-10-06T08:30:00.000Z",
  "counter_offer_cents": null,
  "events": [
    { "type": "created", "at": "2026-10-03T09:12:45.120Z" },
    { "type": "paid", "at": "2026-10-03T09:12:45.134Z" },
    { "type": "accepted", "at": "2026-10-03T15:40:02.310Z" },
    { "type": "published", "at": "2026-10-06T08:30:00.000Z" },
    { "type": "verified", "at": "2026-10-06T08:30:04.512Z" }
  ],
  "checks": [
    {
      "at": "2026-10-07T04:31:12.874Z",
      "ok": true,
      "http_status": 200,
      "link_found": true,
      "rel_found": null,
      "noindex": false
    },
    {
      "at": "2026-10-06T08:30:04.371Z",
      "ok": true,
      "http_status": 200,
      "link_found": true,
      "rel_found": null,
      "noindex": false
    }
  ]
}

DELETE/orders/{id}

Annule une commande que l'éditeur n'a pas encore acceptée.

  • Possible aux statuts AWAITING_PUBLISHER, COUNTER_OFFER et PENDING_PAYMENT. Le montant payé est recrédité sur votre solde.
  • Une commande sur le réseau Fiablink ou un pack démarre au statut ACCEPTED : elle ne peut pas être annulée par l'API.
  • Dans tous les autres cas, y compris pour un identifiant inconnu, la réponse est 400 cannot_cancel.
Requête
curl -X DELETE "https://fiablink.fr/api/v1/orders/cmgb1q8zs000al5fzk2m9v3ep" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200
{
  "id": "cmgb1q8zs000al5fzk2m9v3ep",
  "status": "CANCELLED"
}

Statuts d'une commande

Signification de chaque statut
PENDING_PAYMENTPaiement par carte en attente de confirmation. Ne concerne que les commandes passées sur le site : par l'API, le paiement se fait par le solde.
PAIDValeur réservée : aucune commande ne porte ce statut aujourd'hui.
AWAITING_PUBLISHERPayée, en attente de l'éditeur. Il a 5 jours pour accepter, refuser ou proposer un autre prix ; sans réponse, la commande est annulée et remboursée sur votre solde.
COUNTER_OFFERL'éditeur propose un autre prix (counter_offer_cents). Acceptez ou refusez depuis votre espace, ou annulez par l'API.
ACCEPTEDAcceptée, à produire. C'est le statut de départ des commandes passées sur le réseau Fiablink et des packs.
CONTENT_PENDINGValeur réservée : aucune commande ne porte ce statut aujourd'hui.
IN_PRODUCTIONAcceptée par l'éditeur, article en préparation.
REVIEWArticle rédigé, en relecture avant publication.
PUBLISHEDPublication déclarée (published_url), en attente d'un contrôle conforme du lien. La garantie de 24 mois court à partir de cette date.
VERIFIEDLien contrôlé conforme : page accessible, lien présent vers votre URL, attribut demandé respecté, pas de noindex.
COMPLETEDCommande close, au plus tôt 7 jours après la vérification. Le lien reste contrôlé jusqu'à guarantee_until.
REFUSEDRefusée par l'éditeur. Le montant payé est recrédité sur votre solde.
CANCELLEDAnnulée, par vous ou faute de réponse de l'éditeur. Le montant payé est recrédité sur votre solde.
REFUNDEDRemboursée sur votre solde par notre équipe.
DISPUTEDLitige ouvert depuis votre espace, en cours de traitement.

09

Côté éditeur

Sommaire

Ces points d'entrée portent sur les sites dont vous êtes propriétaire et sur les commandes qui leur sont adressées. Avec la clé d'un compte sans site, les listes sont simplement vides.

GET/publisher/sites

Éditeur : vos sites et leurs prix nets.

Aucun paramètre. Tous vos sites sont renvoyés, quel que soit leur statut, du plus récent au plus ancien.

  • Les prix sont vos prix nets, en centimes : ce que vous percevez par vente. Les prix affichés aux annonceurs se lisent dans GET /sites.
  • verified : propriété du site vérifiée. gsc_verified : Search Console connectée.

Valeurs de status

DRAFT
brouillon
PENDING_VERIFICATION
propriété à vérifier
PENDING_REVIEW
en modération
ACTIVE
en vente
PAUSED
en pause
SUSPENDED
suspendu
REJECTED
refusé
Requête
curl "https://fiablink.fr/api/v1/publisher/sites" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200 (valeurs fictives)
{
  "items": [
    {
      "id": "cmg8v4m2p0007l5fzc1d5t6ru",
      "domain": "habitat-magazine.example",
      "status": "ACTIVE",
      "verified": true,
      "gsc_verified": true,
      "gsc_clicks_90d": 5400,
      "article_price_cents": 12000,
      "insertion_price_cents": 8000,
      "homepage_price_cents": null,
      "sales_count": 14
    }
  ]
}

GET/publisher/orders

Éditeur : commandes reçues sur vos sites.

Paramètre de GET /publisher/orders
statustexteFiltre sur un statut exact, parmi ceux du tableau des statuts. Toute autre valeur renvoie 400 validation_error.
  • Sans filtre, tous les statuts sont renvoyés, sauf PENDING_PAYMENT : une commande dont le paiement n'est pas confirmé n'est jamais transmise à l'éditeur. Filtrez sur AWAITING_PUBLISHER pour ne voir que les commandes à traiter.
  • La réponse contient ce qu'il faut pour publier (adresse cible, ancre, attribut, mention, brief, texte fourni) et votre montant net. Elle ne contient ni le prix payé par l'annonceur ni ses coordonnées.
  • deadline_at : échéance de publication, fixée à l'acceptation.
Requête
curl "https://fiablink.fr/api/v1/publisher/orders?status=AWAITING_PUBLISHER" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY"
Réponse 200 (extrait : une commande sur 100 au plus)
{
  "items": [
    {
      "id": "cmgb1q8zs000al5fzk2m9v3ep",
      "number": "FBL-2026-000042",
      "status": "AWAITING_PUBLISHER",
      "site_domain": "habitat-magazine.example",
      "product_type": "ARTICLE",
      "target_url": "https://www.example.com/assurance-habitation",
      "anchor": "assurance habitation",
      "rel": "DOFOLLOW",
      "mention_requested": true,
      "content_mode": "PLATFORM_WRITES",
      "brief": "Angle : comparer les garanties des contrats multirisques.",
      "provided_content": null,
      "publisher_net_cents": 12000,
      "deadline_at": null,
      "published_url": null,
      "created_at": "2026-10-03T09:12:45.120Z"
    }
  ]
}

POST/publisher/orders/{id}

Éditeur : accepter, refuser, proposer un autre prix ou déclarer la publication.

Actions de POST /publisher/orders/{id}
acceptChamps : AucunStatuts de départ : AWAITING_PUBLISHER, COUNTER_OFFEREffet : La commande passe à IN_PRODUCTION et reçoit son échéance de publication, d'après le délai annoncé pour le site. Depuis COUNTER_OFFER, elle repart au prix d'origine.
refuseChamps : reason : motif, de 3 à 1 000 caractèresStatuts de départ : AWAITING_PUBLISHER, COUNTER_OFFER, ACCEPTED, IN_PRODUCTIONEffet : La commande passe à REFUSED ; l'annonceur est remboursé sur son solde.
counter_offerChamps : new_net_cents : entier, en centimes ; note : facultative, 1 000 caractères au plusStatuts de départ : AWAITING_PUBLISHEREffet : La commande passe à COUNTER_OFFER jusqu'à la décision de l'annonceur. Le nouveau prix net doit dépasser le prix actuel, sans excéder 3 fois ce prix.
deliverChamps : published_url : adresse de l'article publiéStatuts de départ : ACCEPTED, IN_PRODUCTION, REVIEWEffet : La commande passe à PUBLISHED et le lien est contrôlé aussitôt. L'adresse doit appartenir au domaine du site commandé, sous-domaines compris.
  • Un contrôle conforme fait passer la commande à VERIFIED : votre gain entre en séquestre, puis devient disponible 7 jours plus tard. Les retraits se demandent depuis votre espace.
  • La réponse confirme seulement la prise en compte. Relisez la commande dans GET /publisher/orders pour connaître son nouveau statut.
  • Tant que le lien n'est pas publié, les coordonnées (e-mail, téléphone, adresse web) et le nom de votre site sont remplacés par « [masqué] » dans reason et note : l'annonceur les lit avant la publication.
  • Corps mal formé : 400 validation_error. Action impossible à ce statut, commande inconnue ou qui ne vous est pas adressée : 400 order_error, avec le motif dans message.
  • L'en-tête Idempotency-Key est sans effet ici : une action déjà appliquée est refusée par le contrôle de statut.
Un corps par action
{
  "action": "accept"
}

{
  "action": "refuse",
  "reason": "Thématique hors ligne éditoriale"
}

{
  "action": "counter_offer",
  "new_net_cents": 15000,
  "note": "Article long demandé"
}

{
  "action": "deliver",
  "published_url": "https://habitat-magazine.example/guide-assurance-habitation"
}
Requête : déclarer la publication
curl -X POST "https://fiablink.fr/api/v1/publisher/orders/cmgb1q8zs000al5fzk2m9v3ep" \
  -H "X-Fiablink-Api-Key: $FIABLINK_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "deliver",
    "published_url": "https://habitat-magazine.example/guide-assurance-habitation"
  }'
Réponse 200
{
  "id": "cmgb1q8zs000al5fzk2m9v3ep",
  "ok": true
}

10

Erreurs

Sommaire

Toute erreur renvoie le même objet JSON : un code stable, destiné à votre programme, et un message destiné à la lecture.

Format (ici, un 404)
{
  "error": {
    "code": "not_found",
    "message": "Commande introuvable"
  }
}
  • Branchez votre logique sur le statut HTTP et sur code, pas sur message : les messages peuvent évoluer. Ceux de l'authentification (401, 429) sont en anglais.
  • Les appels réussis renvoient 200, et 201 pour POST /orders.
Codes d'erreur
400invalid_jsonLe corps de la requête n'est pas du JSON valide.
400validation_errorChamp du corps ou paramètre de requête manquant ou invalide : tri inconnu, statut inexistant, page non numérique. Sur POST /orders et sur les listes (GET /sites, GET /orders, GET /publisher/orders), message nomme les champs ou paramètres concernés.
400order_errorRègle métier non respectée : site indisponible, option refusée par l'éditeur, code promo refusé, action impossible au statut actuel.
400cannot_cancelDELETE /orders/{id} : commande déjà acceptée ou close, ou introuvable.
400bad_request, errorAutres requêtes refusées, dont une Idempotency-Key de plus de 128 caractères.
401missing_api_keyAucune clé dans la requête.
401invalid_api_keyClé inconnue ou révoquée.
402insufficient_fundsSolde insuffisant pour POST /orders. Rien n'est créé ni débité.
403account_unavailableCompte suspendu ou inexistant.
404not_foundSite (GET /sites/{slug}) ou commande (GET /orders/{id}) introuvable.
409idempotency_in_progressUne requête portant la même Idempotency-Key est encore en cours après 15 secondes d'attente. Rejouez-la.
422idempotency_mismatchIdempotency-Key déjà utilisée avec un autre corps.
429rate_limitedLimite de requêtes atteinte pour la clé.
500internal_errorErreur inattendue de notre côté.
402 : solde insuffisant
{
  "error": {
    "code": "insufficient_funds",
    "message": "Solde insuffisant : rechargez votre compte ou payez par carte"
  }
}
400 : règle du site
{
  "error": {
    "code": "order_error",
    "message": "Ce site n'accepte pas les liens dofollow"
  }
}
400 : validation
{
  "error": {
    "code": "validation_error",
    "message": "items.0.targetUrl: URL invalide; items.0.anchor: Ancre requise"
  }
}
429 : limite atteinte
{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded."
  }
}

11

Bonnes pratiques

Sommaire

Quelques règles simples pour une intégration qui ne double pas une commande, ne perd pas un paiement et reste sous les limites.

Une clé d'idempotence par commande

Générez un identifiant unique pour chaque création, enregistrez-le avec votre commande interne et renvoyez-le à l'identique à chaque nouvel essai. Vous pouvez rejouer sans attendre : une requête rejouée pendant que la première s'exécute attend sa réponse au lieu de commander une seconde fois.

Traitez le 402 sans rien perdre

Sur un 402 insufficient_funds, aucune commande n'est créée et rien n'est débité. Rechargez votre solde depuis votre espace, puis renvoyez la même requête avec la même clé d'idempotence. Avant un lot important, comparez le total attendu à available_cents.

Interrogez à un rythme raisonnable

Les statuts évoluent au rythme des éditeurs et des contrôles de lien, qui sont quotidiens. Un relevé de GET /orders toutes les 15 à 30 minutes suffit ; préférez-le à une boucle sur chaque commande. Des appels espacés de plus de 10 secondes n'atteignent jamais la limite.

Plusieurs liens, une seule requête

Pour plusieurs liens, regroupez-les dans une même requête POST /orders, jusqu'à 50 lignes : elles sont payées ensemble, ou aucune ne l'est. Deux requêtes simultanées pour un même compte passent l'une après l'autre.

Prévoyez l'inconnu

Gardez un cas par défaut pour un statut de commande, un type de mouvement ou un code d'erreur que votre programme ne connaît pas, et ignorez les champs supplémentaires.

Renouvelez vos clés sans coupure

Créez la nouvelle clé, déployez-la, puis révoquez l'ancienne : les 3 clés actives par compte le permettent. Révoquez sans attendre toute clé exposée.

Prêt pour votre premier appel ?

Créez une clé dans vos paramètres, appelez GET /me, puis parcourez le catalogue.