# Limites de requêtes

Chaque requête faite avec un jeton d'installation passe par deux compteurs par minute : celui de votre installation, puis celui de la boutique. Les écritures exigent aussi un en-tête `Idempotency-Key` pour qu'une nouvelle tentative ne s'exécute jamais deux fois.

## Quota par installation[​](#quota-par-installation "Lien direct vers Quota par installation")

Chaque installation de votre application dispose de son propre budget de 120 requêtes par minute. Il est vérifié en premier : une application qui boucle sur une boutique atteint sa propre limite avant de pouvoir épuiser le budget de la boutique du marchand.

Le compteur est une fenêtre fixe qui repart à zéro au début de chaque minute de l'horloge. Chaque requête compte, y compris celles qui échouent. Les requêtes refusées avec `429` comptent aussi : réessayer en boucle serrée ne rapproche pas la remise à zéro.

## Quota de la boutique[​](#quota-de-la-boutique "Lien direct vers Quota de la boutique")

Après le quota de l'installation, la requête est décomptée du budget par minute de la boutique. Ce budget est partagé par toutes les clés et toutes les applications de la boutique, y compris les propres clés API du marchand. Les jetons d'installation reçoivent le budget Enterprise de 600 requêtes par minute, quel que soit le plan de la boutique, sauf si DZBuild a fixé une autre limite pour cette boutique.

La passerelle `https://api.dzbuild.app` applique aussi un plafond de 600 requêtes par minute et par boutique avant que la requête n'atteigne les serveurs de DZBuild. Elle ignore une autre limite fixée par DZBuild pour une boutique : cette boutique reste plafonnée à 600 à ce niveau.

Quelques endpoints coûteux ont un budget supplémentaire par boutique, en plus de ces deux quotas :

| Endpoints                                                                          | Limite par boutique            |
| ---------------------------------------------------------------------------------- | ------------------------------ |
| Envoi d'image produit                                                              | 10 par minute, 3 en même temps |
| Envoi au transporteur, liaison, test et synchronisation des tarifs du transporteur | 6 par minute, 2 en même temps  |
| Écritures des sections de l'accueil                                                | 30 par minute, 5 en même temps |

## 429 Too Many Requests[​](#429-too-many-requests "Lien direct vers 429 Too Many Requests")

Quand un quota est plein, l'API répond `429` :

```
{

  "error": {

    "code": "rate_limited",

    "message": "Per-minute API limit exceeded for this app install",

    "retry_after": 23

  },

  "meta": { "request_id": "8f2c1a9d4b7e6035", "api_version": "v1" }

}
```

La réponse porte aussi un en-tête `Retry-After` avec le même nombre de secondes. Le message indique quel quota est plein : `Per-minute API limit exceeded for this app install` pour le vôtre, `Per-minute API limit exceeded for this store` pour celui de la boutique. Le refus du plafond de la boutique par la passerelle elle-même se lit `Per-minute API limit exceeded for this key`. Attendez `retry_after` secondes, puis renvoyez la requête avec le même `Idempotency-Key`.

Trop d'opérations coûteuses en cours au même moment répondent `429` avec le code `too_many_concurrent` et un `retry_after` de 5 secondes.

## 402 Payment Required[​](#402-payment-required "Lien direct vers 402 Payment Required")

Un `402` signifie que l'appel ne peut pas aboutir tant que le marchand n'a pas payé quelque chose. Réessayer ne sert à rien. Indiquez plutôt au marchand quoi faire.

| Code             | Signification                                                                                                                                            |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `no_credit`      | Le solde WhatsApp de la boutique est vide (voir [API WhatsApp](https://dzbuild.dev/fr/fr/whatsapp.md)). Le marchand le recharge dans le tableau de bord. |
| `quota_exceeded` | La boutique a atteint un quota mensuel de requêtes que DZBuild lui a fixé.                                                                               |

## Idempotency-Key[​](#idempotency-key "Lien direct vers Idempotency-Key")

Les requêtes `POST`, `PATCH` et `DELETE` doivent porter un en-tête `Idempotency-Key`. Les requêtes `GET` et `PUT` n'en ont pas besoin.

```
POST /v1/orders HTTP/1.1

Host: api.dzbuild.app

Authorization: Bearer dzpk_live_xxxxxxxx

Idempotency-Key: create-order-7f3a9c21

Content-Type: application/json
```

Les règles, telles que l'API les applique :

* La clé fait au plus 64 caractères parmi `A-Z`, `a-z`, `0-9`, `_`, `-`, `:` et `.`. Une clé absente ou mal formée répond `400` avec le code `bad_request`.
* Une clé appartient à un jeton d'installation. Les clés de deux installations différentes n'entrent jamais en collision.
* DZBuild conserve la réponse 24 heures. Renvoyer la même clé avec la même méthode, le même chemin et le même corps renvoie le statut et le corps enregistrés sans exécuter de nouveau la requête, avec l'en-tête `Idempotency-Replay: 1`.
* Réutiliser la même clé avec une autre méthode, un autre chemin ou un autre corps répond `422` avec le code `idempotency_key_reuse`. La chaîne de requête n'entre pas dans la comparaison.
* Les réponses `4xx` sont aussi enregistrées. Si une requête a échoué en `4xx` et que vous corrigez le corps, envoyez-la avec une nouvelle clé.
* Les réponses `5xx` et `429` ne sont pas enregistrées : une nouvelle tentative avec la même clé exécute de nouveau la requête.
* La réponse est enregistrée à la fin de la première requête. Deux requêtes envoyées au même instant avec la même clé peuvent s'exécuter toutes les deux : n'envoyez pas de tentatives en parallèle.

Générez une clé par opération, par exemple à partir de votre propre identifiant de tâche, et réutilisez-la pour chaque nouvelle tentative de cette opération.
