Zum Inhalt

Brand Partner API

Eine kleine, berechenbare REST API zum Erstellen von mintbot-Bestellungen, zum Abfragen ihres Status und zum Empfangen von Lifecycle-Ereignissen. JSON rein, JSON raus. Bearer-token auth. Idempotente Schreibvorgänge. Signierte Webhooks.

Dashboard für API-Zugriff Zu Webhooks springen


Auf einen Blick

Base URL https://mint.mintbot.ai/api/v1
Auth `Authorization: Bearer ***
Idempotency Idempotency-Key: <uuid> bei jedem POST
Content type application/json
Rate limit 120 req / 60 s pro Partner
Webhooks Signiert mit HMAC-SHA256, bis zu 7 Wiederholungsversuche

Authentifizierung

Jede Anfrage sendet einen Partner-API-key im Authorization header. Erstelle oder rotiere den key im Dashboard.

Authorization: Bearer mo_liv...xxxx
Content-Type: application/json

Rotation hat kein Karenzfenster

Das Rotieren des keys widerruft den vorherigen key atomar. Plane, den Wert in deiner Konfiguration zu tauschen, bevor du auf Rotate klickst.

Idempotenz

Jeder POST benötigt einen Idempotency-Key header. Jede UUID pro eindeutiger Anfrage funktioniert.

  • Wir cachen die Antwort für 24 Stunden. Ein erneuter Versuch mit demselben key spielt die ursprüngliche Antwort mit Idempotent-Replay: true erneut aus.
  • Wenn du denselben key mit einem anderen body wiederverwendest, kommt 409 idempotency_key_mismatch zurück.

Bestellungen

Bestellung erstellen

POST /orders

Erstellt eine Bestellung und gibt eine Stripe Checkout URL zurück. Sobald die Zahlung bestätigt ist, provisioniert mintbot den Agenten und das Umsatzereignis für den Partneranteil wird automatisch aufgezeichnet.

Anfrage

{
  "tier": "s1",
  "duration_months": 1,
  "credit_usd": 10,
  "language": "en",
  "external_id": "your-side-id",
  "success_url": "https://your.app/thanks?id={ORDER_ID}",
  "cancel_url":  "https://your.app/cart",
  "webhook_url": "https://your.app/mintbot-webhook"
}
tier
Einer von trial, s1, s2, s4.
duration_months
Kalendermonate Serverlaufzeit. Muss einer von 1, 3 oder 12 sein.
credit_usd
Optional. Vorab finanziertes Chat-Guthaben, das mit der Bestellung gebündelt ist.
language
Optional. Beeinflusst die Stripe Checkout locale und die Sprache der Willkommens-E-Mail.
external_id
Optional. Wird in jedem Webhook und jeder Bestellantwort zurückgegeben — nutze es, um mintbot-Bestellungen mit Zeilen in deinem eigenen System zu verknüpfen.
success_url · cancel_url
Rückkehr-URLs für Stripe Checkout. {ORDER_ID} wird serverseitig ersetzt.
webhook_url
Optional. Bestellspezifischer Override für die Webhook-URL auf Partnerebene.

Antwort — 201 Created

{
  "id": 42,
  "tier": "s1",
  "duration_months": 1,
  "credit_usd": 10,
  "amount_cents": 1200,
  "currency": "usd",
  "status": "awaiting_payment",
  "checkout_url": "https://checkout.stripe.com/c/pay/cs_test_…",
  "panel_url": null,
  "expires_at": null,
  "language": "en",
  "external_id": "your-side-id",
  "created_at": "2026-05-16 09:58:00",
  "paid_at": null
}

Beispiel

curl -X POST https://mint.mintbot.ai/api/v1/orders \
  -H "Authorization: Bearer *** \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
    "tier": "s1",
    "duration_months": 1,
    "credit_usd": 10,
    "success_url": "https://your.app/thanks?id={ORDER_ID}",
    "cancel_url":  "https://your.app/cart"
  }'
import os, uuid, requests

r = requests.post(
    "https://mint.mintbot.ai/api/v1/orders",
    headers={
        "Authorization": f"Bearer {os.environ['MINTBOT_API_KEY']}",
        "Idempotency-Key": str(uuid.uuid4()),
    },
    json={
        "tier": "s1",
        "duration_months": 1,
        "credit_usd": 10,
        "success_url": "https://your.app/thanks?id={ORDER_ID}",
        "cancel_url":  "https://your.app/cart",
    },
    timeout=10,
)
r.raise_for_status()
order = r.json()
redirect_to = order["checkout_url"]

Bestellung abrufen

GET /orders/{id}

Ruft eine einzelne Bestellung anhand ihrer mintbot id ab. Gibt dieselbe Struktur wie POST /orders zurück.

curl https://mint.mintbot.ai/api/v1/orders/42 \
  -H "Authorization: Bearer ***

Bestellungen auflisten

GET /orders

Cursor-paginierte Liste, neueste zuerst.

Query parameters

status
Optional. Filtere nach awaiting_payment, completed, deployed, deploy_failed oder expired.
cursor
Optional. Übergib next_cursor von der vorherigen Seite, um fortzufahren.

Antwort

{
  "items": [ /* OrderResponse … */ ],
  "next_cursor": "37"
}

next_cursor ist null, wenn es keine weiteren Seiten gibt.


Bestellung verlängern

POST /orders/{id}/renew

Verlängert einen bestehenden Agenten um weitere duration_months. Nur Infra — es wird kein neues Chat-Guthaben gebündelt. Gibt eine neue Bestell-id und eine frische Stripe Checkout URL zurück.

Anfrage

{
  "duration_months": 1,
  "external_id": "your-side-id",
  "success_url": "https://your.app/thanks?id={ORDER_ID}",
  "cancel_url":  "https://your.app/account"
}

Umsatz

Umsatz lesen

GET /revenue

Summen plus die neuesten 200 Ledger-Ereignisse.

Query parameters

include_paid
Optional, default true. Setze auf false, um nur Ereignisse zu sehen, die noch nicht ausgezahlt wurden.

Antwort

{
  "currency": "usd",
  "gross_cents": 12000,
  "partner_cut_cents": 2000,
  "mintbot_cut_cents": 10000,
  "unpaid_cents": 800,
  "events": [
    {
      "id": 7,
      "order_id": 42,
      "kind": "order_paid",
      "gross_cents": 1200,
      "partner_cut_cents": 200,
      "mintbot_cut_cents": 1000,
      "currency": "usd",
      "created_at": "2026-05-16 09:58:00",
      "payout_id": null,
      "payout_at": null
    }
  ]
}

Partnerprofil

Profil abrufen

GET /partner

Gibt dein Partnerprofil plus den nicht ausgezahlten Saldo zurück — praktisch, um Einnahmen in deiner eigenen Admin UI anzuzeigen, ohne sie selbst zu speichern.

Antwort

{
  "id": 12,
  "email": "you@kliendifirma.com",
  "pricing_currency": "usd",
  "balance_unpaid_cents": 800,
  "webhook_url": "https://your.app/mintbot-webhook",
  "api_key_prefix": "mo_live_a12b"
}

Webhooks

Wenn etwas mit einer Bestellung passiert, senden wir ein signiertes JSON-Ereignis per POST an deine konfigurierte Webhook URL.

Ereignistypen

Event Wann es ausgelöst wird
order.created Stripe Checkout session wurde erstellt, Zahlung ausstehend.
order.paid Stripe hat die Zahlung bestätigt. Umsatzereignis wurde aufgezeichnet.
order.cancelled Bestellung ist abgelaufen oder wurde ausdrücklich storniert.
agent.provisioning_started Deploy pipeline für diese Bestellung wurde gestartet.
agent.ready Deploy erfolgreich. Payload enthält panel_url und expires_at.
agent.failed Deploy pipeline ist fehlgeschlagen. Prüfe das Feld error für den defekten Schritt.
agent.expired Agent TTL ist abgelaufen. Der Partner kann über POST /orders/{id}/renew verlängern.

Zustellung & Wiederholungsversuche

  • Bis zu 7 Versuche nach exponentiellem Zeitplan: 0s, 30s, 2m, 10m, 1h, 6h, 24h.
  • Nach dem letzten Versuch wird die Zustellung als exhausted markiert und nicht weiter wiederholt.
  • Antworte innerhalb von 10 Sekunden mit einem 2xx status, um zu bestätigen.

Request headers

Content-Type: application/json
User-Agent: mintbot-webhook/1.0
X-Mintbot-Signature: t=<unix_ts>,v1=<hex_hmac_sha256>
X-Mintbot-Event-Id: evt_42_order.paid_1747371234567
X-Mintbot-Event-Type: order.paid

Beispiel-Payload — order.paid

{
  "id": 42,
  "tier": "s1",
  "duration_months": 1,
  "credit_usd": 10,
  "amount_cents": 1200,
  "currency": "usd",
  "status": "completed",
  "external_id": "your-side-id",
  "paid_at": "2026-05-16 10:02:14"
}

Signatur verifizieren

Die Signatur ist HMAC-SHA256(secret, "{timestamp}.{raw_body}"). Verifiziere immer den rohen request body — wenn du dein geparstes JSON erneut serialisierst, bricht der Vergleich.

import hmac, hashlib, time

def verify(secret: str, body: bytes, header: str, tolerance: int = 300) -> bool:
    try:
        ts_part, v1_part = header.split(",", 1)
        ts  = int(ts_part.split("=", 1)[1])
        sig = v1_part.split("=", 1)[1]
    except Exception:
        return False
    if abs(int(time.time()) - ts) > tolerance:
        return False
    expected = hmac.new(
        secret.encode(),
        f"{ts}.".encode() + body,
        hashlib.sha256,
    ).hexdigest()
    return hmac.compare_digest(expected, sig)
const crypto = require("crypto");

function verify(secret, rawBody, header, toleranceSec = 300) {
  const [tsPart, v1Part] = header.split(",");
  const ts  = Number(tsPart.split("=")[1]);
  const sig = v1Part.split("=")[1];
  if (Math.abs(Date.now() / 1000 - ts) > toleranceSec) return false;
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${ts}.`)
    .update(rawBody)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(expected, "hex"),
    Buffer.from(sig, "hex"),
  );
}

Idempotente Empfänger

Nutze X-Mintbot-Event-Id als deinen Dedupe-key — Wiederholungsversuche verwenden dieselbe id wieder, sodass ein zeilenweises INSERT … ON CONFLICT DO NOTHING auf dieser Spalte deinen Handler sicher hält.


Fehler

Jede Fehlerantwort enthält einen stabilen code, nach dem du programmatisch verzweigen kannst. Das Feld message ist ein menschenlesbarer Hinweis und kann sich zwischen Releases ändern. request_id spiegelt den X-Request-Id response header wider — füge ihn Support-Tickets hinzu.

{
  "error": {
    "code": "invalid_api_key",
    "message": "API key is unknown or revoked.",
    "request_id": "f0c2d6c4-…"
  }
}
Code Bedeutung
unauthenticated Fehlender oder fehlerhafter Authorization header.
invalid_api_key API key ist unbekannt oder wurde herausrotiert.
rate_limited Rate limit pro Partner oder pro IP überschritten — siehe Retry-After.
missing_idempotency_key POST request ohne Idempotency-Key.
idempotency_key_mismatch Derselbe key wurde mit einem anderen request body wiederverwendet.
validation_error Request body hat die Schema-Validierung nicht bestanden.
not_found Ressource existiert nicht oder gehört nicht zu deinem Partner.
payment_gateway_error Stripe hat die Erstellung der Checkout session abgelehnt.

Rate limits

  • 120 requests / 60 s rolling window, pro Partner. Burst und steady-state teilen sich denselben bucket.
  • 60 requests / 60 s separater bucket pro IP für nicht authentifizierte und fehlgeschlagene Auth-Anfragen — verhindert, dass ein Bearer brute-force die Partnerquote aufbraucht.
  • Überschüssige Anfragen geben 429 rate_limited mit einem Retry-After header zurück (Sekunden zum Zurückziehen).

Brauchst du Hilfe?

Diese Dokumentation ist für Partner geschrieben, die die API wirklich nutzen. Wenn etwas fehlt, unklar oder veraltet ist, erwähne es gegenüber deinem mintbot-Agenten — er leitet das Feedback weiter und wir aktualisieren die Seite.