# Intégration API (/fr/online/integration/api_integration)





Votre backend crée une session Checkout pour chaque commande et la récupère pour vérifier le paiement.

Pour Node.js, le [SDK `@tapayadot/checkout`](/online/integration/node_sdk) fournit des méthodes typées `create()` et `get()` pour ces endpoints. Il lit `TAPAYA_SECRET_KEY` par défaut. Les exemples HTTP de cette page transmettent explicitement `TAPAYA_CHECKOUT_API_KEY`.

## Authentification [#authentication]

Chaque appel au Checkout se fait de serveur à serveur et envoie une clé comme jeton bearer :

```http
Authorization: Bearer <key>
```

Choisissez le mode qui correspond à l’entité qui exploite le backend. Quelle que soit la clé, conservez-la sur votre serveur ; voir [Sécurité du Checkout](/online/security/checkout_security).

<Cards>
  <VisualCard title="Mode commerçant" visual="<Store />" href="#merchant-mode" description="Une seule boutique. Une clé checkout de commerçant sélectionne son commerçant, sans en-tête supplémentaire." />

  <VisualCard title="Mode plateforme" visual="<Building2 />" href="#platform-mode" description="Plusieurs commerçants. La Secret key de l’organisation, plus un jeton de commerçant par requête." />
</Cards>

### Mode commerçant [#merchant-mode]

Utilisez ce mode lorsque le backend sert une seule boutique. Créez une **clé checkout de commerçant** dans les [paramètres du Checkout](/online/integration/checkout_settings#create-merchant-checkout-keys) : ouvrez le commerçant et sélectionnez **Create merchant key**. La clé commence par `tapaya_test_` dans la sandbox ou par `tapaya_live_` en production et correspond exactement à ce commerçant.

```http
Authorization: Bearer <merchant-checkout-key>
```

`X-Tapaya-Merchant-Token` est facultatif dans ce mode. Si vous l’envoyez, il doit désigner le même commerçant.

La plateforme n’affiche la clé qu’une seule fois et n’en stocke que le hash. Pour effectuer une rotation, créez une clé de remplacement avant de révoquer l’ancienne. La révocation d’une clé n’affecte pas les autres clés de commerçant, les clés de l’organisation ni les client secrets déjà émis vers des navigateurs.

### Mode plateforme [#platform-mode]

Utilisez ce mode lorsqu’un même backend agit pour de nombreux commerçants, comme une marketplace ou une plateforme de livraison de repas. Envoyez la Secret key de l’organisation, disponible sur la [page API Keys](https://platform.tapaya.com/api-keys/), et le jeton du commerçant dans **chaque** requête :

```http
Authorization: Bearer <secret-key>
X-Tapaya-Merchant-Token: <merchant-token>
```

Il n’y a pas de commerçant par défaut. Une requête sans cet en-tête renvoie HTTP 401. Le commerçant doit appartenir à l’organisation de la clé. Copiez les jetons de commerçant depuis le tableau des commerçants dans les [paramètres du Checkout](/online/integration/checkout_settings). Le jeton identifie le commerçant ; ce n’est pas un secret.

La Secret key de l’organisation est le même identifiant que celui appelé Server Secret Token dans la [documentation de la Platform API](/platform-api#authentication). Le Checkout exige le préfixe `Bearer`. Les autres endpoints de la Platform API acceptent le jeton directement. L’onboarding des commerçants et la gestion de l’organisation passent par la [Platform API](/platform-api).

Les corps de requête n’acceptent pas de `merchantId`.

## Environnements [#environments]

| Environnement | Origine de l’API                 | Origine du Hosted Checkout            | Identifiants                                                                   |
| ------------- | -------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------ |
| Sandbox       | `https://api.sandbox.tapaya.com` | `https://checkout.sandbox.tapaya.com` | Clés de la sandbox, avec des [cartes de test](/online/getting-started/testing) |
| Production    | `https://api.tapaya.com`         | `https://checkout.tapaya.com`         | Clés de production, avec de vrais moyens de paiement                           |

Définissez `TAPAYA_CHECKOUT_API_URL` sur l’origine de l’API de votre environnement. Les paiements hébergés et intégrés sont tous deux disponibles en production. Chaque commerçant doit effectuer l’[onboarding](/merchants/onboarding), obtenir l’approbation du processeur pour les paiements en ligne et disposer d’une passerelle de paiement configurée. Vérifiez l’état de préparation du commerçant dans les [paramètres du Checkout](/online/integration/checkout_settings). Utilisez l’URL de session hébergée renvoyée sans la modifier.

## Sessions Checkout [#checkout-sessions]

<div className="fd-steps [&_h3]:fd-step">
  ### Créer une session Checkout [#create-a-checkout-session]

  Créez une session lorsque le client clique sur **Checkout** dans votre boutique, puis redirigez-le vers l’`url` renvoyée.
  Calculez d’abord le total final sur votre serveur et enregistrez la commande avec une idempotency key unique.

  **Endpoint :** `POST /merchant/checkout-sessions`

  <CodeBlockTabs defaultValue="curl" groupId="http-client">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="curl">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="curl">
      ```bash
      curl -X 'POST' "$TAPAYA_CHECKOUT_API_URL/merchant/checkout-sessions" \
      -H 'Content-Type: application/json' \
      -H "Authorization: Bearer $TAPAYA_CHECKOUT_API_KEY" \
      -H "X-Tapaya-Merchant-Token: $TAPAYA_MERCHANT_TOKEN" \
      -H 'Idempotency-Key: order-1001-checkout-1' \
      -d '{
              "merchantOrderId": "order-1001",
              "amount": 12100,
              "currency": "EUR",
              "tax": 2100,
              "shipping": 605,
              "taxRate": 21,
              "successUrl": "https://shop.example/checkout/return",
              "cancelUrl": "https://shop.example/checkout/cancel"
          }'
      ```
    </CodeBlockTab>
  </CodeBlockTabs>

  **En-têtes :**

  | En-tête                   | Obligatoire     | Description                                                                                                   |
  | ------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------- |
  | `Authorization`           | ✓               | `Bearer <key>` : une clé checkout de commerçant ou la Secret key de l’organisation.                           |
  | `X-Tapaya-Merchant-Token` | Mode plateforme | Jeton d’un commerçant appartenant à l’organisation de la clé. Facultatif avec une clé checkout de commerçant. |
  | `Idempotency-Key`         | ✓               | Non vide, 250 caractères au maximum. Voir [Idempotence et erreurs](#idempotency-and-errors).                  |

  **Paramètres :**

  | Champ             | Type      | Obligatoire | Description                                                                                                                |
  | ----------------- | --------- | ----------- | -------------------------------------------------------------------------------------------------------------------------- |
  | `merchantOrderId` | `string`  | ✓           | Votre référence de commande, de 1 à 200 caractères. Voir [Un paiement par commande](#one-payment-per-order).               |
  | `amount`          | `integer` | ✓           | Total final débité, en unités mineures de la devise, taxes et livraison comprises. De 1 à 2 147 483 647.                   |
  | `currency`        | `string`  | ✓           | Code ISO 4217 à trois lettres pris en charge par le backend, en majuscules, par exemple `EUR`.                             |
  | `locale`          | `string`  |             | `en` par défaut.                                                                                                           |
  | `successUrl`      | `string`  |             | Remplace l’URL de succès par défaut pour cette session. Doit correspondre à un site autorisé de l’identifiant appelant.    |
  | `cancelUrl`       | `string`  |             | Remplace l’URL d’annulation par défaut pour cette session. Doit correspondre à un site autorisé de l’identifiant appelant. |
  | `tax`             | `integer` |             | TVA déjà incluse dans `amount`, comprise entre zéro et `amount`. `0` par défaut.                                           |
  | `shipping`        | `integer` |             | Frais de livraison déjà inclus dans `amount`, compris entre zéro et `amount`. `0` par défaut.                              |
  | `taxRate`         | `number`  |             | Taux de TVA appliqué à toute la commande, par exemple `21` ou `5.5`. Non négatif.                                          |
  | `taxBreakdown`    | `array`   |             | TVA regroupée par taux. Un tableau non vide ne peut pas accompagner `taxRate`.                                             |
  | `items`           | `array`   |             | Articles de la commande, à titre d’affichage uniquement. Ne détermine pas le total débité.                                 |
  | `customer`        | `object`  |             | E-mail du client, adresse de facturation et adresse de livraison.                                                          |

  La session débite dans la `currency` que vous définissez. Les [devises prises en charge](/merchants/supported_currencies) listent toutes les
  devises prises en charge par Tapaya, mais un commerçant n’est généralement activé que pour certaines d’entre elles. La création d’une session dans une
  devise que le commerçant ou le backend ne prend pas en charge est refusée, et aucune page hébergée n’est donc créée.

  L’API débite `amount` tel qu’il est fourni. Elle n’ajoute ni la livraison ni les taxes, ne calcule pas la TVA à partir d’un taux et ne calcule pas de
  total à partir des articles.

  <Accordions>
    <Accordion title="Entrées de taxBreakdown">
      Chaque entrée contient un `taxRate` numérique et un `tax` entier, tous deux non négatifs. Les taux sont uniques et la somme
      des montants de taxe des entrées est égale au `tax` de premier niveau.

      ```json
      {
          "amount": 22650,
          "currency": "EUR",
          "tax": 2650,
          "shipping": 605,
          "taxBreakdown": [
              { "taxRate": 21, "tax": 2100 },
              { "taxRate": 5.5, "tax": 550 }
          ]
      }
      ```
    </Accordion>

    <Accordion title="Entrées de items">
      Chaque article exige `reference`, `name`, `description`, `imageUrl`, `quantity` et `unitAmount`. Les champs
      texte ne sont pas vides, `imageUrl` est une URL, `quantity` est un entier positif et `unitAmount` est un
      entier non négatif en unités mineures de la devise.
    </Accordion>

    <Accordion title="Champs de customer">
      L’objet `customer` accepte `email`, `billingAddress` et `shippingAddress`. Chaque champ est facultatif,
      de même que chaque champ d’adresse : une adresse de facturation peut donc ne contenir qu’un code postal et un pays.

      | Champ                    | Limite ou format                                              |
      | ------------------------ | ------------------------------------------------------------- |
      | `email`                  | Adresse e-mail, 254 caractères au maximum.                    |
      | `name`, `line1`, `line2` | 200 caractères au maximum chacun.                             |
      | `phone`                  | 30 caractères au maximum.                                     |
      | `city`, `state`          | 100 caractères au maximum chacun.                             |
      | `postalCode`             | 20 caractères au maximum.                                     |
      | `country`                | Code pays ISO à deux lettres en majuscules, par exemple `CZ`. |

      Le texte d’adresse fourni ne doit pas être vide. Les champs inconnus peuvent être omis. Le backend enregistre un instantané des informations
      client fournies pour les informations de risque de la passerelle. Les informations client ne sont pas incluses dans les réponses
      de session.
    </Accordion>
  </Accordions>

  **Réponses :**

  | Code  | Description                                                                                                                                               |
  | ----- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `200` | Session créée, ou même session renvoyée avec son statut actuel pour une clé, un corps et un mode d’identification répétés                                 |
  | `409` | Conflit : la clé a été réutilisée avec un corps ou un mode d’identification modifié (`API-0025`), ou la commande est déjà payée ou a un paiement en cours |

  **Corps de la réponse :**

  ```json
  {
      "id": "cs_7Hq2x9LmR4",
      "merchantOrderId": "order-1001",
      "url": "https://checkout.sandbox.tapaya.com/c/cs_7Hq2x9LmR4",
      "status": "open",
      "paymentStatus": "unpaid",
      "amount": 12100,
      "currency": "EUR",
      "tax": 2100,
      "shipping": 605,
      "taxRate": 21,
      "taxBreakdown": [],
      "items": [],
      "expiresAt": "2026-07-15T12:30:00Z",
      "createdAt": "2026-07-15T12:00:00Z"
  }
  ```

  `taxRate` n’est inclus que s’il a été fourni. Enregistrez l’`id` avec votre commande, puis envoyez le navigateur vers `url` avec
  HTTP 303. Une session accepte de nouveaux paiements pendant 30 minutes après sa création ; un paiement déjà soumis aboutit
  tout de même après ce délai. Les URL de retour sont sélectionnées et validées à la création, à partir des valeurs de la requête ou
  des valeurs par défaut de l’identifiant appelant : les [destinations de retour](/online/integration/checkout_settings#configure-return-destinations) de l’organisation
  pour la Secret key de l’organisation avec `X-Tapaya-Merchant-Token`, celles du commerçant pour une clé checkout de commerçant. Les
  deux ne sont jamais combinées.

  ### Récupérer une session [#retrieve-a-session]

  Lorsque le client revient sur votre URL de succès ou d’annulation, ou depuis une tâche de rapprochement, récupérez la session et
  comparez-la avec la commande enregistrée avant de la traiter.

  **Endpoint :** `GET /merchant/checkout-sessions/{id}`

  <CodeBlockTabs defaultValue="curl" groupId="http-client">
    <CodeBlockTabsList>
      <CodeBlockTabsTrigger value="curl">
        cURL
      </CodeBlockTabsTrigger>
    </CodeBlockTabsList>

    <CodeBlockTab value="curl">
      ```bash
      curl "$TAPAYA_CHECKOUT_API_URL/merchant/checkout-sessions/cs_7Hq2x9LmR4" \
      -H "Authorization: Bearer $TAPAYA_CHECKOUT_API_KEY" \
      -H "X-Tapaya-Merchant-Token: $TAPAYA_MERCHANT_TOKEN"
      ```
    </CodeBlockTab>
  </CodeBlockTabs>

  Il n’y a pas de suffixe `/status`. La réponse contient l’identité de la session, l’URL, les totaux, les champs de taxe, les états et
  les horodatages, ainsi que `paymentReference` et `completedAt`, qui peuvent être null. `paymentReference` identifie la dernière
  tentative de confirmation et vaut null tant qu’aucune tentative n’existe. Une référence non null ne prouve pas le succès.
  Les horodatages sont des chaînes ISO 8601.

  **Statut de la session :**

  | `status`    | Signification                                                                                                                               |
  | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
  | `open`      | La session est disponible pour le paiement, ou le résultat d’un paiement soumis est encore en cours de confirmation.                        |
  | `completed` | La session est terminée. Consultez `paymentStatus` pour connaître le résultat du paiement.                                                  |
  | `expired`   | La session n’est plus disponible pour un nouveau paiement : elle a expiré, ou une session plus récente pour la même commande l’a remplacée. |

  <a id="payment-status" />

  **Statut du paiement :**

  | `paymentStatus` | Signification pour la commande                                                                                             |
  | --------------- | -------------------------------------------------------------------------------------------------------------------------- |
  | `unpaid`        | Aucun paiement réussi confirmé. Le résultat est peut-être encore en cours de confirmation.                                 |
  | `successful`    | Le paiement a réussi. Rapprochez la référence de commande, le montant et la devise avant de traiter la commande.           |
  | `failed`        | Le paiement a été refusé. Le client peut essayer une autre carte ou un autre portefeuille tant que la session est ouverte. |
  | `cancelled`     | Le paiement a été annulé.                                                                                                  |
  | `action_needed` | Une action supplémentaire est requise. Ne traitez pas la commande comme payée.                                             |

  Une carte refusée laisse `status` à `open` et `paymentStatus` à `failed`. Pendant que Tapaya confirme en arrière-plan un résultat
  incertain, la session reste `open` et `unpaid` ; récupérez-la à nouveau plus tard. Suivre le lien d’annulation de la page
  hébergée est une navigation vers `cancelUrl` ; cela ne prouve pas en soi un état de paiement `cancelled`.

  <Callout title="Vérifiez sur votre serveur" type="warn">
    Ne traitez la commande que lorsque la session récupérée correspond à la référence, au montant et à la devise de votre commande enregistrée et que
    `paymentStatus` vaut `successful`. Une redirection du navigateur seule ne prouve jamais le paiement.
  </Callout>
</div>

## Responsabilité de la commande et du paiement [#order-and-payment-ownership]

| Votre serveur gère                                                                   | Tapaya gère                                                            |
| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
| La référence de commande, les prix, la devise et l’état de traitement de la commande | La session Checkout et le résultat du paiement auprès de la passerelle |

Un ID de session Checkout identifie une page Hosted Checkout. Son `merchantOrderId` le relie à votre commande, tandis que
`paymentReference` identifie la dernière tentative de confirmation. Enregistrez l’ID de session avec la commande afin de pouvoir
récupérer le résultat même si le client ferme le navigateur.

La page hébergée utilise des endpoints publics distincts pour charger et confirmer la session. Son ID de session sert d’identifiant
d’accès pour ces endpoints. Une intégration commerçant vérifie le paiement via l’endpoint commerçant authentifié.

### Un paiement par commande [#one-payment-per-order]

Le Hosted Checkout et l’[Embedded Checkout](/online/integration/embedded_checkout) partagent un même moteur de paiement. Un commerçant peut
avoir au plus un paiement réussi par `merchantOrderId`. Les ID de commande sont propres à chaque commerçant : des commerçants
différents, même au sein d’une même organisation, peuvent donc utiliser les mêmes ID.

* La création d’une session pour une commande impayée remplace la session impayée précédente. L’ancienne URL indique `expired` et
  ne peut plus accepter de paiement.
* La création d’une session pour une commande déjà payée, ou dont un paiement est en cours, renvoie HTTP 409.
* Après un refus, le client peut essayer une autre carte ou un autre portefeuille dans la même session. Soumettre à nouveau le même jeton de carte
  ne débite jamais deux fois.
* Tapaya définit la politique 3-D Secure et tente toujours l’authentification.

## Idempotence et erreurs [#idempotency-and-errors]

La création exige une `Idempotency-Key` non vide de 250 caractères au maximum. Pour un même commerçant :

| Vous envoyez                                                                                                                                                                       | Tapaya renvoie                                                                                  |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| La même clé, le même corps et le même mode d’identification                                                                                                                        | La même session, avec ses `status` et `paymentStatus` actuels                                   |
| La même clé avec un corps modifié                                                                                                                                                  | HTTP 409 avec le code `API-0025`                                                                |
| La même clé et le même corps avec l’autre mode d’identification                                                                                                                    | HTTP 409 avec le code `API-0025`, car chaque mode utilise ses propres paramètres de redirection |
| Des totaux invalides, une devise non prise en charge, des destinations de redirection invalides, une configuration de passerelle manquante ou un commerçant non ajouté au Checkout | Une création refusée                                                                            |

Un refus de carte est un résultat de paiement, et non la preuve qu’une requête HTTP a échoué.

<Callout title="Résultat inconnu" type="warn">
  Une erreur réseau ou un dépassement de délai laisse le résultat du paiement inconnu. Il n’existe pas encore de webhooks pour le Checkout : effectuez le rapprochement en
  récupérant la session depuis votre serveur, et ne relancez la création qu’avec la même clé et le même corps.
</Callout>
