Avant de commencer
Tout ce que vous devez savoir avant de toucher la moindre ligne de code.
Qui peut devenir partenaire ?
N'importe quel propriétaire d'un SaaS qui fonctionne avec des crédits, des quotas ou des abonnements. Que vous facturies à l'utilisation, au forfait mensuel ou à la consommation — dès que vos utilisateurs ont un « solde » quelque part dans votre app, vous êtes éligible.
Prérequis techniques
- Un serveur capable de recevoir des requêtes HTTP POST. Next.js, Node/Express, FastAPI, Laravel, Bubble avec un plugin API, n8n, Make — n'importe quelle technologie qui peut répondre à une URL publique.
- Un endroit pour stocker une variable secrète. Une variable d'environnement suffit (
.env, Vercel Vars, Railway, Render…). Vous n'avez PAS besoin d'être développeur senior.
Ce que vous y gagnez
Unibund fonctionne sur un système de crédits arrimé à l'euro (1 crédit = 1 centime — voir [L'unité Unibund](#unite)). Vous gagnez sur chaque crédit consommé chez vous par un utilisateur Unibund, selon une grille transparente (voir [Combien vous gagnez](#gains)). Le taux de conversion entre vos crédits et ceux d'Unibund est fixé à l'inscription (voir [Le taux de conversion](#conversion)).
- ~30 minutes pour le mode test (Niveau 1) : un seul endpoint, vérification de signature, idempotence.
- ~1 heure supplémentaire pour la vraie intégration (Niveau 2) : ajout de la liaison de compte par code.
- +10 minutes pour connecter votre compte Stripe (Stripe Connect) et recevoir vos reversements mensuels.
L'unité Unibund
Pour ne dépendre d'aucune réévaluation tarifaire, l'unité Unibund est arrimée à un sous-multiple stable de l'euro. C'est simple, c'est lisible, ça ne bouge pas.
La règle
1 crédit Unibund = 1 centime d'euro (1 ct) 100 crédits = 1 € 1 000 crédits = 10 € 100 000 crédits = 1 000 €
Pourquoi cette règle est précieuse pour vous
- Vos calculs de gains sont des additions d'entiers — jamais de virgule, ni de taux de change à recalculer.
- Pas d'érosion par l'inflation côté Unibund : si l'euro évolue, le crédit évolue avec lui, automatiquement.
- Les utilisateurs raisonnent en crédits comme en monnaie réelle — ils achètent une recharge, ils voient leur solde diminuer, ils comprennent instantanément ce qu'ils paient et ce qu'ils consomment.
Combien vous gagnez
Unibund vend vos crédits à un tarif réduit par rapport à votre prix public direct. C'est ce qui attire les utilisateurs. La marge d'Unibund est assumée et transparente.
Pour 1 crédit consommé chez vous
Exemple à votre prix public de 0,10 € (10 crédits Unibund)
Le même modèle, à chaque échelle
Vos gains mensuels selon votre nombre d'utilisateurs actifs
SaaS qui démarre
50 utilisateurs actifs
200 000
crédits (2 000 €) / mois
25 000 crédits consommés/mois
SaaS qui décolle
500 utilisateurs actifs
2 000 000
crédits (20 000 €) / mois
250 000 crédits consommés/mois
SaaS établi
5 000 utilisateurs actifs
20 000 000
crédits (200 000 €) / mois
2 500 000 crédits consommés/mois
Hypothèses : ~500 crédits consommés / utilisateur actif / mois, grille de reversement à −20 %. Unibund ne garantit ni volume d'utilisateurs ni part de marché — ces paliers illustrent l'effet de levier, pas une promesse de revenu.
Quand et comment on vous paye
- Reversement mensuel — Déclenché début du mois suivant. Tous les crédits consommés du 1er au dernier jour du mois M sont reversés début M+1.
- Via Stripe Connect — Vous connectez votre compte Stripe à l'inscription. Les fonds arrivent sur votre compte bancaire selon votre cycle Stripe habituel.
- Suivi détaillé — Des reversements dans votre tableau de bord partenaire.
- Sur la roadmap — Reversements plus fréquents (hebdomadaires) — pas garantis à date, à l'étude pour 2026.
Le taux de conversion
Vos crédits n'ont pas la même « valeur unitaire » que les crédits Unibund. Le taux de conversion dit combien de crédits Unibund valent 1 crédit chez vous.
Vous fixez le taux à l'inscription
- Vous déclarez votre prix public direct par crédit chez vous (ex. 0,10 €, soit 10 crédits Unibund).
- Ce prix EST le taux de conversion : combien de crédits Unibund l'utilisateur doit dépenser pour obtenir 1 crédit chez vous.
- Le taux est figé pour la durée du partenariat. Vous pouvez le renégocier depuis votre tableau de bord (préavis 30 jours pour ne pas casser les paniers d'achat en cours).
Important : Unibund fait la conversion pour vous
Quand Unibund vous envoie un grant, le champ credits du payload est DÉJÀ dans VOTRE unité (= des crédits chez vous, conversion appliquée).
Vous créditez ce nombre TEL QUEL côté votre SaaS. Vous ne refaites JAMAIS le calcul de taux — sinon vous comptez le taux deux fois et vous créditez au mauvais montant.
C'est pour ça que le taux que vous déclarez à l'inscription doit être le bon : il pilote tous vos futurs grants.
Exemple complet, bout en bout
Votre prix public : 0,10 € / crédit chez vous (= 10 crédits Unibund par crédit chez vous). Un utilisateur Unibund veut 500 crédits chez vous : il dépense 500 × 9 = 4 500 crédits Unibund (= 45 €) chez Unibund. Unibund convertit en interne et envoie un grant à votre endpoint avec credits = 500 (c'est l'unité chez vous, déjà convertie). Vous ajoutez 500 crédits à son compte chez vous. Point. Côté reversement : Unibund vous reversera 500 × 8 = 4 000 crédits Unibund (= 40 €) au prochain payout mensuel. Marge Unibund sur cette opération : 500 crédits (= 5 €).
Démarrer en 4 étapes
Le chemin le plus court pour devenir partenaire Unibund, de zéro à la production.
- 1Inscrivez-vous comme partenaire
Créez votre compte partenaire sur l'espace partenaire. Unibund vous fournit votre secret partagé (
UNIBUND_SECRET) à cette étape. Cette étape inclut la connexion de votre compte Stripe via Stripe Connect pour recevoir vos reversements mensuels, et la déclaration de votre taux de conversion (voir [#conversion](#conversion)). - 2Récupérez votre secret partagé
Depuis votre tableau de bord partenaire (disponible après inscription), copiez votre
UNIBUND_SECRETet stockez-le en variable d'environnement côté votre SaaS. Ne le commitez jamais. - 3Mode test — faites fonctionner /credits (Niveau 1)
Implémentez l'endpoint
POST /api/unibund/credits. C'est une étape de test uniquement pour valider que votre logique de crédit et de signature fonctionne. Vous n'êtes pas encore partenaire en production. - 4Vrai partenariat — ajoutez la liaison de compte (Niveau 2)
Ajoutez
POST /api/unibund/link/startetPOST /api/unibund/link/verify. C'est cette étape qui vous donne le statut de partenaire Unibund et débloque les échanges réels en production.
Si vous utilisez un outil no-code ou une IA
Vous n'écrivez pas le code vous-même ? Collez l'un de ces prompts dans votre assistant (v0, Cursor, Lovable…). Ils reprennent fidèlement les en-têtes et le payload à 7 champs (dont offer_type et partner_ref). Le prompt Niveau 1 ci-dessous montre la structure de base : pour un routage avancé selon le type d'offre, utilisez le prompt adaptatif dans votre espace partenaire (onglet « IA » de l'étape 3).
Intègre l'API partenaire Unibund (endpoint de crédit). Crée UN endpoint
HTTP POST /api/unibund/credits qui :
1. Lit le corps JSON BRUT (raw body) AVANT tout parsing.
2. Vérifie l'en-tête "Unibund-Signature" au format "t=<unix>,v1=<hex>" :
v1 doit égaler HMAC_SHA256(secret, `${t}.${rawBody}`) en hexadécimal,
comparé en constant-time. Le secret vient de la variable d'env {SECRET_PARTAGE}.
Rejette 401 si invalide ou si t date de plus de 300 secondes (anti-replay).
3. IDEMPOTENCE : lit l'en-tête "Unibund-Event-Id". Si déjà traité, renvoie le
résultat précédent SANS recréditer (replayed: true).
4. Crédite l'utilisateur :
- si body.user.external_id est présent → crédite CE compte exact ;
- sinon → trouve-ou-crée le compte par body.user.email.
Ajoute body.credits au solde TEL QUEL (déjà converti, aucun calcul de taux).
5. Réponds 200 { "ok": true, "external_user_id": "...", "new_balance": <n> }
UNIQUEMENT si le crédit a réussi. Sinon réponds 500 (Unibund réessaiera).
Corps reçu (7 champs) :
{ "event":"credit.grant", "event_id":"evt_abc123", "created":1717761600,
"user":{ "external_id":"user_8842", "email":"{EMAIL_CLIENT}", "name":"Marie D." },
"credits":{MONTANT}, "offer_type":"credits", "partner_ref":null }
Note : offer_type ∈ "credits" | "subscription" | "one_time". partner_ref est le
code produit libre que le partenaire a défini sur l'offre (peut être null). Si
vous ne proposez que des crédits, vous pouvez ignorer ces deux champs — mais ne
créditez jamais par défaut sur un offer_type inattendu (répondez 400).
Utilise mon framework et ma base de données. Donne-moi le code complet de la route.Ajoute la liaison de compte Unibund par code à usage unique. Deux endpoints :
A) POST /api/unibund/link/start — appelé par MON PROPRE frontend (bouton
"Connecter à Unibund"), authentifié par MA session utilisateur.
- génère un code court lisible (ex. "ULINK-7Q2F"), durée de vie 10 minutes ;
- stocke { code, mon_user_id_interne, expires_at } ;
- renvoie { "code": "ULINK-7Q2F", "expires_in": 600 }. Mon frontend l'affiche.
B) POST /api/unibund/link/verify — appelé par UNIBUND, signé exactement comme
l'endpoint de crédit (en-tête Unibund-Signature "t=,v1=", HMAC sur
`${t}.${rawBody}`, secret {SECRET_PARTAGE}, anti-replay 300s).
- corps : { "code": "ULINK-7Q2F" }
- si le code existe, n'est pas expiré et pas déjà consommé : marque-le
consommé, renvoie 200 { "ok": true, "external_user_id": <mon_user_id>,
"email": <optionnel> } ;
- sinon : 404 { "ok": false, "error": "invalid_code" }.
Réutilise ma fonction de vérification de signature. Donne-moi le code complet.# secret partagé = {SECRET_PARTAGE} (depuis votre dashboard partenaire)
# t = horodatage Unix de l'appel
# corps = le corps JSON brut reçu
#
# v1 = HMAC_SHA256( {SECRET_PARTAGE} , "<t>.<corps_brut>" ) → hex
# en-tête à comparer : Unibund-Signature: t=<t>,v1=<v1>C'est quoi connecter mon SaaS ?
Vos clients possèdent des crédits sur Unibund. Quand l'un d'eux choisit d'échanger ses crédits chez vous, Unibund prévient votre SaaS. Votre seul travail : retrouver le bon utilisateur et lui ajouter ces crédits.
Concrètement, vous exposez une ou deux adresses web (des endpoints). Unibund les appelle automatiquement, vous créditez l'utilisateur, vous répondez 200. C'est tout — pas de facture à émettre, pas d'abonnement à gérer.
Niveau 1 n'est pas un point de départ valable en production
Niveau 1 est un bac à sable : il sert uniquement à valider que votre endpoint /credits reçoit bien les appels et crédite correctement. Il ne suffit PAS pour devenir partenaire Unibund. Niveau 2 — la liaison de compte — est requis pour les échanges réels. Vous passez par Niveau 1 le temps de tester, puis vous montez en Niveau 2.
Niveau 1 — recevoir des crédits
Bac à sable — mode test uniquement
Cette configuration ne suffit pas pour devenir partenaire Unibund : elle sert à valider votre endpoint /credits en isolation. Pour les échanges réels et le statut partenaire, passez au Niveau 2.
Vous créez UN seul point d'entrée : POST /api/unibund/credits. En clair, Unibund vous dit « ajoute X crédits à tel utilisateur ». Vous trouvez (ou créez) le compte concerné, et vous créditez.
Le montant est déjà converti
Le nombre dans le champ credits est DÉJÀ exprimé dans VOTRE monnaie de crédits. La conversion au taux négocié est faite côté Unibund. Vous créditez ce nombre TEL QUEL — vous ne refaites aucun calcul de taux.
Les 3 règles à ne pas rater
- Anti-doublon (idempotence). Chaque envoi porte l'en-tête
Unibund-Event-Id. Si vous recevez DEUX fois le même id, vous ne créditez QU'UNE fois : stockez les id déjà traités et renvoyez le même résultat avecreplayed: true. Deux appels identiques = un seul crédit. - Répondez 200 SEULEMENT une fois les crédits réellement ajoutés. Trop tôt, et Unibund croit que c'est fait. En cas d'erreur, renvoyez
500: Unibund réessaiera (jusqu'à 3 fois, attentes 2s / 8s / 32s), puis ANNULERA de son côté. L'utilisateur est alors recrédité chez Unibund — un échec propre ne fait donc perdre de crédits à personne. - Vérifiez la signature AVANT de créditer (voir la section Sécurité).
Ce qu'Unibund vous envoie
{
"event": "credit.grant",
"event_id": "evt_abc123",
"created": 1717761600,
"user": {
"external_id": "user_8842",
"email": "marie@example.com",
"name": "Marie D."
},
"credits": 500,
"offer_type": "subscription",
"partner_ref": "pro_monthly"
}external_id est rempli dès que le compte a été lié (Niveau 2). S'il est null (Niveau 1 ou pas encore lié), retrouvez le compte par email.
{ "ok": true, "external_user_id": "user_8842", "new_balance": 1500 }{ "ok": true, "external_user_id": "user_8842", "new_balance": 1500, "replayed": true }Types d'offres et routage
Le grant porte deux champs supplémentaires qui indiquent CE QUE l'utilisateur a acheté et LE CODE PRODUIT que vous avez associé à cette offre.
Le champ offer_type
offer_type décrit la nature de l'achat. Trois valeurs possibles :
| offer_type | Ce que l'utilisateur a acheté | Ce que vous devez faire |
|---|---|---|
"credits" | Des crédits consommables (montant libre) | Ajoutez credits à son solde consommable. C'est le comportement historique. |
"subscription" | Un abonnement (statut récurrent) | Activez ou prolongez son statut — par exemple passez-le en pro pour la période. credits représente la valeur de la période. |
"one_time" | Un achat unique (accès ou produit) | Débloquez l'accès ou le produit correspondant une seule fois. Utilisez partner_ref pour savoir lequel. |
Ne créditez jamais par défaut
Si vous recevez un offer_type que vous ne reconnaissez pas, répondez 400 avec un message clair. Ne créditez pas par défaut : cela pourrait attribuer des crédits consommables alors que l'utilisateur a acheté un abonnement, ou vice versa.
Le champ partner_ref
partner_ref est le code produit libre que vous avez défini dans votre espace partenaire (section « Mes offres », champ « Référence produit »). Unibund vous le renvoie tel quel — il ne l'interprète pas. Il sert à distinguer plusieurs offres du même type.
- Exemples :
"pro_monthly","premium_annual","lifetime_access","template_pack_v2". - Peut être
nullsi vous n'avez pas renseigné ce champ sur l'offre. - Utile surtout quand vous avez deux abonnements (
proetpremium) ou deux produits one-time (pack Aetpack B) :partner_refvous dit lequel activer.
// Dans votre endpoint /api/unibund/credits, après validation de la signature :
const { credits, offer_type, partner_ref } = JSON.parse(raw)
switch (offer_type) {
case "credits":
// Ajoutez credits au solde consommable de l'utilisateur.
await addCredits(user.id, credits)
break
case "subscription":
// Activez ou prolongez le statut correspondant.
// partner_ref vous indique lequel si vous en avez plusieurs.
await activateSubscription(user.id, partner_ref ?? "default")
break
case "one_time":
// Débloquez le produit ou l'accès correspondant.
await unlockProduct(user.id, partner_ref ?? "default")
break
default:
// offer_type inattendu — ne créditez jamais par défaut.
return new Response(JSON.stringify({ ok: false, error: "unknown_offer_type" }), { status: 400 })
}Rétrocompatibilité totale
Si votre endpoint existant ignore offer_type et partner_ref, il continue de fonctionner : les deux champs sont additifs, ils ne remplacent aucun champ existant. Un endpoint qui ne lit que credits et user continuera de créditer correctement — il traitera simplement tout comme des crédits, ce qui est le bon comportement si vous ne proposez que des crédits.
Niveau 2 — relier les comptes proprement
Vrai partenariat — la configuration qui compte
C'est la configuration qui vous donne le badge "partenaire d'Unibund" et permet les échanges en production. Sans cette étape, vous restez en mode test.
Créditer uniquement par email casse si le client a un autre email chez vous, ou s'il s'est inscrit via Google ou par téléphone — vous risquez alors de créer un compte en double. La liaison règle ça : elle vous donne un identifiant stable, external_id.
L'idée : l'utilisateur, connecté à SON compte chez vous, génère un code à usage unique et le colle dans Unibund. Ce code prouve qu'il possède bien le compte. Vous ajoutez deux points d'entrée :
POST /api/unibund/link/start** — appelé par VOTRE propre bouton « Connecter à Unibund », sur VOTRE site, avec votre session utilisateur habituelle. Vous générez un code à usage unique (durée de vie ~10 min) pour l'utilisateur connecté, et vous l'affichez. ⚠️ Cet endpoint n'est PAS signé par Unibund — c'est votre frontend qui l'appelle.POST /api/unibund/link/verify** — appelé par Unibund (signé) quand le client colle son code chez nous. Vous vérifiez le code, le marquez consommé, et vous renvoyez votreexternal_user_idstable.
{ "code": "ULINK-7Q2F", "expires_in": 600 }// Unibund vous envoie :
{ "code": "ULINK-7Q2F" }
// Vous répondez (200) :
{ "ok": true, "external_user_id": "user_8842", "email": "marie@example.com" }
// Code invalide, expiré ou déjà utilisé (404) :
{ "ok": false, "error": "invalid_code" }Ensuite, tout devient fiable
Une fois la liaison faite, les octrois sur /api/unibund/credits portent cet external_id. Vous créditez ce compte précis, et l'email ne sert plus que de secours.
Sécurité — la signature
Chaque appel VENANT d'Unibund porte l'en-tête Unibund-Signature au format t=<horodatage>,v1=<hash>. Le v1 est un HMAC-SHA256 du secret partagé, calculé sur la chaîne ${t}.${corps_brut}. Vous recalculez ce hash de votre côté, vous comparez, et vous rejetez (401) si ça ne correspond pas OU si t a plus de 300 secondes (5 minutes).
Où s'applique la signature ?
Elle s'applique à /api/unibund/credits et à /api/unibund/link/verify. PAS à /api/unibund/link/start, qui est appelé par votre propre frontend authentifié. Le secret partagé vient de votre tableau de bord partenaire.
attendu = HMAC_SHA256( secret , t + "." + corps_brut ) → en hexadécimal
valide = (attendu === v1) ET (maintenant − t < 300 s)import crypto from "crypto"
const SECRET = process.env.UNIBUND_SECRET!
// Réutilisable pour /credits ET /link/verify
function verify(raw: string, header: string): boolean {
const p = Object.fromEntries(header.split(",").map((x) => x.split("=")))
const expected = crypto.createHmac("sha256", SECRET).update(`${p.t}.${raw}`).digest("hex")
return (
!!p.v1 &&
crypto.timingSafeEqual(Buffer.from(p.v1), Buffer.from(expected)) &&
Math.abs(Date.now() / 1000 - Number(p.t)) < 300
)
}export async function POST(req: Request) {
const raw = await req.text()
if (!verify(raw, req.headers.get("unibund-signature") ?? ""))
return new Response("invalid signature", { status: 401 })
// Idempotence : un même Unibund-Event-Id ne crédite qu'une fois.
const eventId = req.headers.get("unibund-event-id") ?? ""
if (await alreadyProcessed(eventId)) return Response.json(await getResult(eventId))
const body = JSON.parse(raw)
const user = body.user.external_id
? await getUserByExternalId(body.user.external_id) // compte lié → exact
: await findOrCreateUser(body.user.email, body.user.name) // sinon, par email
const newBalance = await addCredits(user.id, body.credits)
const result = { ok: true, external_user_id: user.id, new_balance: newBalance }
await markProcessed(eventId, result)
return Response.json(result)
}Canal retour — tenir Unibund informé des abonnements
Par défaut, Unibund ne connaît l'abonnement d'un utilisateur que s'il l'a acheté via Unibund. Le canal retour vous permet de pousser le statut réel depuis votre SaaS — pour qu'Unibund n'affiche pas une offre déjà possédée, et gère les upgrades correctement.
C'est optionnel
Sans le canal retour, Unibund suit uniquement les achats faits via lui. Avec le canal retour, il reflète l'état réel : utile si l'utilisateur s'est abonné directement chez vous, a changé de gamme, ou a résilié en dehors d'Unibund.
Quand l'envoyer
- À la souscription (nouvelle gamme active) —
status: "active",tier_rankdu nouveau plan. - À chaque upgrade ou downgrade —
status: "active",tier_rankmis à jour. - À la résiliation —
status: "canceled". - Optionnel : à chaque renouvellement pour rafraîchir le timestamp côté Unibund.
L'appel à effectuer
POST {URL_UNIBUND}/api/partner/subscription-status**. Deux headers d'identification : Unibund-Provider-Id: <votre_provider_id> et Unibund-Signature: t=<unix>,v1=<hmac>. Même formule de signature qu'à la réception des grants — mais ici c'est VOUS qui signez, avec votre UNIBUND_SECRET.
{
"external_user_id": "user_8842",
"tier_rank": 1,
"tier_name": "Pro",
"status": "active"
}
// Champs :
// external_user_id (string, requis) — votre identifiant interne de l'utilisateur
// tier_rank (entier ≥ 0, optionnel) — l'ordre de la gamme : Free=0, Pro=1, Business=2...
// tier_name (string, optionnel) — libellé libre affiché à l'utilisateur
// status (string, optionnel) — "active" | "canceled" | "free" (défaut: "active")Signature — vous signez, Unibund vérifie
La formule est identique à la réception des grants, mais les rôles sont inversés.
v1 = HMAC_SHA256( UNIBUND_SECRET, ${t}.${corps_brut} ) → hexadécimal
Header : Unibund-Signature: t=<unix>,v1=<v1>
+ Header : Unibund-Provider-Id: <votre_provider_id>
Anti-replay : Unibund rejette toute signature datant de plus de 300 secondes.
Réponses attendues
| Réponse | Signification |
|---|---|
200 { ok: true, linked: true, applied: true } | Statut enregistré — l'utilisateur est lié et le statut a été mis à jour. |
200 { ok: true, linked: false } | L'utilisateur n'a pas encore lié son compte Unibund. Pas d'erreur — Unibund le sait, il suivra dès la liaison. |
401 | Signature invalide ou expirée. Vérifiez UNIBUND_SECRET et l'horodatage. |
400 | Corps manquant, external_user_id absent, ou tier_rank / status invalide. |
Prompt IA — générer la fonction d'envoi
Collez ce prompt dans votre assistant (v0, Cursor, Lovable…) pour générer la fonction qui notifie Unibund à chaque changement d'abonnement.
Écris une fonction qui notifie Unibund du statut d'abonnement d'un de mes utilisateurs.
Elle fait un POST signé vers {URL_UNIBUND}/api/partner/subscription-status.
Corps JSON (au moins external_user_id requis) :
{
"external_user_id": "<identifiant interne de l'utilisateur>",
"tier_rank": <entier, l'ordre de la gamme : Free=0, Pro=1, Business=2...>,
"tier_name": "<libellé libre de la gamme, ex. 'Pro'>",
"status": "<'active' | 'canceled' | 'free'>"
}
Headers obligatoires :
Unibund-Provider-Id: <ton provider_id Unibund>
Unibund-Signature: t=<horodatage_unix>,v1=<hmac>
Content-Type: application/json
Signature (identique à la réception des grants, mais tu signes toi-même) :
v1 = HMAC_SHA256( UNIBUND_SECRET, `${t}.${corps_brut}` ) → hexadécimal
UNIBUND_SECRET vient de la variable d'env UNIBUND_SECRET.
t est un entier Unix (secondes). Le corps_brut est la chaîne JSON envoyée.
Appelle cette fonction à chaque changement d'abonnement chez toi :
- nouvelle souscription → status="active", tier_rank du nouveau plan
- upgrade/downgrade → status="active", tier_rank mis à jour
- résiliation → status="canceled"
Gestion d'erreurs : log les erreurs sans bloquer ton flux principal
(une erreur de notification Unibund ne doit jamais faire échouer ton propre traitement).
⚠️ Remplace {URL_UNIBUND} et {ton provider_id Unibund} par les vraies valeurs
(disponibles dans ton tableau de bord partenaire). Ne commit JAMAIS UNIBUND_SECRET.
⚠️ Si tu utilises Supabase comme base de données :
- N'importe quelle Edge Function ou API Route peut appeler cette fonction.
- Si tu déclenches la notification depuis un trigger de base de données ou une
Edge Function Supabase, utilise le SDK Admin (service_role) pour les accès DB,
et fetch() ou node-fetch pour l'appel HTTP vers Unibund.
- N'expose jamais UNIBUND_SECRET dans du code client.
Donne-moi le code complet de la fonction, avec un exemple d'appel.Tester le canal retour avec MockFlow
L'espace partenaire inclut MockFlow, un simulateur qui peut émettre un appel de statut d'abonnement de test vers votre propre SaaS ET vers le canal retour Unibund. Utilisez-le pour vérifier que votre fonction de signature envoie correctement un statut avant de le brancher en production.
Tester que ça marche
- 1Envoyez un crédit de test depuis votre tableau de bord partenaire (« Envoyer un grant de test »). Unibund envoie un grant signé à votre endpoint /api/unibund/credits.
- 2Vérifiez le solde : l'utilisateur de test doit avoir reçu le montant du champ
credits. - 3Rejouez le même grant avec le même
Unibund-Event-Id: le solde ne doit PAS bouger, et vous renvoyezreplayed: true. C'est la preuve que votre anti-doublon fonctionne.
curl -X POST {URL_DE_BASE}/api/unibund/credits \
-H "Content-Type: application/json" \
-H "Unibund-Signature: t=1717761600,v1=<hmac_du_dashboard>" \
-H "Unibund-Event-Id: evt_test_001" \
-d '{"event":"credit.grant","event_id":"evt_test_001","created":1717761600,
"user":{"external_id":null,"email":"{EMAIL_CLIENT}","name":"Test"},
"credits":{MONTANT},"offer_type":"credits","partner_ref":null}'| Votre réponse | Ce qu'Unibund fait |
|---|---|
| 200 | Grant confirmé, terminé. |
| 401 | Signature invalide → alerte dashboard, aucun nouvel essai. |
| 404 invalid_code (liaison) | L'utilisateur est invité à régénérer un code. |
| 500 / timeout | Nouvel essai : 3 fois, attentes 2s → 8s → 32s. |
| échec après 3 essais | Grant marqué échoué, l'utilisateur est remboursé côté Unibund. |
La règle d'or
Répondez 200 uniquement si les crédits ont vraiment été ajoutés.