RefCampaign/docs
Integration

Postback serveur à serveur

Suivez les conversions en appelant l'API REST directement depuis votre backend, sans le SDK.

Le SDK est le chemin recommandé pour les stacks JavaScript et TypeScript. Si vous êtes sur un autre runtime — PHP, Python, Ruby, Go, Elixir — ou si vous ne voulez pas de dépendance, appelez les endpoints REST publics directement. Ce guide couvre le pattern le plus utilisé : un postback serveur à serveur déclenché depuis votre backend de checkout après un paiement réussi.

Quand utiliser le postback

Le postback est le bon pattern quand :

  • La conversion a lieu côté serveur (webhook Stripe, IPN PayPal, processeur de paiement custom).
  • Vous avez besoin de garanties de livraison plus strictes que ce qu'un pixel navigateur peut offrir.
  • Vous opérez sur une stack non-JS.
  • La session navigateur peut être perdue entre le clic et la conversion (Safari ITP, cross-device, app mobile).

Si la conversion est liée à une page que le client est en train de visiter, le SDK est plus simple.

Endpoint

POST /api/v1/conversions/postback
Authorization: Bearer <VOTRE_CLE_API>
Content-Type: application/json

Payload

{
  "externalId": "ord_42",
  "conversionType": "SALE",
  "amount": 4990,
  "currency": "EUR",
  "sessionId": "rcs_7fKj2...",
  "metadata": { "plan": "pro" }
}
ChampTypeRequisNotes
externalIdstring (1–255)ouiVotre identifiant de commande / transaction. Sert de clé d'idempotence.
conversionTypestringouiL'un de SALE, LEAD, TRIAL, CUSTOM.
amountintegerouiValeur de la conversion en unités mineures (centimes). Ex. 49,90 € → 4990. Les décimaux sont rejetés avec 422.
currencystringouiCode ISO 4217 à 3 lettres (mis en majuscules côté serveur).
sessionId / rcsidstringun parmiIdentifiant de session depuis le cookie de clic. Préféré quand intact.
clickId / cidstringun parmiIdentifiant de clic retourné par l'URL de tracking. Alternative à sessionId.
customerEmailHashstringun parmiSHA-256 hex de l'email client en minuscules. Fallback si la session est perdue.
customerEmailstringun parmiEmail client en clair (hashé côté serveur). Fallback.
customerIdstringnonVotre identifiant client interne.
convertedAtstringnonDatetime ISO 8601 de la conversion. Par défaut : maintenant.
customParamsobjectnonJusqu'à 5 paramètres personnalisés : { s1, s2, s3, s4, s5 }.
metadataobjectnonFormat libre. Persisté sur la conversion, exposé dans les exports.

Au moins un identifiant d'attribution (sessionId/rcsid, clickId/cid, customerEmailHash ou customerEmail) doit être présent. Si plusieurs sont fournis, la priorité est : clickIdsessionIdcustomerEmailHashcustomerEmail.

Calculer le hash de l'email

Hashez côté serveur, pas côté client

Le hash est un identifiant de fallback ; si vous le calculez dans le navigateur, un attaquant peut le rejouer pour s'attribuer des conversions. Hashez toujours côté serveur, après avoir vérifié que l'email appartient bien au client qui paie.

import hashlib
email = customer_email.lower().strip()
email_hash = hashlib.sha256(email.encode()).hexdigest()
$emailHash = hash('sha256', strtolower(trim($email)));
require 'digest'
email_hash = Digest::SHA256.hexdigest(email.downcase.strip)

Le hash est ce que nous stockons. L'email en clair ne quitte jamais votre infrastructure.

Exemple : handler webhook Stripe

Pattern typique : votre serveur reçoit déjà un webhook Stripe checkout.session.completed. Étendez le handler pour déclencher un postback RefCampaign.

# Python / Flask
import os
import requests

REFCAMPAIGN_KEY = os.environ['REFCAMPAIGN_API_KEY']
REFCAMPAIGN_URL = 'https://app.refcampaign.com/api/v1/conversions/postback'

def on_stripe_completed(session):
    requests.post(
        REFCAMPAIGN_URL,
        headers={
            'Authorization': f'Bearer {REFCAMPAIGN_KEY}',
            'Content-Type': 'application/json',
        },
        json={
            'externalId': session.id,
            'conversionType': 'SALE',
            'amount': session.amount_total,  # déjà en centimes
            'currency': session.currency.upper(),
        },
        timeout=10,
    )

Idempotence et retries

L'endpoint est idempotent sur externalId — un appel répété avec le même externalId pour le même marchand renvoie la conversion existante ({ success: true, conversionId, message: "Conversion already tracked" }) sans créer de doublon. Si le même externalId est soumis par un autre marchand, le serveur retourne 409.

Si votre handler webhook retry sur erreur transitoire, c'est sûr — renvoyer le même externalId ne crée jamais de conversion en double.

Pour les retries au niveau réseau : respectez le header Retry-After sur 429, traitez les 5xx comme transitoires avec backoff, traitez les 4xx comme terminaux (pas de retry, log + alerte).

Vérifier la livraison

Le tableau de bord marchand affiche les conversions entrantes en temps réel. Pour les pipelines automatisés, requêtez la liste des conversions pour confirmer l'arrivée :

curl https://app.refcampaign.com/api/v1/conversions?campaignId=cmp_xxx&limit=10 \
  -H "Authorization: Bearer $REFCAMPAIGN_API_KEY"

Sécurité

  • Envoyez la clé API uniquement sur HTTPS.
  • Stockez-la dans un gestionnaire de secrets — jamais dans le code source.
  • Utilisez une clé dédiée par environnement (production / staging / local).
  • Voir authentification pour la checklist complète.

Sur cette page