> ## Documentation Index
> Fetch the complete documentation index at: https://storekit.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Rédiger un prompt qui fonctionne

> La structure de prompt en cinq parties des recettes storekit et le bloc de contexte qui indique à Lovable, Bolt, Replit ou v0 comment arrivent les webhooks.

Les app builders IA font ce que tu demandes et devinent le reste. Un prompt vague te donnera un joli écran qui ne recevra jamais de commande. Les prompts de nos recettes suivent une seule structure pour que les devinettes soient faites avant que tu ne colles. Utilise la même structure pour tes propres idées.

## La structure

Chaque prompt a cinq parties, dans cet ordre :

1. **Le résultat**, en un paragraphe, tel que tu le décrirais à un nouveau manager. Qui l'utilise, où il tourne, ce qu'il ne doit jamais faire.
2. **Le bloc de contexte storekit** ci-dessous — copié intégralement. Il indique au builder exactement comment storekit va parler à l'application, pour qu'il n'invente pas un payload ni ne saute la vérification des signatures.
3. **Ce qu'il faut construire**, sous forme de liste numérotée. Indique le chemin de l'endpoint, chaque écran, chaque règle. Si tu vérifierais quelque chose lors du test, cela doit figurer dans cette liste.
4. **Définition du terminé**, sous forme de cases à cocher. Le builder les utilisera pour tester son propre travail.
5. **Ce qu'il faut te rendre** : l'URL publique du webhook, la liste des variables d'environnement que tu dois définir, et comment tester.

Garde tout dans un seul message. Les messages suivants servent à corriger ce que le premier a raté, pas à ajouter les exigences que tu as oubliées.

## Le bloc de contexte

Colle ceci dans chaque prompt, sans modification, juste après ton paragraphe de résultat. C'est le même bloc utilisé dans toutes les recettes.

```text theme={null}
CONTEXT ABOUT STOREKIT

I run a hospitality business on storekit (storekit.com), an online ordering and payments platform for restaurants, cafés and bars. storekit can notify my own app about things that happen in my store by sending webhooks.

How storekit webhooks work:
- Each event is an HTTP POST with a JSON body to a URL I register in the storekit dashboard.
- The body has the shape { "event": "<event type>", "data": { ... } }. Two exceptions: the legacy order.created event (do not use it; use order.created.v2) sends the bare order object, and the order.refund.created / order.refund.succeeded / order.refund.failed events put order, customer, venue and refund next to event instead of inside data.
- Requests are signed with Svix. Every request carries the headers svix-id, svix-timestamp and svix-signature. Verify them with the official `svix` library for your language, using a secret I will provide in an environment variable called STOREKIT_WEBHOOK_SECRET. Reject anything that fails verification with HTTP 400.
- My endpoint must respond with a 2xx status within 15 seconds. Save the event to the database first, respond 200, then do the work from the saved copy.
- Once I have responded 200, storekit will not send that event again, so the work must not be lost: store each event with a status (pending, done, failed) and only mark it done after the work has actually succeeded. On startup and on a timer, pick up anything still pending or failed and retry it. Never do the work only in memory after responding.
- The same event can occasionally be delivered more than once. Use the svix-id header as the unique key for the saved event: a repeat of an event already saved is ignored, whatever its status.
- Any page or endpoint protected by a password must be served over HTTPS only; redirect or refuse plain HTTP.
- Money fields (total, tip, deliveryFee, discountTotal, item price, modifier price) are integers in minor units: 2500 means £25.00.
- orderType is one of Delivery, Pickup, InStore, Curbside, CateringDelivery, CateringPickup or Billpay.
- table is only present for in-store orders; deliveryAddress and pickUpTime only for delivery orders. When they do not apply the key is omitted, so treat a missing key the same as null. notes and items[].note can be null or empty. customer.companyName and customer.vatNumber appear only when supplied.

Example order.created.v2 payload:

{
  "event": "order.created.v2",
  "data": {
    "id": "ord_abc123",
    "code": "A1B2",
    "asap": true,
    "total": 2500,
    "tip": 250,
    "deliveryFee": 299,
    "discountTotal": 0,
    "orderType": "Delivery",
    "pickUpTime": "2024-01-15T10:45:00Z",
    "channel": "WEB",
    "poNumber": null,
    "createdAt": "2024-01-15T10:30:00Z",
    "deliveryTime": "2024-01-15T11:00:00Z",
    "notes": "Ring doorbell",
    "customer": {
      "firstName": "John",
      "lastName": "Doe",
      "email": "john@example.com",
      "phone": "+44123456789",
      "marketingConsent": true
    },
    "items": [
      {
        "name": "Margherita Pizza",
        "printName": "Margherita",
        "price": 1200,
        "quantity": 1,
        "plu": null,
        "posId": null,
        "taxRate": 20,
        "note": null,
        "modifiers": [
          { "name": "Extra cheese", "printName": "Cheese", "price": 150, "quantity": 1, "plu": null, "posId": null, "taxRate": 20 }
        ]
      }
    ],
    "venue": {
      "id": 1234,
      "name": "My Restaurant",
      "slug": "my-restaurant",
      "address": {
        "street1": "123 Main St",
        "street2": "",
        "city": "London",
        "postCode": "W1A 1AA",
        "country": "UK",
        "companyName": "My Restaurant Ltd",
        "coordinates": { "latitude": 51.5074, "longitude": -0.1278 }
      }
    },
    "deliveryAddress": {
      "street1": "456 Oak Ave",
      "street2": "Flat 2",
      "city": "London",
      "postCode": "E1 6AN",
      "country": "UK",
      "notes": null,
      "coordinates": { "latitude": 51.5155, "longitude": -0.0722 }
    }
  }
}

The full list of event types and payloads is at https://storekit.com/docs/developers/webhooks/webhook-events
```

Si ton outil utilise un événement autre que `order.created.v2`, copie l'exemple de payload de cet événement depuis la [référence des événements](/docs/fr/developers/webhooks/webhook-events) et ajoute-le également sous « Example payload ».

## Règles à répéter

Les builders les oublient sauf si le prompt est explicite, alors chaque recette les détaille. Copie les lignes dont tu as besoin dans la partie 3 de ton prompt.

* Vérifier la signature Svix de chaque requête en utilisant la bibliothèque officielle `svix`. Ne pas écrire ta propre vérification. Renvoyer 400 en cas d'échec.
* Renvoyer 200 dès que l'événement est stocké, puis le traiter. Ne jamais faire attendre storekit sur une imprimante, un SMS ou une API tierce.
* Ignorer tout `svix-id` déjà vu.
* Conserver l'historique des événements dans une vraie base de données, pas en mémoire, pour que rien ne soit perdu au redémarrage ou au redéploiement de l'application.
* Ne pas envoyer les noms, numéros de téléphone ou adresses des clients à un service tiers sauf si le prompt le dit.
* Formater les montants en divisant par 100 et en utilisant la devise du magasin.
* Afficher les heures dans le fuseau horaire local du magasin, pas celui du serveur.
* Mettre le secret du webhook et toutes les clés API dans des variables d'environnement. Jamais dans le code.

## Choisir un builder

Nous ne recommandons pas un builder plutôt qu'un autre pour tout, mais les recettes le précisent là où ça compte :

* **Les outils qui reçoivent des webhooks** ont besoin d'une URL publique stable qui reste en ligne et, en général, d'une base de données. [Replit](https://replit.com) te donne les trois au même endroit, c'est pourquoi les recettes qui reçoivent des événements sont écrites avec Replit en tête. Bolt et Lovable peuvent aussi le faire si tu y attaches un backend (Supabase est l'association habituelle) ; quand tu leur donnes le prompt, ajoute « déploie le backend pour qu'il ait une URL publique, et dis-moi laquelle c'est ».
* **Les outils uniquement d'affichage** qui lisent depuis une base de données remplie par un autre de tes outils conviennent bien à [Lovable](https://lovable.dev) et [v0](https://v0.dev).
* **Les tâches planifiées** (un résumé quotidien à 23h30, un digest hebdomadaire) ont besoin d'un endroit où faire tourner un planificateur. Demande directement au builder : « ceci doit s'exécuter tous les jours à 23h30 Europe/London ; dis-moi comment tu l'as planifié et comment je peux confirmer que ça s'est exécuté ».

Quel que soit ton choix, consulte la documentation du builder pour savoir comment il stocke les secrets et affiche l'URL déployée — les noms changent plus souvent que cette page.

## Connecter l'application terminée

Une fois que le builder te donne une URL, connecte-la :

**1. Open the webhooks portal**

In the dashboard sidebar, go to **Settings** → **Webhooks**. If your plan includes webhooks and they are not yet enabled, click **Enable Webhooks**. If the page shows **Upgrade to enable webhooks**, [contact support](/docs/getting-started/contact-support) to discuss adding webhooks to your plan.

**2. Add your app as an endpoint**

In the embedded portal, add a new endpoint, paste the webhook URL your app builder gave you, and tick only the event types the recipe needs.

**3. Copy the signing secret into your app**

Open the endpoint you just created and copy its signing secret. In your app builder, save it as the environment variable `STOREKIT_WEBHOOK_SECRET` (builders call this "secrets" or "environment variables"). Redeploy if the builder asks you to.

**4. Send a test event**

Use the portal's test option on the endpoint to send a sample event. The delivery log shows the response code from your app. A `2xx` means your app accepted it; anything else, read the response body in the log — it is usually a missing secret.

## Tester sans attendre une vraie commande

* L'option de test de livraison dans le portail webhooks utilise un exemple générique, pas ton menu. Elle prouve la connexion et la vérification de signature ; elle ne prouve pas ta mise en page.
* Pour un vrai payload, passe une petite commande sur ta propre boutique avec un moyen de paiement de test ou un code de réduction à 100 %, puis rembourse-la. Fais-le pendant que le journal de l'application est ouvert.
* Casse volontairement quelque chose une fois : change `STOREKIT_WEBHOOK_SECRET` avec une mauvaise valeur et confirme que l'application renvoie 400 et que le portail affiche la livraison en échec. Remets ensuite la bonne valeur.

## Quand le builder se trompe

Colle l'erreur, pas une description. La plupart des correctifs sont l'un des suivants :

* « Il dit 400 dans le journal de livraison storekit. » Le secret dans l'application ne correspond pas à celui de l'endpoint, ou l'application parse le corps avant de le vérifier. Dis au builder : « vérifie le corps brut de la requête, exactement tel que reçu, avant de parser le JSON ».
* « Il a imprimé deux fois / envoyé deux SMS. » L'application ne vérifie pas `svix-id`, ou fait le travail avant de renvoyer 200 et dépasse le délai. Rappelle-lui les deux règles.
* « Ça marchait, puis a arrêté après un jour. » L'application s'est mise en veille ou l'historique était en mémoire. Demande un déploiement toujours actif et une base de données.
* « Les prix sont 100 fois trop grands. » Les unités mineures — rappelle-lui de diviser par 100.


## Related topics

- [Journal des ruptures et digest matinal](/docs/fr/guides/build/recipes/out-of-stock-log.md)
- [Créer tes propres outils sur storekit](/docs/fr/guides/build/overview.md)
- [Documentation storekit : guides et API de commande en ligne](/docs/fr/index.md)
- [Feuille de rapprochement des virements](/docs/fr/guides/build/recipes/payout-reconciliation.md)
- [Tableau des commandes en direct pour le pass](/docs/fr/guides/build/recipes/live-order-board.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.