Un fichier destiné aux outils, pas une page à lire. Collez cette adresse dans Postman, Insomnia ou Bruno pour importer tous les appels d'un coup, ou donnez-la à un générateur de client pour obtenir une bibliothèque dans votre langage.
À coller dans votre outil
https://fidapp.fr/api/v1/openapi.json
Elle est produite à partir des schémas qui valident réellement les requêtes : elle ne peut pas être en retard sur le serveur.
Premier crédit en trente minutes
1 · Obtenir un jeton
Deux chemins, selon ce que vous branchez. Une borne ou une tablette s'appaire avec le code à six chiffres de l'établissement, comme le ferait un employé. Un système déjà en place — caisse, CRM — utilise une clé d'organisation, créée par le commerçant dans Paramètres → Développeurs.
Premier réflexe de toute intégration. La réponse dit l'enseigne, l'établissement, les droits et le débit accordé — de quoi savoir tout de suite si vous tenez la bonne clé.
Par le QR de sa carte, par son identifiant dicté au comptoir (K7QM-3XA9), ou par son téléphone. Le téléphone et l'email passent par POST : un numéro dans une URL finit dans les journaux d'accès de chaque intermédiaire, et s'y conserve des mois.
La clé d'idempotence se génère avant l'envoi et se réutilise telle quelle à chaque réessai. C'est elle qui transforme une reprise réseau en non-événement plutôt qu'en double crédit. La réponse contient le nouveau solde, la promotion appliquée et la récompense éventuellement débloquée : rien d'autre à demander pour afficher l'écran de confirmation.
Trois règles qui décident de la qualité d'une intégration
Générez la clé d'idempotence avant l'envoi
La générer au moment du réessai revient à ne pas en avoir. Rejouée avec la même clé, une écriture rend la réponse d'origine — entière, récompense débloquée comprise — et l'en-tête Idempotency-Replayed: true.
Déclarez occurredAt dès que l'envoi est différé
Une caisse qui resynchronise après une coupure doit dire quand le client était au comptoir. Sans cela, un passage de 18 h 55 reçu à 19 h 10 perd sa happy hour, et les statistiques du commerçant décrivent vos synchronisations plutôt que sa fréquentation. Tolérance : 48 heures dans le passé, cinq minutes dans le futur.
Ne mettez jamais redeem dans une file de rejeu
Un crédit peut attendre le retour du réseau ; l'utilisation d'une récompense, non. Elle se décide sur un solde possiblement périmé, et une double consommation coûte de l'argent réel au commerçant. Hors ligne, refusez l'opération et dites-le à l'employé.
Les 14 routes
Générées depuis la spécification, elle-même tirée des schémas qui valident les requêtes. Cette liste ne peut pas être en retard sur le serveur.
Route
Ce qu'elle fait
Droit
POST /devices/pair
Appairer un appareil
public
POST /devices/unpair
Désappairer l'appareil courant
pos:read
GET /me
Identité du porteur
—
GET /programs
Programmes de l'enseigne
programs:read
GET /programs/{id}
Détail d'un programme
programs:read
GET /locations
Établissements visibles
pos:read
GET /members/lookup
Identifier par QR ou identifiant dicté
pos:read
POST /members/lookup
Identifier par téléphone ou email
pos:read
GET /members/search
Rechercher un client
pos:read
GET /members/{membershipId}
État d'une adhésion
pos:read
POST /members/{membershipId}/earn
Créditer un passage
pos:write
POST /members/{membershipId}/redeem
Utiliser une récompense
pos:write
GET /transactions
Journal des transactions
pos:read
POST /transactions/{id}/cancel
Annuler une transaction récente
pos:write
Droits
Une clé porte les droits qu'on lui donne, et rien de plus. Une borne posée en salle reçoit les trois premiers : elle doit pouvoir créditer, pas reconfigurer le programme.
pos:read
Identifier un client et lire son solde
pos:write
Créditer un passage et utiliser une récompense
members:read
Lire la base clients
members:write
Inscrire et modifier des clients
programs:read
Lire les programmes, récompenses et paliers
programs:write
Configurer les programmes
analytics:read
Lire les analyses et exporter
webhooks:manage
Gérer les notifications sortantes
Erreurs
Branchez votre logique sur code, jamais sur message : le premier est stable pour toute la durée de la version, le second est du français destiné à un écran, que nous nous réservons de réécrire. Chaque réponse porte un requestId — c'est ce que le support vous demandera.
Jeton inconnu. Vérifiez la clé utilisée, ou créez-en une nouvelle.
TOKEN_EXPIRED
401
Ce jeton a expiré. Réappairez l'appareil pour en obtenir un nouveau.
TOKEN_REVOKED
401
Ce jeton a été révoqué depuis le back-office.
OAUTH_NOT_AVAILABLE
401
Les jetons OAuth ne sont pas encore acceptés. Utilisez une clé d'organisation.
FORBIDDEN_SCOPE
403
Cette clé ne porte pas les droits nécessaires à cette opération.
PLAN_REQUIRED
403
L'accès à l'API fait partie des offres Pro et Business.
ORGANIZATION_SUSPENDED
403
Ce compte est suspendu. Contactez-nous pour le réactiver.
VALIDATION_FAILED
400
La requête est mal formée.
NOT_FOUND
404
Ressource introuvable.
METHOD_NOT_ALLOWED
405
Méthode non autorisée sur cette ressource.
UNSUPPORTED_MEDIA_TYPE
415
Envoyez un corps JSON avec « Content-Type: application/json ».
PAYLOAD_TOO_LARGE
413
Corps de requête trop volumineux.
IDEMPOTENCY_KEY_REQUIRED
400
En-tête « Idempotency-Key » obligatoire sur cette écriture : il protège du double-crédit en cas de réessai.
IDEMPOTENCY_KEY_REUSED
409
Cette clé d'idempotence a déjà servi pour une requête différente. Générez-en une nouvelle.
REQUEST_IN_FLIGHT
409
Une requête portant cette clé d'idempotence est en cours de traitement. Réessayez dans un instant.
RATE_LIMITED
429
Trop de requêtes. Réessayez dans quelques secondes.
INVALID_ACCESS_CODE
401
Ce code ne correspond à aucun établissement.
BLOCKED
422
Cette carte est désactivée.
PROGRAM_INACTIVE
422
Ce programme n'accepte plus d'opération.
COOLDOWN
429
Ce client vient d'être crédité. Patientez avant de recommencer.
DAILY_CAP
422
Le plafond journalier de ce programme est atteint pour ce client.
NOTHING_TO_EARN
422
Ce montant ne donne droit à rien.
INSUFFICIENT
422
Solde insuffisant.
ALREADY_USED
422
Cette récompense a déjà été utilisée.
UNAVAILABLE
422
Cette récompense n'est plus disponible.
EXPIRED
422
Cette récompense a expiré.
OUT_OF_STOCK
422
Cette récompense est épuisée.
TIER_REQUIRED
422
Cette récompense est réservée à un palier supérieur.
TOO_LATE
422
Passé cinq minutes, l'annulation se fait depuis le back-office.
ALREADY_CANCELLED
422
Cette transaction est déjà annulée.
AMOUNT_REQUIRED
400
Ce programme crédite au montant : indiquez « amountCents ».
INVALID_AMOUNT
400
Montant invalide.
INVALID_QUANTITY
400
Quantité invalide.
INVALID_COMBINATION
400
Cette combinaison de paramètres n'est pas acceptée par ce programme.
INVALID_COST
400
Coût de récompense invalide.
MISSING_CONFIG
422
Ce programme est incomplètement configuré.
OCCURRED_AT_OUT_OF_RANGE
422
« occurredAt » est trop éloigné de l'heure actuelle. Une opération se déclare dans les 48 heures.
INTERNAL
500
Erreur interne. Réessayez, puis contactez-nous avec l'identifiant de requête.
Notifications sortantes
Pour la caisse, la réponse de earn suffit : elle contient déjà le nouveau solde et la récompense débloquée. Les notifications servent au reste — tenir votre propre fichier client à jour, réagir à une montée de palier survenue entre deux visites, sans nous interroger en boucle. Le commerçant déclare son adresse dans Paramètres → Développeurs.
member.joined
Un client s'inscrit à un programme
transaction.created
Un passage est crédité
transaction.cancelled
Une opération est annulée
reward.earned
Une récompense est débloquée
reward.redeemed
Une récompense est utilisée
tier.upgraded
Un client atteint un palier supérieur
membership.updated
Le solde ou l'état d'une adhésion change
Livraison au moins une fois. En cas de doute — un délai d'attente sur une requête qui a peut-être abouti — nous réessayons. Dédupliquez sur id, qui identifie le fait et non la livraison. L'ordre n'est pas garanti.
Réessais après 1 min, 5 min, 15 min, 1 h, 3 h, 6 h, 12 h, 24 h. Au-delà, la livraison est abandonnée — mais votre adresse continue de recevoir les événements suivants, jusqu'à trois jours d'échecs consécutifs. Un serveur réparé le mardi soir reprend donc le fil tout seul.
Vérifiez la signature. Sans cette étape, n'importe qui connaissant votre adresse peut vous faire croire à un passage. L'horodatage fait partie de ce qui est signé : une requête interceptée cesse d'être valable au bout de cinq minutes.
Vérification (Node)
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, header, secret) {
const parts = Object.fromEntries(
header.split(",").map((p) => p.trim().split("=")),
);
// Fenêtre anti-rejeu.
if (Math.abs(Date.now() / 1000 - Number(parts.t)) > 300) return false;
const expected = createHmac("sha256", secret)
.update(`${parts.t}.${rawBody}`)
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(parts.v1);
return a.length === b.length && timingSafeEqual(a, b);
}
Le corps doit être lu brut, avant tout analyseur JSON : une re-sérialisation change les espaces et l'ordre des clés, et l'empreinte ne correspond plus.
Il n'existe pas d'événement de descente de palier, et il n'en existera pas. Une montée se célèbre, une descente se constate en silence : prévenir quelqu'un qu'il perd son statut ne le fait pas revenir, ça lui fait désinstaller sa carte.
Débit et offres
L'accès par clé fait partie des offres Pro et Business. Les appareils appairés, eux, fonctionnent sur toutes les offres — c'est la console caisse, elle est incluse partout.
Offre
Par minute
Par mois
Clés
Adresses
Pro
60
100 000
3
2
Business
300
1 000 000
10
10
Un forfait épuisé n'arrête jamais le comptoir. Créditer un passage et utiliser une récompense passent quoi qu'il arrive : le client d'un commerçant n'a pas à payer un différend d'abonnement entre ce commerçant et nous. Ce sont les lectures qui ralentissent.
Une question sur une intégration ?
Écrivez-nous avec l'identifiant de requête que vous a rendu l'API : il nous mène directement à ce qui s'est passé.