Brancher votre caisse sur Encore
Une API REST, une clé par enseigne, du JSON. Ce qui suit se lit en dix minutes ; la référence complète est générée à côté.
Tous les champs, toutes les réponses, avec un bouton pour essayer.
Démarrer
Votre client crée une clé depuis son espace, rubrique Intégrations. Le secret ne s'affiche qu'une fois : s'il le perd, il en crée une autre et révoque l'ancienne.
Votre premier appel
curl https://encore.ma/api/v1/programme \
-H "Authorization: Bearer enc_xxxxxxxx_………"
L'authentification
Passez la clé en `Authorization: Bearer`. L'en-tête `X-API-Key` marche aussi. Il n'y a ni session, ni jeton à rafraîchir, ni `societe_id` à envoyer : la clé désigne l'enseigne, et rien dans votre requête ne peut la changer.
Les portées
Chaque clé porte la liste de ce qu'elle a le droit de faire. Une clé de caisse n'a pas besoin de lire tous les membres. Un appel hors portée rend `403` avec le code `portee_absente` — c'est différent d'une clé invalide, qui rend `401`.
membres.readmembres.writemouvements.writerachatprepayereferentiel.read
Le point de vente
Tout geste s'impute à un point de vente : c'est ce qui permet au commerçant de comparer ses boutiques et de suivre ses caissiers. Si la clé porte un seul point de vente, vous n'avez rien à passer. Si elle en porte plusieurs, ajoutez `site_id` — hors de sa portée, l'appel est refusé.
Une clé sans point de vente peut lire, jamais écrire un geste : un geste sans site fausserait tous les chiffres du commerçant.
L'idempotence
Toute écriture exige un en-tête `Idempotency-Key`, que vous choisissez : le numéro de votre ticket de caisse fait un excellent candidat. Rejouer le même appel avec la même clé ne crée jamais un second geste — il rend le premier, avec `cree: false`.
curl -X POST https://encore.ma/api/v1/membres/42/mouvements \
-H "Authorization: Bearer enc_xxxxxxxx_………" \
-H "Idempotency-Key: ticket-2026-09-19-0187" \
-H "Content-Type: application/json" \
-d '{"quantite": 1}'
C'est ce qui vous permet de retenter après un réseau coupé sans jamais tamponner deux fois. Nous ne l'inventons pas à votre place : deux ventes légitimes identiques existent, et vous seul savez si c'est un rejeu.
Les erreurs
Chaque refus porte un `code` machine en plus de son message. Lisez le code, affichez le message.
| 401 | cle_invalide |
Clé absente, inconnue ou révoquée. |
| 403 | portee_absente |
La clé existe mais n'a pas ce droit. |
| 403 | chaine_inactive |
L'abonnement de l'enseigne est suspendu. |
| 422 | — |
Requête mal formée, ou geste refusé par une règle (plafond, délai). |
| 429 | trop_d_appels |
Trop d'appels : l'en-tête `Retry-After` dit quand revenir. |
Les webhooks
Plutôt que d'interroger l'API en boucle, donnez-nous une adresse : nous vous appelons quand il se passe quelque chose. Huit événements, en `POST` JSON.
Les huit événements
membre.creemouvement.ajouterecompense.debloqueerecompense.racheteeprepaye.venduprepaye.consommecampagne.termineefeedback.recu
Vérifiez la signature
Chaque appel porte `X-Encore-Timestamp` et `X-Encore-Signature`. Recalculez le HMAC sur `timestamp.corps_brut` — le corps **exact** que vous avez reçu, avant tout décodage.
$attendue = 'sha256=' . hash_hmac(
'sha256',
$request->header('X-Encore-Timestamp') . '.' . $request->getContent(),
$votreSecret
);
hash_equals($attendue, $request->header('X-Encore-Signature'));
Un appel qui échoue est rejoué cinq fois, à intervalles croissants (1 min, 5, 30, 2 h, 6 h). Après dix échecs consécutifs, l'adresse est suspendue et votre client en est informé dans son espace.
Une question ?
Écrivez-nous à contact@encore.ma. Donnez le préfixe de votre clé (`enc_…`) : il nous suffit à retrouver vos appels, et il ne révèle rien.