Cloud Accept API
BetaLancez des paiements en magasin sur un appareil Tapaya appairé depuis votre ECR ou votre backend POS.
La Cloud Accept API permet à votre caisse enregistreuse électronique (ECR) ou à votre backend POS de lancer un paiement sur un appareil Tapaya via le cloud. Votre système ne communique jamais directement avec l’appareil : il envoie une demande de paiement à Tapaya, Tapaya avertit l’appareil appairé, et l’appareil affiche l’écran de paiement au client. La progression vous parvient sous forme de webhooks, ou vous l’obtenez par interrogation régulière (polling).
Choisir comment appairer les appareils
Chaque appareil auquel vous envoyez des paiements a besoin d’un externalDeviceId : le nom que votre système lui donne, par exemple
till-01. Attribuez-le de l’une des deux manières suivantes :
Depuis votre application
Votre application attribue l’externalDeviceId via l’Accept SDK sur l’appareil.
QR code depuis la plateforme
Le commerçant affiche un QR code dans la Tapaya Platform et le scanne avec l’application commerçant.
Avant de commencer
- Obtenez votre Server Secret Token sur la page API Keys. Vous l’échangez ci-dessous contre un jeton d’accès limité à un commerçant (voir l’authentification de la Platform API).
- Enregistrez le commerçant et conservez son
merchantToken. Voir Enregistrer un nouveau commerçant. - Préparez chaque appareil avec l’application Tapaya connectée pour ce commerçant, afin qu’il puisse être appairé et recevoir des demandes.
Un jeton, un commerçant
Chaque appel à la Cloud Accept API est limité à un seul et unique commerçant. Pour servir plusieurs commerçants, échangez un jeton d’accès distinct pour chacun d’eux.
Appairer un appareil
L’appairage attribue un externalDeviceId à un appareil Tapaya, afin que vous puissiez le retrouver lorsque vous listez les appareils
et le cibler lorsque vous lancez un paiement.
Attribuer depuis votre application
Votre application appelle une fonction de l’Accept SDK sur l’appareil pour lui attribuer son externalDeviceId. Utilisez
le même identifiant dans chaque appel à la Cloud Accept API concernant cet appareil.
Scanner un QR code
Le commerçant ouvre le parcours d’appairage dans la Tapaya Platform, qui affiche un QR code pour
l’externalDeviceId à attribuer. Le commerçant le scanne avec l’application commerçant Tapaya sur l’appareil
cible, et l’application finalise l’appairage.
Échanger un jeton d’accès
Échangez votre Server Secret Token et le merchantToken du commerçant contre un jeton d’accès avec
POST /ecr/auth. Le merchantToken n’est envoyé qu’ici ; tous les appels suivants envoient uniquement
Authorization: Bearer <accessToken>.
curl -X 'POST' 'https://api.tapaya.com/ecr/auth' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer REPLACE_ME' \
-d '{
"merchantToken": "unique_merchant_id_from_your_db"
}'{
"accessToken": "...",
"tokenType": "Bearer",
"expiresAt": "2026-01-13T16:30:59Z"
}| Code | Description |
|---|---|
401 | Jeton API invalide ou expiré. |
403 | L’accès au commerçant n’est pas autorisé. |
Renouvelez le jeton avant expiresAt. Appelez POST /ecr/auth/refresh avec l’accessToken actuel, encore valide,
dans l’en-tête Authorization. L’appel renvoie le même corps avec un nouveau jeton ; enregistrez-le
et utilisez-le désormais.
curl -X 'POST' 'https://api.tapaya.com/ecr/auth/refresh' \
-H 'Authorization: Bearer ACCESS_TOKEN'| Code | Description |
|---|---|
401 | Le jeton d’accès est invalide, expiré ou révoqué. Échangez-en un nouveau avec POST /ecr/auth. |
403 | Vous n’avez plus accès au commerçant. Aucun nouveau jeton n’est émis. |
Trouver un appareil prêt
Listez les appareils du commerçant avec GET /ecr/devices. Ajoutez ?connected=true pour exclure
les appareils déconnectés, ou récupérez un seul appareil avec GET /ecr/devices/{externalDeviceId}.
curl 'https://api.tapaya.com/ecr/devices/till-01' \
-H 'Authorization: Bearer ACCESS_TOKEN'{
"externalDeviceId": "till-01",
"name": "Front counter",
"connected": true,
"availability": "ready",
"lastSeenAt": "2026-01-13T16:30:59Z",
"updatedAt": "2026-01-13T16:30:59Z"
}N’envoyez des paiements qu’à un appareil dont l’availability vaut ready. La liste n’est qu’un instantané :
la disponibilité est vérifiée de nouveau lors de l’envoi, si bien qu’un appareil ready peut tout de même refuser
une demande. Voir Disponibilité des appareils.
Envoyer une demande de paiement
Envoyez le montant à un appareil avec POST /ecr/payment-requests. Tapaya enregistre la demande et
avertit l’appareil, qui affiche l’écran de paiement.
curl -X 'POST' 'https://api.tapaya.com/ecr/payment-requests' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Idempotency-Key: order-1042-attempt-1' \
-d '{
"externalDeviceId": "till-01",
"amount": 12500,
"tipAmount": 500,
"currency": "CZK"
}'Paramètres :
| Champ | Type | Obligatoire | Description |
|---|---|---|---|
externalDeviceId | string | ✓ | L’appareil appairé qui doit afficher le paiement. |
amount | integer | ✓ | Montant dans la plus petite unité de la devise (12500 correspond à 125,00 Kč). |
tipAmount | integer | Pourboire dans la plus petite unité de la devise. | |
currency | string | ✓ | Code de devise ISO 4217. |
paymentToken | string | Un paiement existant auquel rattacher la demande. |
{
"requestId": "...",
"status": "pending",
"paymentToken": null,
"expiresAt": "2026-01-13T16:30:59Z"
}202 n’est pas un résultat de paiement
202 Accepted signifie que Tapaya a enregistré la demande. Cela ne signifie pas que l’appareil l’a vue
ni que le client a payé. Tout ce qui échoue ensuite vous parvient sous forme de changement de statut.
Sécurisez les nouvelles tentatives. L’en-tête Idempotency-Key est obligatoire. Réutiliser une clé avec le même corps
renvoie la demande d’origine au lieu de lancer un second paiement ; la réutiliser avec un corps différent
renvoie 409 idempotency_conflict. Associez la clé à la vente et à la tentative, comme dans
order-1042-attempt-1.
Suivre le résultat
Suivez la demande à travers ses statuts avec des webhooks, ou interrogez régulièrement
GET /ecr/payment-requests/{requestId}. Dès qu’elle atteint payment_created, la réponse contient
le paymentToken, et les événements payment.updated rendent compte de la progression du paiement lui-même.
Pour recevoir des webhooks, enregistrez votre endpoint HTTPS avec POST /ecr/webhook-subscriptions, ou définissez
l’URL de callback et les types d’événements du commerçant dans la Tapaya Platform.
curl -X 'POST' 'https://api.tapaya.com/ecr/webhook-subscriptions' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-d '{
"url": "https://integrator.example.com/webhooks/tapaya",
"events": ["payment_request.updated", "payment.updated"]
}'{
"subscriptionId": "...",
"url": "https://integrator.example.com/webhooks/tapaya",
"events": ["payment_request.updated", "payment.updated"],
"signingSecret": "..."
}Enregistrez le signing secret
signingSecret n’est renvoyé qu’à la création de l’abonnement. Conservez-le en lieu sûr ; vous
en avez besoin pour vérifier la signature des webhooks entrants.
Un abonnement appartient à l’intégrateur et au commerçant, et non à un jeton d’accès ; il est donc conservé
lors du renouvellement du jeton. Répondez à chaque événement par un 2xx dès que vous l’avez accepté.
Vérifiez avant de clôturer la vente
Les webhooks sont des notifications, et non une preuve de paiement ; un webhook peut arriver en retard, ou ne jamais arriver. Ne clôturez jamais une vente sur la seule base d’un webhook :
- Lorsqu’un webhook arrive, confirmez le résultat final via l’API, par exemple avec Récupérer les détails d’un paiement.
- Lorsqu’aucun webhook n’arrive dans un délai adapté à votre parcours d’encaissement, et au plus tard
à l’
expiresAtde la demande, appelezGET /ecr/payment-requests/{requestId}pour lire son statut actuel, puis confirmez le paiement via l’API comme ci-dessus.
Référence
Endpoints
| Méthode | Endpoint | Description |
|---|---|---|
POST | /ecr/auth | Échange votre jeton API et un merchantToken contre un jeton d’accès. |
POST | /ecr/auth/refresh | Renouvelle un jeton d’accès encore valide. |
GET | /ecr/devices | Liste les appareils du commerçant. Filtre connected=true facultatif. |
GET | /ecr/devices/{externalDeviceId} | Renvoie un appareil et sa disponibilité actuelle. |
POST | /ecr/payment-requests | Enregistre une demande de paiement et avertit l’appareil. Nécessite Idempotency-Key. |
GET | /ecr/payment-requests/{requestId} | Renvoie le statut de la demande, l’éventuel motif de refus et le paymentToken. |
POST | /ecr/webhook-subscriptions | Enregistre une URL HTTPS et des types d’événements. Renvoie le signing secret (secret de signature) une seule fois. |
GET | /ecr/webhook-subscriptions | Liste vos abonnements pour le commerçant, sans les signing secrets. |
DELETE | /ecr/webhook-subscriptions/{subscriptionId} | Supprime un abonnement. |
Disponibilité des appareils
Les deux endpoints d’appareils renvoient externalDeviceId, name, connected, availability, lastSeenAt et
updatedAt.
| Valeur | Description |
|---|---|
ready | Connecté, et capable de recevoir et d’afficher une demande. |
busy | Traite un paiement ou détient une demande active. |
unavailable | Déconnecté, sans session valide, ou incapable d’afficher l’écran de paiement. |
Statuts des demandes
| Statut | Description |
|---|---|
pending | Enregistrée et en attente d’acceptation par l’appareil. |
acknowledged | L’appareil l’a reçue ; le paiement n’existe peut-être pas encore. |
payment_created | Un paiement et son paymentToken existent. Suivez la suite de la progression sur le paiement. |
rejected | L’appareil ou Tapaya a refusé la demande. |
Erreurs
| Code | Motif | Description |
|---|---|---|
403 / 404 | Objet indisponible | Vous n’avez pas l’autorisation, ou l’objet n’existe pas. |
409 | device_busy | L’appareil a déjà une demande ou un paiement actif. |
409 | device_unavailable | L’appareil est connecté mais n’est pas prêt. |
409 | idempotency_conflict | La clé a déjà été utilisée avec un corps différent. |
503 | device_offline | L’appareil n’est pas connecté. |
Les erreurs de validation du montant et de la devise suivent les mêmes conventions que le reste de la Platform API.
Événements webhook
| Événement | Envoyé lorsque | Contenu de data |
|---|---|---|
device.connected | Un appareil ouvre une nouvelle connexion active. | externalDeviceId, connected, availability, lastSeenAt |
device.disconnected | La connexion se ferme ou la vérification d’activité expire. | externalDeviceId, connected, availability, lastSeenAt |
device.availability_changed | La disponibilité passe de l’une à l’autre des valeurs ready, busy et unavailable. | externalDeviceId, availability, reason facultatif |
payment_request.updated | La demande est enregistrée, reçue, refusée, expire ou se voit associer un paiement. | requestId, externalDeviceId, status, paymentToken, reference, reason, expiresAt |
payment.updated | Le statut du paiement change. | paymentToken, requestId, externalDeviceId, status, reference, amount, currency, receiptUrl facultatif |
Chaque événement arrive sous forme de POST HTTP dans la même enveloppe :
{
"eventId": "...",
"type": "payment_request.updated",
"occurredAt": "2026-01-13T16:30:59Z",
"data": {
"requestId": "...",
"externalDeviceId": "till-01",
"status": "acknowledged",
"paymentToken": null,
"reference": "ORDER-1042",
"reason": null,
"expiresAt": "2026-01-13T16:30:59Z"
}
}