> ## 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.

# Einen Prompt schreiben, der funktioniert

> Die fünfteilige Prompt-Struktur der storekit-Rezepte und der Kontextblock, der Lovable, Bolt, Replit oder v0 zeigt, wie Webhooks eintreffen.

KI-App-Builder machen, was Sie fragen, und raten den Rest. Ein vager Prompt liefert Ihnen einen hübschen Screen, der nie eine Bestellung empfängt. Die Prompts in unseren Rezepten folgen einer einzigen Struktur, sodass das Raten schon vor dem Einfügen erledigt ist. Nutzen Sie dieselbe Struktur für Ihre eigenen Ideen.

## Die Struktur

Jeder Prompt hat fünf Teile, in dieser Reihenfolge:

1. **Das Ergebnis**, in einem Absatz, so wie Sie es einem neuen Manager beschreiben würden. Wer nutzt es, wo läuft es, was darf es niemals tun.
2. **Der untenstehende storekit-Kontextblock** – vollständig übernommen. Er sagt dem Builder genau, wie storekit mit der App sprechen wird, sodass er kein Payload erfindet und keine Signaturprüfungen weglässt.
3. **Was zu bauen ist**, als nummerierte Liste. Nennen Sie den Endpoint-Pfad, jeden Screen, jede Regel. Wenn Sie beim Testen etwas prüfen würden, gehört es auf diese Liste.
4. **Definition of Done**, als Checkboxen. Der Builder nutzt das, um seine eigene Arbeit zu testen.
5. **Was zurückgegeben wird**: die öffentliche Webhook-URL, die Liste der Umgebungsvariablen, die Sie setzen müssen, und wie Sie es testen.

Halten Sie das Ganze in einer Nachricht. Folgenachrichten sind dafür da, zu reparieren, was die erste falsch gemacht hat – nicht, um vergessene Anforderungen nachzureichen.

## Der Kontextblock

Fügen Sie diesen unverändert in jeden Prompt ein, direkt nach Ihrem Ergebnis-Absatz. Es ist derselbe Block, der in allen Rezepten verwendet wird.

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

Wenn Ihr Tool ein anderes Event als `order.created.v2` nutzt, kopieren Sie dessen Beispiel-Payload aus der [Event-Referenz](/docs/de/developers/webhooks/webhook-events) und fügen Sie ihn ebenfalls unter „Example payload" ein.

## Regeln, die es wert sind, wiederholt zu werden

Builder vergessen diese, wenn der Prompt sie nicht explizit macht, deshalb schreibt jedes Rezept sie aus. Kopieren Sie die Zeilen, die Sie brauchen, in Teil 3 Ihres Prompts.

* Verifizieren Sie die Svix-Signatur bei jeder Anfrage mit der offiziellen `svix`-Bibliothek. Schreiben Sie keine eigene Verifizierung. Geben Sie 400 zurück, wenn sie fehlschlägt.
* Antworten Sie mit 200, sobald das Event gespeichert ist, und verarbeiten Sie es dann. Lassen Sie storekit nie auf einen Drucker, eine SMS oder eine Drittanbieter-API warten.
* Ignorieren Sie jede `svix-id`, die Sie bereits gesehen haben.
* Halten Sie den Event-Verlauf in einer echten Datenbank, nicht im Speicher, damit nichts verloren geht, wenn die App neu startet oder neu deployt wird.
* Senden Sie keine Kundennamen, Telefonnummern oder Adressen an Drittanbieter-Dienste, es sei denn, der Prompt fordert es.
* Formatieren Sie Beträge, indem Sie durch 100 teilen und die Währung des Betriebs verwenden.
* Zeigen Sie Zeiten in der lokalen Zeitzone des Betriebs an, nicht der des Servers.
* Legen Sie das Webhook-Secret und alle API-Keys in Umgebungsvariablen ab. Nie im Code.

## Einen Builder wählen

Wir empfehlen nicht pauschal einen Builder gegenüber einem anderen, aber die Rezepte weisen darauf hin, wo es zählt:

* **Tools, die Webhooks empfangen**, brauchen eine stabile öffentliche URL, die verfügbar bleibt, und in der Regel eine Datenbank. [Replit](https://replit.com) bietet alle drei an einem Ort, weshalb Rezepte, die Events empfangen, mit Replit im Hinterkopf geschrieben sind. Bolt und Lovable können das auch, wenn Sie ein Backend anhängen (Supabase ist die übliche Kombination); wenn Sie sie prompten, fügen Sie hinzu: „deploy the backend so it has a public URL, and tell me what it is".
* **Reine Bildschirm-Tools**, die aus einer Datenbank lesen, in die Ihr anderes Tool schreibt, passen gut zu [Lovable](https://lovable.dev) und [v0](https://v0.dev).
* **Zeitgesteuerte Jobs** (eine tägliche Zusammenfassung um 23:30, ein wöchentlicher Digest) brauchen eine Umgebung mit Scheduler. Fragen Sie den Builder direkt: „this must run every day at 23:30 Europe/London; tell me how you have scheduled it and how I can confirm it ran".

Egal welchen Sie wählen: prüfen Sie in der Doku des jeweiligen Builders, wie er Secrets speichert und Ihnen die deployte URL zeigt – die Bezeichnungen ändern sich häufiger als diese Seite.

## Die fertige App verbinden

Sobald der Builder Ihnen eine URL gibt, verbinden Sie sie:

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

## Testen, ohne auf eine echte Bestellung zu warten

* Die Test-Zustelloption im Webhooks-Portal verwendet ein generisches Beispiel, nicht Ihr Menü. Sie belegt, dass die Verbindung und die Signaturprüfung funktionieren; sie belegt nicht Ihr Layout.
* Für ein echtes Payload legen Sie eine kleine Bestellung auf Ihrer eigenen Bestellseite mit einer Test-Zahlungsmethode oder einem 100 %-Rabattcode auf und erstatten sie anschließend. Machen Sie das mit geöffnetem App-Log.
* Zerbrechen Sie einmal absichtlich etwas: ändern Sie `STOREKIT_WEBHOOK_SECRET` auf einen falschen Wert und bestätigen Sie, dass die App 400 zurückgibt und das Portal die fehlgeschlagene Zustellung zeigt. Setzen Sie den richtigen Wert wieder ein.

## Wenn der Builder es falsch macht

Fügen Sie den Fehler ein, nicht eine Beschreibung davon. Die meisten Korrekturen sind eine von diesen:

* „Es sagt 400 im storekit-Zustell-Log." Das Secret in der App stimmt nicht mit dem Secret des Endpoints überein, oder die App parst den Body, bevor sie ihn verifiziert. Sagen Sie dem Builder: „verify the raw request body, exactly as received, before parsing JSON".
* „Es hat zweimal gedruckt / zweimal per SMS gesendet." Die App prüft `svix-id` nicht, oder sie erledigt die Arbeit, bevor sie 200 zurückgibt, und läuft in einen Timeout. Sagen Sie dem Builder beide Regeln erneut.
* „Es hat funktioniert, dann nach einem Tag aufgehört." Die App ist eingeschlafen, oder der Verlauf war im Speicher. Fragen Sie nach einem Always-on-Deployment und einer Datenbank.
* „Die Preise sind 100-mal zu groß." Minor Units – erinnern Sie den Builder daran, durch 100 zu teilen.


## Related topics

- [Individueller Küchen-Bon auf einem Star-Cloud-Drucker](/docs/de/guides/build/recipes/custom-kitchen-ticket.md)
- [Auszahlungs-Abgleichsblatt](/docs/de/guides/build/recipes/payout-reconciliation.md)
- [Live-Bestell-Board für den Pass](/docs/de/guides/build/recipes/live-order-board.md)
- [Bestell-Alerts an Slack oder Ihr Handy](/docs/de/guides/build/recipes/order-alerts.md)
- [Out-of-Stock-Log und Morgen-Digest](/docs/de/guides/build/recipes/out-of-stock-log.md)


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