# Integrazione tramite API (/it/online/integration/api_integration)





Il Suo backend crea una sessione di Checkout per ogni ordine e la recupera per verificare il pagamento.

Per Node.js, l'[SDK `@tapayadot/checkout`](/online/integration/node_sdk) fornisce per questi endpoint i metodi tipizzati `create()` e `get()`. Per impostazione predefinita legge `TAPAYA_SECRET_KEY`. Gli esempi HTTP in questa pagina passano `TAPAYA_CHECKOUT_API_KEY` in modo esplicito.

## Autenticazione [#authentication]

Ogni chiamata a Checkout avviene da server a server e invia una chiave come bearer token:

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

Scelga la modalità in base a chi gestisce il backend. In entrambi i casi conservi la chiave sul Suo server; si veda [Sicurezza di Checkout](/online/security/checkout_security).

<Cards>
  <VisualCard title="Modalità esercente" visual="<Store />" href="#merchant-mode" description="Un solo negozio. Una chiave checkout dell'esercente identifica il proprio esercente, senza intestazioni aggiuntive." />

  <VisualCard title="Modalità piattaforma" visual="<Building2 />" href="#platform-mode" description="Molti esercenti. La Secret key dell'organizzazione, più un token dell'esercente per ogni richiesta." />
</Cards>

### Modalità esercente [#merchant-mode]

Usi questa modalità quando il backend serve un solo negozio. Crei una **chiave checkout dell'esercente** nelle [impostazioni di Checkout](/online/integration/checkout_settings#create-merchant-checkout-keys): apra l'esercente e selezioni **Create merchant key**. La chiave inizia con `tapaya_test_` in sandbox o con `tapaya_live_` in produzione e corrisponde esattamente a quell'esercente.

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

In questa modalità `X-Tapaya-Merchant-Token` è facoltativo. Se lo invia, deve indicare lo stesso esercente.

La Platform mostra la chiave una sola volta e ne salva solo un hash. Per ruotare una chiave, crei quella sostitutiva prima di revocare la vecchia. La revoca di una chiave non influisce sulle altre chiavi dell'esercente, sulle chiavi dell'organizzazione né sui client secret già emessi ai browser.

### Modalità piattaforma [#platform-mode]

Usi questa modalità quando un unico backend agisce per molti esercenti, ad esempio un marketplace o una piattaforma di consegna di cibo a domicilio. Invii in **ogni** richiesta la Secret key dell'organizzazione dalla [pagina API Keys](https://platform.tapaya.com/api-keys/) e il token dell'esercente:

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

Non esiste un esercente predefinito. Una richiesta senza l'intestazione restituisce HTTP 401. L'esercente deve appartenere all'organizzazione della chiave. Copi i token degli esercenti dalla tabella degli esercenti nelle [impostazioni di Checkout](/online/integration/checkout_settings). Il token identifica l'esercente; non è un segreto.

La Secret key dell'organizzazione è la stessa credenziale che la [documentazione della Platform API](/platform-api#authentication) chiama Server Secret Token. Checkout richiede il prefisso `Bearer`. Gli altri endpoint della Platform API accettano il token direttamente. L'onboarding degli esercenti e la gestione dell'organizzazione usano la [Platform API](/platform-api).

I corpi delle richieste non accettano un `merchantId`.

## Ambienti [#environments]

| Ambiente   | Origine dell'API                 | Origine di Hosted Checkout            | Credenziali                                                           |
| ---------- | -------------------------------- | ------------------------------------- | --------------------------------------------------------------------- |
| Sandbox    | `https://api.sandbox.tapaya.com` | `https://checkout.sandbox.tapaya.com` | Chiavi sandbox, con [carte di prova](/online/getting-started/testing) |
| Produzione | `https://api.tapaya.com`         | `https://checkout.tapaya.com`         | Chiavi live, con metodi di pagamento reali                            |

Imposti `TAPAYA_CHECKOUT_API_URL` sull'origine dell'API del Suo ambiente. In produzione sono disponibili sia i pagamenti ospitati sia quelli incorporati. Ogni esercente deve completare l'[onboarding](/merchants/onboarding), ottenere l'approvazione del processore di pagamento per i pagamenti online e avere un gateway di pagamento configurato. Verifichi la preparazione dell'esercente nelle [impostazioni di Checkout](/online/integration/checkout_settings). Usi invariato l'URL della sessione ospitata restituito.

## Sessioni di Checkout [#checkout-sessions]

<div className="fd-steps [&_h3]:fd-step">
  ### Creare una sessione di Checkout [#create-a-checkout-session]

  Crei una sessione quando il cliente fa clic su **Checkout** nel Suo negozio, poi lo reindirizzi all'`url` restituito.
  Prima calcoli il totale finale sul Suo server e salvi l'ordine con una idempotency key (chiave di idempotenza) univoca.

  **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>

  **Intestazioni:**

  | Intestazione              | Obbligatorio         | Descrizione                                                                                                             |
  | ------------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------- |
  | `Authorization`           | ✓                    | `Bearer <key>`: una chiave checkout dell'esercente o la Secret key dell'organizzazione.                                 |
  | `X-Tapaya-Merchant-Token` | Modalità piattaforma | Token di un esercente appartenente all'organizzazione della chiave. Facoltativo con una chiave checkout dell'esercente. |
  | `Idempotency-Key`         | ✓                    | Non vuoto, al massimo 250 caratteri. Si veda [Idempotenza ed errori](#idempotency-and-errors).                          |

  **Parametri:**

  | Campo             | Tipo      | Obbligatorio | Descrizione                                                                                                                                 |
  | ----------------- | --------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
  | `merchantOrderId` | `string`  | ✓            | Il Suo riferimento dell'ordine, da 1 a 200 caratteri. Si veda [Un pagamento per ordine](#one-payment-per-order).                            |
  | `amount`          | `integer` | ✓            | Totale finale da addebitare nell'unità minore della valuta, imposte e spedizione comprese. Da 1 a 2.147.483.647.                            |
  | `currency`        | `string`  | ✓            | Codice ISO 4217 di tre lettere supportato dal backend, in maiuscolo, ad esempio `EUR`.                                                      |
  | `locale`          | `string`  |              | Valore predefinito: `en`.                                                                                                                   |
  | `successUrl`      | `string`  |              | Sostituisce l'URL di successo predefinito per questa sessione. Deve corrispondere a un sito web consentito della credenziale chiamante.     |
  | `cancelUrl`       | `string`  |              | Sostituisce l'URL di annullamento predefinito per questa sessione. Deve corrispondere a un sito web consentito della credenziale chiamante. |
  | `tax`             | `integer` |              | IVA già inclusa in `amount`, compresa tra zero e `amount`. Valore predefinito: `0`.                                                         |
  | `shipping`        | `integer` |              | Spedizione già inclusa in `amount`, compresa tra zero e `amount`. Valore predefinito: `0`.                                                  |
  | `taxRate`         | `number`  |              | Aliquota IVA percentuale per l'intero ordine, ad esempio `21` o `5.5`. Non negativa.                                                        |
  | `taxBreakdown`    | `array`   |              | IVA raggruppata per aliquota. Un array non vuoto non può essere inviato insieme a `taxRate`.                                                |
  | `items`           | `array`   |              | Righe dell'ordine solo a scopo di visualizzazione. Non determinano il totale addebitato.                                                    |
  | `customer`        | `object`  |              | Email, indirizzo di fatturazione e indirizzo di spedizione del cliente.                                                                     |

  La sessione addebita nella valuta `currency` che imposta. [Valute supportate](/merchants/supported_currencies) elenca tutte
  le valute supportate da Tapaya, ma di solito un esercente è abilitato solo per alcune di esse. La creazione di una sessione in una
  valuta non supportata dall'esercente o dal backend viene rifiutata, quindi non viene creata alcuna pagina ospitata.

  L'API addebita `amount` così come viene fornito. Non aggiunge spedizione o imposte, non calcola l'IVA da un'aliquota e non calcola un
  totale dalle righe dell'ordine.

  <Accordions>
    <Accordion title="Voci di taxBreakdown">
      Ogni voce contiene un `taxRate` numerico e un `tax` intero, entrambi non negativi. Le aliquote sono univoche e la
      somma degli importi d'imposta delle voci è pari al `tax` di primo livello.

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

    <Accordion title="Voci di items">
      Ogni riga richiede `reference`, `name`, `description`, `imageUrl`, `quantity` e `unitAmount`. I campi
      di testo non sono vuoti, `imageUrl` è un URL, `quantity` è un intero positivo e `unitAmount` è un
      intero non negativo nell'unità minima della valuta.
    </Accordion>

    <Accordion title="Campi di customer">
      L'oggetto `customer` accetta `email`, `billingAddress` e `shippingAddress`. Ogni campo è facoltativo,
      così come ogni campo dell'indirizzo, quindi un indirizzo di fatturazione può contenere solo il codice postale e il paese.

      | Campo                    | Limite o formato                                               |
      | ------------------------ | -------------------------------------------------------------- |
      | `email`                  | Indirizzo email, fino a 254 caratteri.                         |
      | `name`, `line1`, `line2` | Fino a 200 caratteri ciascuno.                                 |
      | `phone`                  | Fino a 30 caratteri.                                           |
      | `city`, `state`          | Fino a 100 caratteri ciascuno.                                 |
      | `postalCode`             | Fino a 20 caratteri.                                           |
      | `country`                | Codice paese ISO di due lettere in maiuscolo, ad esempio `CZ`. |

      Il testo dell'indirizzo fornito non deve essere vuoto. I campi che non conosce possono essere omessi. Il backend salva uno snapshot dei dati
      del cliente forniti come informazioni di rischio per il gateway. I dati del cliente non sono inclusi nelle risposte
      della sessione.
    </Accordion>
  </Accordions>

  **Risposte:**

  | Codice | Descrizione                                                                                                                                                                  |
  | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
  | `200`  | Sessione creata, oppure la stessa sessione restituita con il suo stato attuale per una ripetizione con la stessa chiave, lo stesso corpo e la stessa modalità di credenziale |
  | `409`  | Conflitto: la chiave è stata riutilizzata con un corpo o una modalità di credenziale diversi (`API-0025`), oppure l'ordine è già pagato o ha un pagamento in corso           |

  **Corpo della risposta:**

  ```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` è incluso solo se fornito. Salvi l'`id` insieme all'ordine, poi invii il browser a `url` con
  HTTP 303. Una sessione accetta nuovi pagamenti per 30 minuti dalla creazione; un pagamento già inviato viene comunque
  completato anche dopo. Gli URL di ritorno vengono selezionati e convalidati alla creazione, usando i valori della richiesta oppure
  i valori predefiniti della credenziale chiamante: le [destinazioni di ritorno](/online/integration/checkout_settings#configure-return-destinations) dell'organizzazione
  per la Secret key dell'organizzazione con `X-Tapaya-Merchant-Token`, quelle dell'esercente per una chiave checkout dell'esercente. Le
  due configurazioni non vengono mai combinate.

  ### Recuperare una sessione [#retrieve-a-session]

  Quando il cliente torna al Suo URL di successo o di annullamento, oppure da un job di riconciliazione, recuperi la sessione e
  la confronti con l'ordine salvato prima di evaderlo.

  **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>

  Non esiste un suffisso `/status`. La risposta contiene l'identità della sessione, l'URL, i totali, i campi delle imposte, gli stati e
  i timestamp, oltre a `paymentReference` e `completedAt`, che possono essere null. `paymentReference` identifica l'ultimo
  tentativo di conferma ed è null finché non esiste un tentativo. Un riferimento non null non prova il successo.
  I timestamp sono stringhe ISO 8601.

  **Stato della sessione:**

  | `status`    | Significato                                                                                                                                      |
  | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
  | `open`      | La sessione è disponibile per il pagamento, oppure l'esito di un pagamento inviato è ancora in fase di conferma.                                 |
  | `completed` | La sessione è stata completata. Controlli `paymentStatus` per l'esito del pagamento.                                                             |
  | `expired`   | La sessione non è più disponibile per un nuovo pagamento: è scaduta, oppure è stata sostituita da una sessione più recente per lo stesso ordine. |

  <a id="payment-status" />

  **Stato del pagamento:**

  | `paymentStatus` | Significato per l'ordine                                                                                             |
  | --------------- | -------------------------------------------------------------------------------------------------------------------- |
  | `unpaid`        | Nessun pagamento riuscito confermato. L'esito potrebbe essere ancora in fase di conferma.                            |
  | `successful`    | Il pagamento è riuscito. Riconcili riferimento dell'ordine, importo e valuta prima dell'evasione.                    |
  | `failed`        | Il pagamento è stato rifiutato. Il cliente può provare un'altra carta o un altro wallet finché la sessione è aperta. |
  | `cancelled`     | Il pagamento è stato annullato.                                                                                      |
  | `action_needed` | È necessaria un'ulteriore azione. Non evada l'ordine come pagato.                                                    |

  Una carta rifiutata lascia `status` su `open` e `paymentStatus` su `failed`. Mentre Tapaya conferma in background un esito
  incerto, la sessione resta `open` e `unpaid`; la recuperi di nuovo più tardi. Seguire il link di annullamento della pagina
  ospitata è una navigazione verso `cancelUrl`; di per sé non prova uno stato di pagamento `cancelled`.

  <Callout title="Verificare sul server" type="warn">
    Evada l'ordine solo quando la sessione recuperata corrisponde a riferimento, importo e valuta dell'ordine salvato e
    `paymentStatus` è `successful`. Un reindirizzamento del browser da solo non prova mai il pagamento.
  </Callout>
</div>

## Responsabilità di ordine e pagamento [#order-and-payment-ownership]

| Gestito dal Suo server                                                 | Gestito da Tapaya                                           |
| ---------------------------------------------------------------------- | ----------------------------------------------------------- |
| Il riferimento dell'ordine, i prezzi, la valuta e lo stato di evasione | La sessione di checkout e l'esito del pagamento del gateway |

L'ID di una sessione di checkout identifica un Hosted Checkout. Il suo `merchantOrderId` la collega al Suo ordine, mentre
`paymentReference` identifica l'ultimo tentativo di conferma. Salvi l'ID della sessione insieme all'ordine, così da poter
recuperare l'esito anche se il cliente chiude il browser.

La pagina ospitata usa endpoint pubblici separati per caricare e confermare la sessione. Il suo ID di sessione è una credenziale
di accesso per quegli endpoint. Un'integrazione dell'esercente verifica il pagamento tramite l'endpoint autenticato per gli esercenti.

### Un pagamento per ordine [#one-payment-per-order]

Hosted ed [Embedded Checkout](/online/integration/embedded_checkout) condividono un unico motore di pagamento. Un esercente può
avere al massimo un pagamento riuscito per `merchantOrderId`. Gli ID degli ordini valgono a livello di esercente, quindi esercenti
diversi, anche all'interno della stessa organizzazione, possono usare gli stessi ID.

* La creazione di una sessione per un ordine non pagato sostituisce la sessione non pagata precedente. Il vecchio URL riporta `expired` e
  non può più accettare pagamenti.
* La creazione di una sessione per un ordine già pagato, o con un pagamento in corso, restituisce HTTP 409.
* Dopo un rifiuto, il cliente può provare un'altra carta o un altro wallet nella stessa sessione. Inviare di nuovo lo stesso token
  della carta non comporta mai un doppio addebito.
* Tapaya definisce la policy 3-D Secure e tenta sempre l'autenticazione.

## Idempotenza ed errori [#idempotency-and-errors]

La creazione richiede un `Idempotency-Key` non vuoto di al massimo 250 caratteri. Per lo stesso esercente:

| Se invia                                                                                                                                                              | Tapaya restituisce                                                                                   |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
| La stessa chiave, lo stesso corpo e la stessa modalità di credenziale                                                                                                 | La stessa sessione, con i suoi `status` e `paymentStatus` attuali                                    |
| La stessa chiave con un corpo modificato                                                                                                                              | HTTP 409 con codice `API-0025`                                                                       |
| La stessa chiave e lo stesso corpo con l'altra modalità di credenziale                                                                                                | HTTP 409 con codice `API-0025`, perché ogni modalità usa le proprie impostazioni di reindirizzamento |
| Totali non validi, una valuta non supportata, destinazioni di reindirizzamento non valide, configurazione del gateway mancante o un esercente non aggiunto a Checkout | Un rifiuto della creazione                                                                           |

Il rifiuto di una carta è un esito del pagamento, non la prova che una richiesta HTTP non sia riuscita.

<Callout title="Esito sconosciuto" type="warn">
  Un errore di rete o un timeout lascia sconosciuto l'esito del pagamento. I webhook di Checkout non sono ancora disponibili: esegua la riconciliazione
  recuperando la sessione dal Suo server e ripeta la creazione solo con la stessa chiave e lo stesso corpo.
</Callout>
