Connect your till to Encore
A REST API, one key per business, JSON. This takes ten minutes to read; the full reference is generated next door.
Every field, every response, with a button to try it.
Getting started
Your customer creates a key from their account, under Integrations. The secret is shown once: if they lose it, they create another and revoke the old one.
Your first call
curl https://encore.ma/api/v1/programme \
-H "Authorization: Bearer enc_xxxxxxxx_………"
Authentication
Send the key as `Authorization: Bearer`. The `X-API-Key` header works too. There is no session, no token to refresh and no `societe_id` to send: the key identifies the business, and nothing in your request can change it.
Scopes
Each key carries the list of what it may do. A till key does not need to read every member. A call outside its scope returns `403` with code `portee_absente` — which is different from an invalid key, which returns `401`.
membres.readmembres.writemouvements.writerachatprepayereferentiel.read
The location
Every action belongs to a location: that is what lets the merchant compare shops and follow their staff. If the key carries a single location, you have nothing to pass. If it carries several, add `site_id` — outside its scope, the call is refused.
A key with no location can read, never write an action: an action without a location would skew every figure the merchant relies on.
Idempotency
Every write requires an `Idempotency-Key` header of your choosing: your receipt number makes an excellent candidate. Replaying the same call with the same key never creates a second action — it returns the first, with `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}'
This is what lets you retry after a dropped connection without ever stamping twice. We do not invent it for you: two legitimate identical sales do happen, and only you know whether it is a replay.
Errors
Every refusal carries a machine `code` alongside its message. Read the code, show the message.
| 401 | cle_invalide |
Key missing, unknown or revoked. |
| 403 | portee_absente |
The key exists but lacks this right. |
| 403 | chaine_inactive |
The business subscription is suspended. |
| 422 | — |
Malformed request, or action refused by a rule (cap, cooldown). |
| 429 | trop_d_appels |
Too many calls: the `Retry-After` header says when to come back. |
Webhooks
Rather than polling the API, give us an address: we call you when something happens. Eight events, as JSON `POST`.
The eight events
membre.creemouvement.ajouterecompense.debloqueerecompense.racheteeprepaye.venduprepaye.consommecampagne.termineefeedback.recu
Verify the signature
Every call carries `X-Encore-Timestamp` and `X-Encore-Signature`. Recompute the HMAC over `timestamp.raw_body` — the **exact** body you received, before any decoding.
$attendue = 'sha256=' . hash_hmac(
'sha256',
$request->header('X-Encore-Timestamp') . '.' . $request->getContent(),
$votreSecret
);
hash_equals($attendue, $request->header('X-Encore-Signature'));
A failing call is retried five times, at growing intervals (1 min, 5, 30, 2 h, 6 h). After ten consecutive failures the address is suspended and your customer is told in their account.
A question?
Write to contact@encore.ma. Include your key prefix (`enc_…`): it is enough for us to find your calls, and it reveals nothing.