Mandate und Verbindungen

Ein Mandat ist eine Befugnis, einmalig von Ihrem vertrauenswürdigen Backend erklärt: welcher Kunde, welche Aktionen, welche Limits, bis wann. Guard prüft jeden Vorschlag dagegen. Eine Verbindung ist das Provider-Konto, auf dem die Aktionen ausgeführt werden.

Direkt aus dem Code geschrieben · aktualisiert am 26 Sept. 2026 · Fehlt etwas oder ist etwas falsch? Schreib uns

Ein Mandat registrieren

POST /v1/mandates – Backend-Schlüssel oder Sitzung (Editor+). Üblich ist ein Mandat pro Ticket oder Gespräch.

{
  "project_id": "…",
  "connection_id": "…",                       // optional: defaults to the project's Guard connection
  "source_request_id": "ticket_4711",         // your id; ties every operation back to the request
  "subject": { "customer_id": "cus_01", "payment_ids": ["pi_01"], "subscription_ids": ["sub_01"] },
                                              // Shopify: "order_ids": ["#1042"] — the orders order.cancel may touch
  "actions": ["refund.create", "subscription.cancel"],
  "limits": {
    "currency": "eur",
    "max_amount_minor": 5000,                  // total refundable under this mandate; above → DENY
    "auto_allow_up_to_minor": 2000,            // per operation; above (but within max) → REVIEW
    "max_operations": 2,
    "cancel_modes_allowed": ["period_end"],
    "cancel_modes_review": ["immediate"],      // allowed only after a human approves
    "max_pause_days": 30,                      // subscription.pause: longest pause; longer → DENY
    "pause_open_ended": "review",              // a pause with no end date: never | review | allow
    "allowed_price_ids": ["price_basic"],      // subscription.change_plan: plans it may move to
    "change_plan_at": ["now", "period_end"],
    "auto_allow_proration_up_to_minor": 1500,  // a switch that charges more today → REVIEW
    "allowed_coupons": ["WINBACK20"]           // coupon.apply
  },
  "expires_at": "2026-10-01T12:00:00Z",
  "approver": "[email protected]"       // optional label shown to reviewers
}

Antwort 201: das Mandat mit seiner mandate_id und version. Mandate sind unveränderlich; um eine Befugnis zu ändern, registrieren Sie ein neues. Ein abgelaufenes oder ausgeschöpftes Mandat führt bei jedem weiteren Vorschlag zu DENY mit dem Grund mandate_inactive.

Wie Limits zu Entscheidungen werden

BedingungEntscheidung
Aktion nicht in actions, falscher Gegenstand, falsche Währung, über max_amount_minor, über max_operations, eine Pause länger als max_pause_days (oder ohne Enddatum, wenn pause_open_ended auf never steht), ein Tarif nicht in allowed_price_ids, ein Gutschein nicht in allowed_coupons, ein Wechsel, der mehr als max_proration_minor berechnetDENY
Betrag über auto_allow_up_to_minor, aber innerhalb des Maximums; Kündigungsmodus in cancel_modes_review; eine Pause ohne Enddatum, wenn pause_open_ended auf review steht; ein Tarifwechsel, der heute mehr als auto_allow_proration_up_to_minor berechnetREVIEW (menschliche Freigabe)
Provider-Zustand nicht lesbar, Limit pro Endkunde mit HOLD überschrittenHOLD (später erneut vorschlagbar)
alles innerhalb der Limits, Guardrails unauffälligALLOW → einmal ausgeführt → verifiziert

Verbindungen

Eine Verbindung ist ein Provider-Konto, das an ein Projekt angebunden ist. Derzeit gibt es diese Arten:

  • Sandbox (simuliertes Stripe) – POST /v1/projects/{id}/connections/sandbox erstellt eine isolierte Welt aus einer Vorlagen-Fixture, optional mit Störungen (Fehler bei refund.create / subscription.cancel / read, Verzögerungen). Testläufe erstellen pro Versuch ihre eigenen Welten; dieser Endpunkt dient dazu, Guard ohne Stripe-Konto auszuprobieren.
  • Stripe – verbunden über die Projektseite (oder POST /v1/projects/{id}/connections/stripe mit secret_key + webhook_secret) mit einem eingeschränkten Schlüssel; Live-Schlüssel müssen eingeschränkt sein (rk_live_), und die Berechtigungen werden vor dem Speichern nur lesend geprüft. Rotieren mit …/connections/{connection_id}/rotate; entfernen mit DELETE (abgelehnt, solange aktive Mandate sie nutzen) (Schreibrechte für Erstattungen und Abonnements, Leserechte für die Verifizierung) und ein Webhook-Signatur-Secret. Der Schlüssel wird pro Organisation verschlüsselt und nur vom Executor verwendet.
  • Paddle Billing – verbunden über die Projektseite (Add a connection → Paddle Billing) oder POST /v1/projects/{id}/connections/paddle mit api_key (pdl_sdbx_apikey_… oder pdl_live_apikey_…) + webhook_secret (der Secret Key pdl_ntfset_… des Benachrichtigungsziels). Der Schlüssel benötigt Transactions lesen, Subscriptions lesen und schreiben, Adjustments lesen und schreiben, Customers lesen; ein Schlüssel, der auch Produkte schreiben kann, wird abgelehnt. Auf Paddle kann COLVO erstatten (ein Erstattungs-Adjustment, das auf Paddles Prüfung wartet, bevor es als verifiziert gilt), kündigen, pausieren, fortsetzen und eine geplante Kündigung zurücknehmen – noch keine Tarifwechsel oder Rabatte. Paddle hat keine Idempotenzschlüssel: COLVO markiert den Grund jeder Erstattung mit [colvo:<operation id>] und sucht vor jedem Wiederholungsversuch danach.
  • Chargebee – verbunden über die Projektseite (Add a connection → Chargebee) oder POST /v1/projects/{id}/connections/chargebee mit site (z. B. acme-test) + api_key. Chargebee-Schlüssel lassen sich nicht auf einzelne Aktionen beschränken: Verwenden Sie einen Vollzugriffsschlüssel vom Typ Write key, der nur für COLVO erstellt wurde (ein reiner Leseschlüssel wird abgelehnt; ein Schlüssel, der löschen kann, erhält eine Warnung). Die Antwort enthält Webhook-URL, Benutzername und Passwort (einmalig angezeigt). Auf Chargebee nennt eine Erstattung eine Rechnung (invoice_id oder payment_id = die Rechnungs-ID) und wird zu einer erstattungsfähigen Gutschrift; Kündigen, Pausieren, Fortsetzen, Kündigung zurücknehmen, Tarifwechsel (Item Prices) und Gutscheine funktionieren wie bei Stripe. Schreibvorgänge tragen chargebee-idempotency-key = die Operations-ID; Chargebee bewahrt Schlüssel 30 Minuten auf, daher sendet COLVO danach nie einen Schreibvorgang erneut – es eröffnet einen Vorfall, den eine Person prüft.

Jedes Projekt hat eine Standard-Guard-Verbindung; ein Mandat kann eine andere angeben.

Limits pro Endkunde

GET / PUT /v1/projects/{id}/end-user-caps – bis zu sechs Limits pro Projekt, bezogen auf die customer_id des Mandatsgegenstands:

{ "caps": [
  { "window": "day",   "max_actions": 3,                          "action_on_exceed": "HOLD" },
  { "window": "month", "max_amount_minor": 20000, "action_on_exceed": "DENY" }
] }
Mandate und Verbindungen · Docs · COLVO