Zum Hauptinhalt springen
RESTJSONOpenAPI 3.1

doWallet API

Pässe für Apple Wallet und Google Wallet ausstellen, ändern und entwerten, Ereignisse empfangen und Einlösungen melden. Diese Referenz beschreibt jeden Endpunkt mit Feldern, Antworten und einem Beispiel, das du direkt kopieren kannst.

Schritt 1: API-Schlüssel erstellen

Einstellungen › Entwickler › API-Schlüssel erstellen (nur Inhaberin oder Inhaber). Berechtigungen: passes:issue zum Ausstellen, passes:write zum Ändern, templates:write für die Feldliste der Vorlage.

API-Schlüssel erstellen →

Schritt 2: Pass ausstellen

Ein Aufruf pro Kauf, Anmeldung oder Vertrag. Die Rezepte unten zeigen den ganzen Ablauf mit curl.

Rezepte →

Schritt 3: Ereignisse empfangen

Webhook mit Ereignissen aus dem Katalog anlegen, z. B. Pass im Wallet gespeichert oder Pass genutzt.

Webhooks →

Basis-URL

Produktionhttps://api.dowallet.de
Diese Umgebunghttps://api.dowallet.dev

Alle Pfade sind versioniert (/v1/…). Zeitstempel ISO 8601 in UTC, Beträge in Cent, Antworten JSON.

Authentifizierung

Integrationen nutzen einen API-Schlüssel als Bearer-Token. Die Web-App selbst verwendet eine Cookie-Sitzung; für Server-zu-Server-Aufrufe brauchst du das nicht.

  • Bindung: Ein Schlüssel gehört zu einer Organisation, gilt auf Wunsch nur für einen Workspace und handelt mit der Rolle der Person, die ihn angelegt hat, nie mit Plattform-Admin-Rechten.
  • Scopes: Lesende Aufrufe brauchen den Lese-Scope (etwa passes:read, templates:read), alle anderen den Schreib-Scope (passes:issue zum Ausstellen, passes:write zum Ändern, templates:write für Feldliste, Wertquelle und Code-Listen, webhooks:write für Webhooks). Die Pass-Routen prüfen das sofort, die übrigen zuerst im Beobachtungsmodus, danach mit 403 missing_scope samt den nötigen Scopes. Die ganze Tabelle steht in der interaktiven Konsole unter „Scopes“.
  • Nur im Browser: Die Verwaltung der Organisation (Team, Einladungen, API-Schlüssel, Rechnungen) und das eigene Konto gehen nur mit Anmeldung in der App.
Authorization: Bearer dwlt_xxxxxxxxxxxxxxxxxxxxxxxx

Rate-Limits und Idempotenz

Aufrufe sind je Token begrenzt, ohne Anmeldung je IP; bei 429 den Header Retry-After beachten. Viele Pässe stellst du gebündelt aus, bis 100 je Aufruf. Ein Idempotency-Key macht schreibende Aufrufe wiederholbar: 24 Stunden lang liefert derselbe Schlüssel dieselbe Antwort und legt nichts doppelt an. Bei Einlösungen verhindert zusätzlich externalId, dass dieselbe Einlösung zweimal zählt.

Fehler

Jeder Fehler kommt als Envelope mit stabiler Kennung und einer Request-ID für den Support.

{
  "error": {
    "type": "https://docs.dowallet.de/errors/validation_failed",
    "title": "Validation failed",
    "status": 422,
    "code": "validation_failed",
    "detail": "Die Attribute passen nicht zur Feldliste der Vorlage.",
    "fields": { "attributes.saal": ["Pflichtfeld fehlt"] },
    "requestId": "req-8f3a…"
  }
}
401Token fehlt, ist abgelaufen oder widerrufen
402Funktion nicht im Paket oder Kontingent erreicht
403Rolle reicht nicht (permission_denied) oder dem Token fehlt ein Scope (missing_scope)
404Objekt gehört nicht zu deiner Organisation
409Konflikt, z. B. Code schon vergeben (code_in_use) oder Pass schon entwertet
422Validierung fehlgeschlagen, fields nennt die Felder
429Rate-Limit, Retry-After beachten
503Kein Code verfügbar (codes_exhausted)

Webhook-Signatur

Ausgehende Zustellungen und Meldungen an eine Empfangs-URL tragen dieselbe Signatur. Prüfe sie, bevor du den Body verarbeitest; ein Zeitstempel älter als 5 Minuten gilt nicht. Während einer Secret-Rotation stehen zwei v1=-Werte im Header (neues und altes Secret): eine Übereinstimmung genügt.

x-dowallet-signature: t=1758000000,v1=<hex(hmac_sha256(secret, t + "." + body))>[,v1=<zweite Signatur>]
x-dowallet-event-id: <Ereignis-ID, gleich bei jeder Wiederholung und beim erneuten Senden>
x-dowallet-event: pass.redeemed

Die Prüfung in Node.js, PHP und Python, jeweils über den rohen Body:

// Node.js
import { createHmac, timingSafeEqual } from "node:crypto"
export function verify(secret, header, rawBody) {
  const parts = Object.fromEntries(header.split(",").map((p) => p.split("=")))
  const t = Number(parts.t)
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return false
  const expected = createHmac("sha256", secret).update(`${t}.`).update(rawBody).digest("hex")
  return header.split(",").filter((p) => p.startsWith("v1=")).map((p) => p.slice(3))
    .some((sig) => sig.length === expected.length && timingSafeEqual(Buffer.from(sig), Buffer.from(expected)))
}
// PHP
function verify(string $secret, string $header, string $rawBody): bool {
  parse_str(str_replace(",", "&", $header), $parts);
  $t = (int) ($parts["t"] ?? 0);
  if ($t === 0 || abs(time() - $t) > 300) return false;
  $expected = hash_hmac("sha256", $t . "." . $rawBody, $secret);
  foreach (explode(",", $header) as $p) {
    if (str_starts_with($p, "v1=") && hash_equals($expected, substr($p, 3))) return true;
  }
  return false;
}
# Python
import hmac, hashlib, time
def verify(secret: str, header: str, raw_body: bytes) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t = int(parts.get("t", "0"))
    if not t or abs(time.time() - t) > 300:
        return False
    expected = hmac.new(secret.encode(), f"{t}.".encode() + raw_body, hashlib.sha256).hexdigest()
    sigs = [p[3:] for p in header.split(",") if p.startswith("v1=")]
    return any(hmac.compare_digest(s, expected) for s in sigs)

Jede Zustellung lässt sich in den Einstellungen unter Webhooks einsehen (gesendete Kopfzeilen, Nutzlast, Antwort deines Endpunkts) und erneut senden; das Secret rotierst du dort mit einer Übergangsfrist von bis zu 72 Stunden.

MCP-Server

Für Claude Desktop, Cursor und andere MCP-Clients gibt es @dowallet/mcp-server: elf Werkzeuge über dieselbe API (Workspaces, Vorlagen, Kampagnen, Zielgruppen, Pässe mit Wallet-Status, Kennzahlen, Trichter) und mit den passenden Scopes auch Schreiben (Pass ausstellen, Push senden, Vorlage veröffentlichen). Der Server zeigt nur die Werkzeuge, die der Token darf.

{
  "mcpServers": {
    "dowallet": {
      "command": "npx",
      "args": ["-y", "@dowallet/mcp-server"],
      "env": { "DOWALLET_API_BASE": "https://api.dowallet.dev", "DOWALLET_API_TOKEN": "dwlt_…" }
    }
  }
}

Rezepte

Vier Abläufe von der Vorlage bis zum Pass im Wallet. Setze die Variablen einmal, dann läuft jedes Beispiel per Kopieren. Die Vorlage legst du in der App an und veröffentlichst sie; die Aufrufe hier setzen Feldliste und Wertquelle und stellen die Pässe aus.

Variablenshell
export DOWALLET_API="https://api.dowallet.dev"
export DOWALLET_TOKEN="dwlt_…"   # Einstellungen › Entwickler › API-Schlüssel
export WORKSPACE_ID="…"          # Seite /redemptions → Anbindung
export TEMPLATE_ID="…"           # Adresse des Editors: /templates/<ID>

Kino, Theater, Konzert

Ticket pro Kauf

Dein Ticketing-System verkauft ein Ticket, doWallet stellt den Pass dazu aus. Film, Saal und Platz stehen im Pass, der Barcode trägt deinen Ticketing-Code, damit die Einlass-Scanner ihn lesen.

Token-Scope

  • passes:issuePässe ausstellen
  • templates:writeFeldliste an die Vorlage

Die Feldliste setzt der Token mit der Rolle der Person, die ihn angelegt hat (ab editor).

Webhook-Ereignisse

  • pass.createdPass ausgestellt
  • pass.registeredPass im Wallet gespeichert
  • pass.redeemedPass eingelöst
  1. 1

    Feldliste an die Vorlage

    Einmal je Vorlage. Im Editor legst du die Felder mit {{attr.film}}, {{attr.saal}} und {{attr.platz}} auf den Pass und veröffentlichst die Vorlage; der Barcode steht auf {{code}}. Das Feld mit der Rolle eventStart ist der Beginn der Vorstellung.

    Anfragecurl
    curl -X PATCH "$DOWALLET_API/v1/templates/$TEMPLATE_ID" \
      -H "Authorization: Bearer $DOWALLET_TOKEN" \
      -H "Content-Type: application/json" \
      -d '{
      "attributeSchema": [
        { "key": "film", "label": "Film", "type": "text", "required": true },
        { "key": "saal", "label": "Saal", "type": "text", "required": true },
        { "key": "platz", "label": "Platz", "type": "text" },
        { "key": "beginn", "label": "Beginn", "type": "date", "role": "eventStart" }
      ]
    }'
  2. 2

    Pass pro Kauf ausstellen

    Ein Aufruf je Ticket. code ist dein Ticketing-Code: je Vorlage eindeutig, sonst 409 code_in_use. Fehlt ein Pflichtfeld, antwortet die API mit 422 und nennt es in fields, z. B. attributes.saal. Mit der Bestellnummer als Idempotency-Key legt eine Wiederholung keinen zweiten Pass an.

    Anfragecurl
    curl -X POST "$DOWALLET_API/v1/workspaces/$WORKSPACE_ID/passes" \
      -H "Authorization: Bearer $DOWALLET_TOKEN" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: bestellung-4711-1" \
      -d @- <<JSON
    {
      "templateId": "$TEMPLATE_ID",
      "attributes": { "film": "Das Lehrerzimmer", "saal": "5", "platz": "H12", "beginn": "2026-10-03T20:15:00+02:00" },
      "code": "TK-889"
    }
    JSON
    Antwort201
    {
      "passId": "5d0c2f4e-8a1b-4c3d-9e7f-1a2b3c4d5e6f",
      "serial": "dwp_Q3vX9kLm2Pw",
      "code": "TK-889",
      "validUntil": null,
      "apple": { "downloadUrl": "https://api.dowallet.de/api/public/passes/dwp_Q3vX9kLm2Pw.pkpass?d=…" },
      "google": { "saveUrl": "https://pay.google.com/gp/v/save/…" }
    }

Ohne code im Aufruf: feste Wertquelle

Soll der Code als Feld mitkommen, ergänze die Feldliste um { "key": "ticket_code", "label": "Ticketcode", "type": "text", "required": true } und setze die Wertquelle der Vorlage auf {{attr.ticket_code}}. Dann schickst du ticket_code in attributes und lässt code weg. Die Eindeutigkeit je Vorlage prüft doWallet nur beim Feld code.

Anfragecurl
curl -X PATCH "$DOWALLET_API/v1/templates/$TEMPLATE_ID" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "valueSource": { "mode": "static", "value": "{{attr.ticket_code}}" }
}'
  • Die Links aus der Antwort (apple.downloadUrl ohne Ablauf, google.saveUrl) gehören in die Bestellbestätigung. google ist null, solange die Organisation keinen Google-Zugang hat.
  • Saalwechsel für ein einzelnes Ticket: PATCH /v1/passes/{passId}/attributes mit set, notify "push" und message, wie im Rezept „Karte pro Vertrag“.

Ereignisse abonnieren

Ein Webhook meldet deinem System die Ereignisse eines Rezepts. Welche es gibt, liefert GET /v1/webhook-event-types. Die Antwort enthält das Signatur-Secret genau einmal; prüfe damit jede Zustellung (x-dowallet-signature). Anlegen darf ein Org-Admin, der Token braucht dafür webhooks:write.

Anfragecurl
curl -X POST "$DOWALLET_API/v1/workspaces/$WORKSPACE_ID/webhooks" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.com/dowallet/webhook",
  "eventTypes": ["pass.created", "pass.registered", "pass.redeemed"]
}'

OpenAPI-Dokument: openapi.json. Interaktive Konsole: api.dowallet.dev/docs

Integration

API-Schlüssel

Tokens für Server-zu-Server-Zugriff anlegen, auflisten und widerrufen.

GET/v1/orgs/{orgId}/api-tokens

API-Tokens auflisten

Alle API-Tokens der Organisation ohne Geheimnis (nur Präfix, Scopes, Daten, Ersteller). Inhaber und org-weite Admins; Admins sehen die Liste nur lesend (canManage: false) und in owners, wer Tokens anlegen und widerrufen darf.

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/api-tokens" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "tokenPrefix": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx",
      "scopes": [
        "text"
      ],
      "lastUsedAt": "2026-09-15T10:32:00Z",
      "lastUsedRoute": "text",
      "lastUsedIpClass": "text",
      "expiresAt": "2026-09-15T10:32:00Z",
      "revokedAt": "2026-09-15T10:32:00Z",
      "createdAt": "2026-09-15T10:32:00Z",
      "createdBy": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "name": "Sommer-Aktion"
      }
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  },
  "canManage": true,
  "owners": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion"
    }
  ]
}
POST/v1/orgs/{orgId}/api-tokens

API-Token anlegen

Erzeugt einen Bearer-Token (dwlt_…) mit Scopes (scopes, z. B. passes:issue, templates:read, events:write; die Tabelle je Routenfamilie steht unter „Authentifizierung“), optional an einen Workspace gebunden (workspaceId) und mit Ablauf (expiresAt). Der Token handelt mit der Rolle der Person, die ihn anlegt, nur in dieser Organisation und Bindung, nie mit Plattform-Admin-Rechten. Die Antwort enthält den Klartext genau einmal; gespeichert wird nur der Hash. Org-Owner, nur mit Anmeldung im Browser: ein Token legt keine Tokens an (403).

Pfad-Parameter

  • orgIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–120 Zeichen

  • scopesstring[]Pflicht

    1–∞ Einträge

  • workspaceIduuid | nulloptional
  • expiresAtdate-time | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/api-tokens" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "scopes": [
    "text"
  ],
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "expiresAt": "2026-09-15T10:32:00Z"
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "name": "Sommer-Aktion",
    "tokenPrefix": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx",
    "scopes": [
      "text"
    ],
    "lastUsedAt": "2026-09-15T10:32:00Z",
    "lastUsedRoute": "text",
    "lastUsedIpClass": "text",
    "expiresAt": "2026-09-15T10:32:00Z",
    "revokedAt": "2026-09-15T10:32:00Z",
    "createdAt": "2026-09-15T10:32:00Z"
  },
  "plaintext": "Heute 20 % auf alles. Nur bis Ladenschluss."
}
POST/v1/api-tokens/{id}/rotate

API-Token rotieren

Erzeugt einen neuen Token mit Name, Scopes, Bindung und Ablauf des alten und liefert den Klartext einmal. Der alte Token arbeitet noch graceMinutes (0 bis 1440, Standard 0) weiter, dann 401; so wechselt ein Deployment ohne Lücke. Org-Owner, nur mit Anmeldung im Browser.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • graceMinutesintegeroptional

    0 bis 1440

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/api-tokens/{id}/rotate" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "graceMinutes": 0
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "name": "Sommer-Aktion",
    "tokenPrefix": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx",
    "scopes": [
      "text"
    ],
    "lastUsedAt": "2026-09-15T10:32:00Z",
    "lastUsedRoute": "text",
    "lastUsedIpClass": "text",
    "expiresAt": "2026-09-15T10:32:00Z",
    "revokedAt": "2026-09-15T10:32:00Z",
    "createdAt": "2026-09-15T10:32:00Z"
  },
  "plaintext": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "previousValidUntil": "2026-09-15T10:32:00Z"
}
PATCH/v1/api-tokens/{id}

API-Token ändern

Name, Scopes oder Ablauf eines aktiven Tokens. Org-Owner, nur mit Anmeldung im Browser; ein widerrufener oder rotierter Token ist 409.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • scopesstring[]optional

    1–∞ Einträge

  • expiresAtdate-time | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/api-tokens/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "scopes": [
    "text"
  ],
  "expiresAt": "2026-09-15T10:32:00Z"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "tokenPrefix": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx",
  "scopes": [
    "text"
  ],
  "lastUsedAt": "2026-09-15T10:32:00Z",
  "lastUsedRoute": "text",
  "lastUsedIpClass": "text",
  "expiresAt": "2026-09-15T10:32:00Z",
  "revokedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}
DELETE/v1/api-tokens/{id}

API-Token widerrufen

Sofort wirksam. Aufrufe mit diesem Token bekommen ab jetzt 401. Org-Owner, nur mit Anmeldung im Browser.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/api-tokens/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
GET/v1/api-tokens/{id}/requests

Aufrufe eines Tokens

Die letzten Aufrufe (bis 200) mit Methode, Routenmuster, Status, Dauer und ob der Scope der Route fehlte (scopeMissing, requiredScopes). Nie Körper oder Adresse; 30 Tage. Org-Admin.

Pfad-Parameter

  • iduuidPflicht

Query-Parameter

  • limitintegeroptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/api-tokens/{id}/requests?limit=50" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "method": "text",
      "route": "text",
      "status": 1,
      "latencyMs": 1,
      "scopeMissing": true,
      "requiredScopes": [
        "text"
      ],
      "requestId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "occurredAt": "2026-09-15T10:32:00Z"
    }
  ]
}
GET/v1/orgs/{orgId}/api-requests/summary

Aufrufe je Token

Aufrufe und fehlende Scopes je Token der letzten days Tage (Standard 7) mit letzter Route und Zeitpunkt. Org-Admin.

Pfad-Parameter

  • orgIduuidPflicht

Query-Parameter

  • daysintegeroptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/api-requests/summary?days=7" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "days": 1,
  "calls": 1,
  "scopeMissing": 1,
  "tokens": [
    {
      "tokenId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "calls": 1,
      "scopeMissing": 1,
      "lastRoute": "text",
      "lastAt": "2026-09-15T10:32:00Z"
    }
  ]
}
GET/v1/orgs/{orgId}/token-scopes

Scope-Durchsetzung lesen

Ob fehlende Scopes für die Tokens dieser Organisation 403 missing_scope bedeuten (enforce), der Modus der Plattform (globalMode) und wie viele Aufrufe der letzten 7 Tage einen Scope vermissten. Org-Admin.

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/token-scopes" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "enforce": true,
  "enforcedAt": "2026-09-15T10:32:00Z",
  "globalMode": "monitor",
  "missingLast7d": 1
}
PATCH/v1/orgs/{orgId}/token-scopes

Scope-Durchsetzung schalten

enforce: true schaltet die Prüfung für die eigenen Tokens scharf (bis dahin nur Protokoll); false nimmt sie zurück, solange die Plattform nicht selbst durchsetzt. Org-Owner, nur mit Anmeldung im Browser.

Pfad-Parameter

  • orgIduuidPflicht

Request-Body (JSON)

  • enforcebooleanPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/orgs/{orgId}/token-scopes" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "enforce": true
}'
Antwort200
{
  "enforce": true,
  "enforcedAt": "2026-09-15T10:32:00Z",
  "globalMode": "monitor",
  "missingLast7d": 1
}

Einlösungen

Nutzungen melden, importieren und auswerten.

POST/v1/workspaces/{workspaceId}/redemptions/import

Nutzungen aus CSV importieren

Accepts multipart/form-data with a file part (≤ 10 MB) or application/json { "csv": "…" }. Delimiter (, ; tab) and header names are detected; see docs/redemptions.md for the recognised columns. Writes redemptionLogged events through the same ingest as the bulk API (externalId idempotency, pass resolution by id / serial / code). Editor role or above; session or API token. Rate limit 10/min. Not on the free plan (402).

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 413Zu groß
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/redemptions/import" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "total": 1,
  "accepted": 1,
  "duplicates": 1,
  "unmatched": [
    {
      "index": 1,
      "row": {},
      "reason": "text"
    }
  ],
  "errors": [
    {
      "index": 1,
      "row": {},
      "reason": "text"
    }
  ],
  "mapping": {
    "delimiter": ",",
    "columns": {},
    "ignoredHeaders": [
      "text"
    ]
  },
  "parseErrors": [
    {
      "line": 1,
      "reason": "text"
    }
  ],
  "preview": [
    {}
  ]
}
POST/v1/workspaces/{workspaceId}/redemptions/import/preview

Nutzungs-CSV prüfen, ohne zu schreiben

Gleiche Eingabe wie der Import. Liefert die erkannte Spaltenzuordnung, die ersten 20 gelesenen Zeilen und wie viele Zeilen ohne Treffer oder doppelt wären. Es wird nichts geschrieben. Wie der Import nicht im Free-Plan (402).

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 413Zu groß
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/redemptions/import/preview" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "mapping": {
    "delimiter": ",",
    "columns": {},
    "ignoredHeaders": [
      "text"
    ]
  },
  "rowCount": 1,
  "rows": [
    {}
  ],
  "parseErrors": [
    {
      "line": 1,
      "reason": "text"
    }
  ],
  "unmatched": 1,
  "duplicates": 1
}
GET/v1/workspaces/{workspaceId}/redemptions

Nutzungen auflisten (neueste zuerst)

Cursor-Paginierung über pagination.nextCursor. Filter: templateId, source (exakt, mehrere durch Komma), locationName (Filiale, ohne Groß-/Kleinschreibung), kind (redemption | checkin | stamp; Zeilen ohne Art zählen als redemption), campaignId, passId, from/to. Jede Rolle im Workspace, auch im Free-Plan. pass ist null, wenn das Ereignis keinen Pass (mehr) hat.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • limitintegeroptional
  • cursorstringoptional
  • passIduuidoptional
  • campaignIduuidoptional
  • templateIduuidoptional
  • sourcestringoptional
  • locationNamestringoptional
  • kindredemption | checkin | stamp | pointsoptional
  • fromstringoptional
  • tostringoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/redemptions?limit=100&cursor=text&passId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "occurredAt": "2026-09-15T10:32:00Z",
      "kind": "redemption",
      "pass": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "serial": "ABC123456",
        "templateName": "Sommer-Aktion"
      },
      "amountCents": 1250,
      "currency": "EUR",
      "locationName": "Sommer-Aktion",
      "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "source": "text",
      "externalId": "bon-4711",
      "actor": {
        "kind": "user",
        "label": "Sommer-Aktion"
      }
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/redemptions

Nutzungen melden (Sammelaufruf)

Up to 5,000 redemptions per call. Each row names the pass by pass.id, pass.serial or pass.code (resolved in that order, within the workspace). externalId (e.g. the receipt number) is the idempotency key per workspace: resending the same externalId is reported under duplicates, never stored twice. Rows without externalId are deduped on (pass, redeemedAt) inside the batch. redeemedAt defaults to now. Editor role or above; session or API token (Authorization: Bearer dwlt_…). Rate limit 60/min. Not on the free plan (402).

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • redemptionsobject[]Pflicht

    1–5000 Einträge

  • passobjectoptional
  • iduuidoptional
  • serialstringoptional

    1–200 Zeichen

  • codestringoptional

    1–200 Zeichen

  • redeemedAtdate-timeoptional
  • kind"redemption" | "checkin" | "stamp" | "points"optional
  • pointsintegeroptional

    -100000 bis 100000

  • rewardbooleanoptional
  • rewardIduuidoptional
  • amountCentsintegeroptional

    0 bis 100000000

  • currencystringoptional

    3–3 Zeichen

  • locationIduuidoptional
  • locationNamestringoptional

    1–200 Zeichen

  • locationRefstringoptional

    1–80 Zeichen

  • campaignIduuidoptional
  • externalIdstringoptional

    1–200 Zeichen

  • notestringoptional

    0–2000 Zeichen

  • passIduuidoptional
  • serialstringoptional

    1–200 Zeichen

  • codestringoptional

    1–200 Zeichen

  • occurredAtdate-timeoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/redemptions" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "redemptions": [
    {}
  ]
}'
Antwort200
{
  "total": 1,
  "accepted": 1,
  "duplicates": 1,
  "unmatched": [
    {
      "index": 1,
      "row": {},
      "reason": "text"
    }
  ],
  "errors": [
    {
      "index": 1,
      "row": {},
      "reason": "text"
    }
  ]
}
GET/v1/workspaces/{workspaceId}/redemptions/totals

Nutzungen zählen (mit den Filtern der Liste)

Anzahl und Summe der Beträge in Cent über alle Zeilen, die die Liste mit denselben Filtern zeigt. Jede Rolle im Workspace.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • passIduuidoptional
  • campaignIduuidoptional
  • templateIduuidoptional
  • sourcestringoptional
  • locationNamestringoptional
  • kindredemption | checkin | stamp | pointsoptional
  • fromstringoptional
  • tostringoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/redemptions/totals?passId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01&campaignId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01&templateId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "count": 1,
  "amountCents": 1250
}
GET/v1/workspaces/{workspaceId}/redemptions/export.csv

Nutzungen als CSV (mit den Filtern der Liste)

Eine Zeile je Nutzung, neueste zuerst, höchstens 50.000: zeitpunkt;seriennummer;vorlage;art;betrag_cent;waehrung;filiale;quelle;kampagne_id;externe_id (Zeitpunkt ISO 8601 in UTC). Semikolon, UTF-8 mit BOM und CRLF; Zellen, die mit = + - @ beginnen, bleiben Text. Jede Rolle im Workspace, jeder Export steht im Audit-Log (redemptions.export).

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • passIduuidoptional
  • campaignIduuidoptional
  • templateIduuidoptional
  • sourcestringoptional
  • locationNamestringoptional
  • kindredemption | checkin | stamp | pointsoptional
  • fromstringoptional
  • tostringoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/redemptions/export.csv?passId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01&campaignId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01&templateId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
"text"
GET/v1/workspaces/{workspaceId}/redemptions/locations

Filialen, die in den Nutzungen vorkommen

Jede Filiale (payload.locationName, ältere Zeilen payload.location, sonst die Filialnummer payload.locationRef) einmal, ohne Groß-/Kleinschreibung zusammengefasst, mit der Zahl der Nutzungen; häufigste zuerst, höchstens 500. from/to begrenzen den Zeitraum (Vorgabe: alle). Der Name passt als locationName in die Liste. Jede Rolle im Workspace.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • fromstringoptional
  • tostringoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/redemptions/locations?from=2026-09-15T10%3A32%3A00Z&to=2026-09-15T10%3A32%3A00Z" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "locationName": "Sommer-Aktion",
      "count": 1
    }
  ]
}
GET/v1/workspaces/{workspaceId}/redemptions/summary

Nutzungen im Zeitraum: gesamt, Umsatz, je Tag, je Filiale, je Quelle, wiederkehrende Gäste, Top-Vorlagen

from/to: Zeitstempel oder Kalendertag (YYYY-MM-DD, in der Zeitzone des Workspace: from ab Tagesbeginn, to bis Tagesende). Vorgabe: die letzten 30 Kalendertage einschließlich heute; höchstens 366 Tage (sonst 422). Jede Zahl zählt Nutzungen jeder Art (Einlösung, Einlass, Stempel) im Zeitraum; checkins und stamps sagen, wie viele davon Einlass bzw. Stempel sind. byDay hat einen Eintrag je Kalendertag von from bis to, die Summe ist total. byLocation fasst Filialen wie der Filter im Protokoll zusammen, plus eine Zeile ohne Filiale. returning: Pässe mit mindestens einer Nutzung im Zeitraum und davon die mit mindestens zwei. Jede Rolle im Workspace, auch im Free-Plan.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • fromstringoptional
  • tostringoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/redemptions/summary?from=2026-09-15T10%3A32%3A00Z&to=2026-09-15T10%3A32%3A00Z" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "range": {
    "from": "2026-09-15T10:32:00Z",
    "to": "2026-09-15T10:32:00Z"
  },
  "total": 1,
  "amountCents": 1250,
  "bySource": [
    {
      "source": "text",
      "count": 1
    }
  ],
  "byDay": [
    {
      "date": "text",
      "day": "text",
      "count": 1,
      "checkins": 1,
      "stamps": 1
    }
  ],
  "byLocation": [
    {
      "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "locationName": "Sommer-Aktion",
      "count": 1,
      "amountCents": 1250,
      "checkins": 1,
      "stamps": 1
    }
  ],
  "returning": {
    "uniquePasses": 1,
    "returningPasses": 1,
    "repeatRate": 1
  },
  "topTemplates": [
    {
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "templateName": "Sommer-Aktion",
      "count": 1
    }
  ]
}
GET/v1/workspaces/{workspaceId}/scan/lookup

Gescannten Wert prüfen

value ist der Barcode-Inhalt, die Seriennummer oder die Pass-UUID (auch ein Link, der einen davon trägt), aufgelöst nur in diesem Workspace. status: valid, already_redeemed, limit_reached, expired, voided oder not_found (mit reason: "ambiguous_value", wenn der Code auf mehreren Pässen steht). actions sind die Knöpfe des Scanners, die erste ist die Hauptaktion; enabled: false trägt reason. Stempel und Prämie folgen der Treue-Regel der Vorlage (GET /v1/templates/{id}/loyalty-rules), display.lines beginnt dann mit dem Stand („7 / 10 Stempel“, „250 Punkte · Gold“). Ein Scanner-Gerät sieht nur seine freigegebenen Aktionen; ein Pass einer Vorlage, die es nicht nutzen darf, oder ohne freigegebene Aktion ist 403 device_not_allowed. Schreibt nichts. Browser-Sitzung mit Rolle editor oder höher oder ein gekoppeltes Scanner-Gerät (Authorization: Bearer dwsd_…); 300 Aufrufe je Minute und Person oder Gerät. Ist der Scanner für die Organisation nicht eingeschaltet (nur doWallet schaltet ihn ein): 403 feature_disabled, für Personen wie für Geräte.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • valuestringPflicht
  • localede | en | froptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/scan/lookup?value=text&locale=de" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "status": "valid",
  "reason": "ambiguous_value",
  "pass": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "serial": "ABC123456",
    "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "templateName": "Sommer-Aktion",
    "passType": "text",
    "useCase": "text",
    "isTest": true,
    "validUntil": "2026-09-15T10:32:00Z",
    "expiredAt": "2026-09-15T10:32:00Z",
    "voidedAt": "2026-09-15T10:32:00Z",
    "redeemedAt": "2026-09-15T10:32:00Z"
  },
  "display": {
    "title": "Sommer-Aktion",
    "subtitle": "Sommer-Aktion",
    "lines": [
      "text"
    ]
  },
  "policy": {
    "mode": "unlimited",
    "maxCount": 1,
    "voidAfterRedeem": true
  },
  "useCount": 1,
  "lastRedemption": {
    "at": "2026-09-15T10:32:00Z",
    "kind": "redemption",
    "locationName": "Sommer-Aktion"
  },
  "actions": [
    {
      "key": "redeem",
      "label": "Sommer-Aktion",
      "primary": true,
      "enabled": true
    }
  ],
  "loyalty": {
    "kind": "stamps",
    "balance": 1,
    "goal": 1,
    "reward": "text",
    "tier": "text",
    "rewardAvailable": true
  }
}
POST/v1/workspaces/{workspaceId}/scans

Scan ausführen (Einlösen oder Einlass)

action redeem schreibt eine Einlösung, checkin einen Einlass, beide als Nutzung mit Quelle app und dem Scanner als payload.actor (Person oder Gerät). Die Einlöse-Regel der Vorlage gilt: eine abgelehnte Nutzung antwortet 409 mit already_redeemed, limit_reached, pass_expired oder pass_voided, details.lastRedemption und der aktuellen Ansicht. Schöpft die Nutzung die Regel aus und ist Entwerten eingestellt, ist der Pass danach im Wallet entwertet. 200 liefert die Ansicht nach der Nutzung, jeder gebuchte Scan schreibt den Audit-Eintrag pass.scan. stamp bucht +1 Stempel (Nutzung der Art stamp), reward löst die Prämie ein (−Ziel, Nutzung der Art redemption mit payload.reason: "reward", gegen die Einlöse-Regel geprüft); beides auch im Free-Plan. Kein Pass zum Wert: 404; Code auf mehreren Pässen: 409 ambiguous_value; Aktion nicht angeboten: 422; Stempel oder Prämie ohne Treue-Regel: 422 loyalty_rule_missing; Prämie noch nicht erreicht: 409 reward_not_available. Ein Scanner-Gerät bucht immer an seinem festen Standort (ein anderer locationId ist 403) und nur freigegebene Aktionen und Vorlagen (sonst 403 device_not_allowed); Nutzung und Audit tragen dann payload.actor.kind = "device" und keine Person. Ein widerrufenes Gerät bekommt 401 device_revoked. Header Idempotency-Key (24 h, je Person oder Gerät) macht Wiederholungen sicher. Browser-Sitzung mit Rolle editor oder höher oder ein gekoppeltes Scanner-Gerät; 300 Aufrufe je Minute und Person oder Gerät. Ist der Scanner für die Organisation nicht eingeschaltet (nur doWallet schaltet ihn ein): 403 feature_disabled, für Personen wie für Geräte.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • valuestringPflicht

    1–512 Zeichen

  • action"redeem" | "checkin" | "stamp" | "reward" | "points"Pflicht
  • locationIduuidoptional
  • locale"de" | "en" | "fr"optional
  • amountCentsintegeroptional

    1 bis 100000000

  • pointsintegeroptional

    1 bis 100000

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/scans" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "value": "text",
  "action": "redeem",
  "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "locale": "de",
  "amountCents": 1250,
  "points": 1
}'
Antwort200
{
  "status": "valid",
  "reason": "ambiguous_value",
  "pass": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "serial": "ABC123456",
    "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "templateName": "Sommer-Aktion",
    "passType": "text",
    "useCase": "text",
    "isTest": true,
    "validUntil": "2026-09-15T10:32:00Z",
    "expiredAt": "2026-09-15T10:32:00Z",
    "voidedAt": "2026-09-15T10:32:00Z",
    "redeemedAt": "2026-09-15T10:32:00Z"
  },
  "display": {
    "title": "Sommer-Aktion",
    "subtitle": "Sommer-Aktion",
    "lines": [
      "text"
    ]
  },
  "policy": {
    "mode": "unlimited",
    "maxCount": 1,
    "voidAfterRedeem": true
  },
  "useCount": 1,
  "lastRedemption": {
    "at": "2026-09-15T10:32:00Z",
    "kind": "redemption",
    "locationName": "Sommer-Aktion"
  },
  "actions": [
    {
      "key": "redeem",
      "label": "Sommer-Aktion",
      "primary": true,
      "enabled": true
    }
  ],
  "loyalty": {
    "kind": "stamps",
    "balance": 1,
    "goal": 1,
    "reward": "text",
    "tier": "text",
    "rewardAvailable": true
  },
  "result": "ok",
  "eventId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}
GET/v1/workspaces/{workspaceId}/scanner-devices

Scanner-Geräte auflisten

Alle Scanner-Geräte des Arbeitsbereichs, neueste zuerst, auch widerrufene (state: "revoked"). state: waiting (Kopplungscode offen), code_expired (Code abgelaufen, nie gekoppelt), paired, expired (Freigabe abgelaufen), revoked. Nur Browser-Sitzung mit Admin-Rechten im Arbeitsbereich. Ist der Scanner für die Organisation nicht eingeschaltet (nur doWallet schaltet ihn ein), antwortet die Route 403 feature_disabled.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/scanner-devices" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "locationName": "Sommer-Aktion",
      "allowedActions": [
        "redeem"
      ],
      "templateIds": [
        "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
      ],
      "pointsDefault": 1,
      "state": "waiting",
      "paired": true,
      "pairExpiresAt": "2026-09-15T10:32:00Z",
      "expiresAt": "2026-09-15T10:32:00Z",
      "revokedAt": "2026-09-15T10:32:00Z",
      "lastSeenAt": "2026-09-15T10:32:00Z",
      "createdAt": "2026-09-15T10:32:00Z"
    }
  ]
}
POST/v1/workspaces/{workspaceId}/scanner-devices

Scanner-Gerät anlegen

Legt ein Handy ohne Konto an, das nur scannt: name (1 bis 60 Zeichen), fester Standort locationId (optional), allowedActions (mindestens eine aus redeem, checkin, stamp, reward, points), optional templateIds (nur Pässe dieser Vorlagen; fehlt = alle) und expiresAt (Ende der Freigabe). Mit points bucht das Gerät auf einer Punktekarte „Punkte buchen“; pointsDefault (1 bis 100.000) sind dann feste Punkte je Scan, ohne Angabe fragt das Gerät nach Betrag oder Punkten. Antwort 201 mit dem Kopplungscode pairCode (8 Zeichen, einmalig, 15 Minuten gültig) und pairUrl für den QR: das zweite Handy öffnet ihn und scannt danach ohne Anmeldung. Nur Browser-Sitzung mit Admin-Rechten im Arbeitsbereich. Audit scanner_device.create (ohne Code). Ist der Scanner für die Organisation nicht eingeschaltet (nur doWallet schaltet ihn ein), antwortet die Route 403 feature_disabled.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–60 Zeichen

  • locationIduuid | nulloptional
  • allowedActions"redeem" | "checkin" | "stamp" | "reward" | "points"[]Pflicht

    1–5 Einträge

  • templateIdsuuid[] | nulloptional
  • expiresAtdate-time | nulloptional
  • pointsDefaultinteger | nulloptional

Antworten

  • 201Angelegt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/scanner-devices" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "allowedActions": [
    "redeem"
  ],
  "templateIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "expiresAt": "2026-09-15T10:32:00Z",
  "pointsDefault": 1
}'
Antwort201
{
  "device": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "name": "Sommer-Aktion",
    "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "locationName": "Sommer-Aktion",
    "allowedActions": [
      "redeem"
    ],
    "templateIds": [
      "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
    ],
    "pointsDefault": 1,
    "state": "waiting",
    "paired": true,
    "pairExpiresAt": "2026-09-15T10:32:00Z",
    "expiresAt": "2026-09-15T10:32:00Z",
    "revokedAt": "2026-09-15T10:32:00Z",
    "lastSeenAt": "2026-09-15T10:32:00Z",
    "createdAt": "2026-09-15T10:32:00Z"
  },
  "pairCode": "text",
  "pairUrl": "https://example.de/hook",
  "pairExpiresAt": "2026-09-15T10:32:00Z"
}
PATCH/v1/scanner-devices/{id}

Scanner-Gerät ändern

Ändert name, locationId (null = ohne Standort), allowedActions, templateIds (null = alle Vorlagen), expiresAt (null = unbegrenzt) oder pointsDefault (feste Punkte je Scan mit der Aktion points, null = fragen). Gilt ab dem nächsten Scan des Geräts, ohne neue Kopplung. Ein widerrufenes Gerät lässt sich nicht mehr ändern (409). Nur Browser-Sitzung mit Admin-Rechten im Arbeitsbereich. Audit scanner_device.update. Ist der Scanner für die Organisation nicht eingeschaltet (nur doWallet schaltet ihn ein), antwortet die Route 403 feature_disabled.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–60 Zeichen

  • locationIduuid | nulloptional
  • allowedActions"redeem" | "checkin" | "stamp" | "reward" | "points"[]optional

    1–5 Einträge

  • templateIdsuuid[] | nulloptional
  • expiresAtdate-time | nulloptional
  • pointsDefaultinteger | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/scanner-devices/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "allowedActions": [
    "redeem"
  ],
  "templateIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "expiresAt": "2026-09-15T10:32:00Z",
  "pointsDefault": 1
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "locationName": "Sommer-Aktion",
  "allowedActions": [
    "redeem"
  ],
  "templateIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "pointsDefault": 1,
  "state": "waiting",
  "paired": true,
  "pairExpiresAt": "2026-09-15T10:32:00Z",
  "expiresAt": "2026-09-15T10:32:00Z",
  "revokedAt": "2026-09-15T10:32:00Z",
  "lastSeenAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}
DELETE/v1/scanner-devices/{id}

Scanner-Gerät widerrufen

Setzt revokedAt und verwirft einen offenen Kopplungscode. Der nächste Scan des Handys antwortet 401 device_revoked. Endgültig: ein widerrufenes Gerät lässt sich nicht wieder freigeben, dafür ein neues anlegen. Ein zweites DELETE antwortet ebenfalls 204. Nur Browser-Sitzung mit Admin-Rechten im Arbeitsbereich. Audit scanner_device.revoke. Ist der Scanner für die Organisation nicht eingeschaltet (nur doWallet schaltet ihn ein), antwortet die Route 403 feature_disabled.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/scanner-devices/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/scanner-devices/{id}/pair-code

Neuen Kopplungscode ausgeben

Neuer Code (8 Zeichen, einmalig, 15 Minuten gültig) für dasselbe Gerät, etwa für ein neues Handy oder nach einem abgelaufenen Code; ein offener älterer Code verfällt. Ist das Gerät schon gekoppelt, scannt das bisherige Handy weiter, bis der neue Code eingelöst ist; danach antwortet es 401 device_revoked. Ein widerrufenes Gerät bekommt keinen Code (409). Nur Browser-Sitzung mit Admin-Rechten im Arbeitsbereich. Audit scanner_device.pair_code (ohne Code). Ist der Scanner für die Organisation nicht eingeschaltet (nur doWallet schaltet ihn ein), antwortet die Route 403 feature_disabled.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/scanner-devices/{id}/pair-code" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "device": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "name": "Sommer-Aktion",
    "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "locationName": "Sommer-Aktion",
    "allowedActions": [
      "redeem"
    ],
    "templateIds": [
      "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
    ],
    "pointsDefault": 1,
    "state": "waiting",
    "paired": true,
    "pairExpiresAt": "2026-09-15T10:32:00Z",
    "expiresAt": "2026-09-15T10:32:00Z",
    "revokedAt": "2026-09-15T10:32:00Z",
    "lastSeenAt": "2026-09-15T10:32:00Z",
    "createdAt": "2026-09-15T10:32:00Z"
  },
  "pairCode": "text",
  "pairUrl": "https://example.de/hook",
  "pairExpiresAt": "2026-09-15T10:32:00Z"
}

Webhooks

Ausgehende Webhooks mit Ereignissen aus dem Katalog, Zustellungen prüfen, Nutzungen über Empfangs-URLs annehmen.

GET/v1/webhook-event-types

Webhook-Ereignisse auflisten

Alle Ereignisse, die doWallet an Webhooks zustellt, mit Name, Bezeichnung und Beschreibung. Nur diese Namen lassen sich abonnieren; aliases sind frühere Namen, die weiter passen. Jede Zustellung trägt den Namen in type und im Header x-dowallet-event. Ohne Anmeldung lesbar.

Antworten

  • 200OK
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/webhook-event-types" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "name": "pass.redeemed",
      "label": "Pass eingelöst",
      "description": "Eine Nutzung wurde angenommen: am Scanner, von der Kasse über die Empfangs-URL, per API oder CSV-Import. Genau eine Zustellung je Nutzung; data.kind ist redemption oder checkin (Einlass).",
      "aliases": [
        "redemptionLogged",
        "redemption.logged"
      ],
      "example": {
        "passId": "7f0c…",
        "templateId": "2a1b…",
        "campaignId": null,
        "kind": "redemption",
        "locationName": "Filiale Hörde",
        "source": "scan"
      }
    }
  ]
}
GET/v1/workspaces/{workspaceId}/webhooks

Webhooks auflisten

Ausgehende Webhooks des Workspace mit abonnierten Ereignissen (eventTypes), Status, letzter Zustellung und Zahl der gescheiterten Zustellungen in Folge.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/webhooks" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "url": "https://example.de/hook",
      "eventTypes": [
        "pass.redeemed"
      ],
      "isActive": true,
      "lastDeliveryAt": "2026-09-15T10:32:00Z",
      "lastDeliveryStatus": 1,
      "failedDeliveriesInARow": 1,
      "createdAt": "2026-09-15T10:32:00Z",
      "disabledAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/webhooks

Webhook anlegen

Registriert eine HTTPS-URL für die Ereignisse in eventTypes (mindestens eins, Namen aus GET /v1/webhook-event-types). Die Antwort enthält das Signatur-Secret (whsec_…) einmalig. Jede Zustellung ist ein POST mit dem JSON-Umschlag { "id", "type", "occurredAt", "workspaceId", "data" }: type ist der Name aus dem Katalog, data hängt vom Ereignis ab. Kopfzeilen: x-dowallet-event (derselbe Name), x-dowallet-event-id (die id) und x-dowallet-signature: t=<unix>,v1=<hex(hmac_sha256(secret, t + "." + body))>. Org-Admin.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • urluriPflicht
  • eventTypesstring[]Pflicht

    1–∞ Einträge

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/webhooks" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.de/hook",
  "eventTypes": [
    "pass.redeemed"
  ]
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "url": "https://example.de/hook",
  "eventTypes": [
    "pass.redeemed"
  ],
  "isActive": true,
  "lastDeliveryAt": "2026-09-15T10:32:00Z",
  "lastDeliveryStatus": 1,
  "failedDeliveriesInARow": 1,
  "createdAt": "2026-09-15T10:32:00Z",
  "disabledAt": "2026-09-15T10:32:00Z",
  "secret": "text"
}
POST/v1/webhooks/{id}/test

Test-Zustellung senden

Schickt ein signiertes Test-Ereignis ({"type": "webhook.test"}) an die URL und liefert den Statuscode deines Endpunkts. Der Versuch erscheint in den Zustellungen.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/webhooks/{id}/test" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "ok": true,
  "status": 1,
  "error": "text"
}
GET/v1/webhooks/{id}/deliveries

Zustellungen einsehen

Die letzten 50 Zustellversuche mit Ereignis (eventType), Status, Antwortcode, dem Anfang der Antwort deines Endpunkts und, bei erneut gesendeten, der Herkunft (redeliveredFromId). Zur Fehlersuche auf deiner Seite.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/webhooks/{id}/deliveries" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "webhookId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "attempt": 1,
      "status": "active",
      "eventType": "text",
      "eventId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "responseStatus": 1,
      "responseBody": "Heute 20 % auf alles. Nur bis Ladenschluss.",
      "redeliveredFromId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "completedAt": "2026-09-15T10:32:00Z",
      "createdAt": "2026-09-15T10:32:00Z"
    }
  ]
}
GET/v1/webhooks/{id}/deliveries/{deliveryId}

Eine Zustellung mit Nutzlast

Die gesendete Nutzlast (bis 8 KB), die gesendeten Kopfzeilen (x-dowallet-signature, x-dowallet-event-id, x-dowallet-event) und die ganze Antwort deines Endpunkts. 30 Tage nach der Zustellung sind Nutzlast und Antwort entfernt.

Pfad-Parameter

  • iduuidPflicht
  • deliveryIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/webhooks/{id}/deliveries/{deliveryId}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "webhookId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "attempt": 1,
  "status": "active",
  "eventType": "text",
  "eventId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "responseStatus": 1,
  "responseBody": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "redeliveredFromId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "completedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z",
  "payload": {},
  "requestHeaders": {}
}
POST/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver

Zustellung erneut senden

Schickt dieselbe Nutzlast (gleiche eventId, dein Endpunkt kann doppelte erkennen) mit frischer Signatur noch einmal und startet eine neue Wiederholungskette. Test-Zustellungen und Zustellungen ohne gespeicherte Nutzlast sind 409.

Pfad-Parameter

  • iduuidPflicht
  • deliveryIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/webhooks/{id}/deliveries/{deliveryId}/redeliver" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "queued": true,
  "jobId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "eventId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "type": "text"
}
POST/v1/webhooks/{id}/rotate-secret

Signatur-Secret rotieren

Neues Secret, einmal im Klartext. Das alte signiert noch overlapHours (0 bis 72, Standard 24) als zweites v1= im Header x-dowallet-signature mit, damit dein Endpunkt ohne Lücke wechselt.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • overlapHoursintegeroptional

    0 bis 72

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/webhooks/{id}/rotate-secret" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "overlapHours": 24
}'
Antwort200
{
  "secret": "text",
  "previousValidUntil": "2026-09-15T10:32:00Z"
}
PATCH/v1/webhooks/{id}

Webhook ändern

URL, Ereignisse oder Aktiv-Status ändern. Scheitern zehn Ereignisse in Folge auch nach allen Wiederholungen, schaltet doWallet den Webhook ab; isActive: true nimmt ihn wieder auf und setzt den Zähler zurück. Org-Admin.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • urlurioptional
  • eventTypesstring[]optional

    1–∞ Einträge

  • isActivebooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/webhooks/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "url": "https://example.de/hook",
  "eventTypes": [
    "pass.redeemed"
  ],
  "isActive": true
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "url": "https://example.de/hook",
  "eventTypes": [
    "pass.redeemed"
  ],
  "isActive": true,
  "lastDeliveryAt": "2026-09-15T10:32:00Z",
  "lastDeliveryStatus": 1,
  "failedDeliveriesInARow": 1,
  "createdAt": "2026-09-15T10:32:00Z",
  "disabledAt": "2026-09-15T10:32:00Z"
}
DELETE/v1/webhooks/{id}

Webhook löschen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/webhooks/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
GET/v1/workspaces/{workspaceId}/inbound-endpoints

Empfangs-URLs auflisten

Empfangs-URLs des Workspace (ohne widerrufene), neueste zuerst, mit dem Zeitpunkt der letzten gültig signierten Meldung. Das Secret steht nie in dieser Liste. Org-Admin.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/inbound-endpoints" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "kind": "pos",
      "url": "https://example.de/hook",
      "lastUsedAt": "2026-09-15T10:32:00Z",
      "createdAt": "2026-09-15T10:32:00Z"
    }
  ]
}
POST/v1/workspaces/{workspaceId}/inbound-endpoints

Empfangs-URL anlegen

Legt eine Empfangs-URL für eine Kasse, ein Clearing-, Ticketing- oder Shop-System an (kind: pos, clearing, ticketing, shop, other). Die Antwort enthält das Signatur-Secret genau einmal. Höchstens 20 je Workspace. Org-Admin; nicht im Free-Plan.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–80 Zeichen

  • kind"pos" | "clearing" | "ticketing" | "shop" | "other"optional

Antworten

  • 201Angelegt
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/inbound-endpoints" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "kind": "pos"
}'
Antwort201
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "kind": "pos",
  "url": "https://example.de/hook",
  "lastUsedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z",
  "secret": "text"
}
POST/v1/inbound-endpoints/{id}/rotate

Secret einer Empfangs-URL erneuern

Erzeugt ein neues Signatur-Secret und gibt es genau einmal zurück. Das alte Secret gilt ab sofort nicht mehr: Meldungen damit bekommen 401, bis das sendende System das neue Secret nutzt. Die URL bleibt gleich. Org-Admin.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/inbound-endpoints/{id}/rotate" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "kind": "pos",
  "url": "https://example.de/hook",
  "lastUsedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z",
  "secret": "text"
}
DELETE/v1/inbound-endpoints/{id}

Empfangs-URL widerrufen

Sofort wirksam: Meldungen an diese URL bekommen ab jetzt 404. Bereits gemeldete Nutzungen bleiben erhalten. Org-Admin.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/inbound-endpoints/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/webhooks/incoming/{webhookId}

Nutzung von Kasse, Clearing, Ticketing oder Shop melden

Ohne Token, signiert: X-DoWallet-Signature: t=<unix>,v1=<hex(hmac_sha256(secret, t + "." + body))> über den Body genau so, wie er gesendet wird (formatiertes JSON ist erlaubt); t höchstens 5 Minuten alt. :webhookId ist die ID einer Empfangs-URL (POST /v1/workspaces/{workspaceId}/inbound-endpoints) oder übergangsweise eines ausgehenden Webhooks; ein nach Zustellfehlern abgeschalteter Webhook nimmt weiter an. Body { "type": "redemption", "passId"?, "payload": { "serial"? | "code"?, "redeemedAt"?, "amountCents"?, "locationName"?, "locationRef"?, "kind"?, "externalId"? } }. Typen redemption, redemptionLogged, conversion, purchase und pos.checkin (Einlass) werden eine Nutzung; weitere pos.* werden als Ereignis gespeichert. Antworten: 200 { accepted: true }, auch für eine schon gemeldete externalId (duplicate: true); 409 already_redeemed, limit_reached, pass_voided oder pass_expired mit details.lastRedemptionAt, wenn die Einlöse-Regel der Vorlage die Nutzung ablehnt; 422 ohne passenden Pass; 401 bei falscher Signatur; 404 für eine unbekannte oder widerrufene URL. Ratenklasse: 1.200 Aufrufe je Minute und URL, höchstens 3.000 je Minute und IP über alle URLs.

Pfad-Parameter

  • webhookIdstringPflicht

Antworten

  • 200OK
  • 400Ungültige Anfrage
  • 401Nicht angemeldet
  • 404Nicht gefunden
  • 409Konflikt
  • 413Zu groß
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/webhooks/incoming/{webhookId}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "accepted": true,
  "duplicate": true
}

Pässe

Pässe ausstellen (einzeln und gebündelt), lesen, Attribute und Gültigkeit ändern, entwerten, personenbezogene Daten löschen.

POST/v1/passes/{id}/push

Mitteilung an einen Pass senden

Hängt message (bis 80 Zeichen, sonst „Dein Pass wurde aktualisiert“) an die Mitteilungen des Passes und schickt einen Apple-Push an seine Geräte. Bei Google-Pässen geht dieselbe Mitteilung an Google Wallet (google.jobId, höchstens 3 Benachrichtigungen je Pass in 24 Stunden). Für viele Pässe eine Kampagne verwenden. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • reasonstringoptional

    1–80 Zeichen

  • messagestringoptional

    1–80 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/passes/{id}/push" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "manual",
  "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
}'
Antwort200
{
  "enqueued": true,
  "jobId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "mode": "instant",
  "delivered": 1,
  "apple": {
    "mode": "instant",
    "delivered": 1,
    "failed": 1,
    "invalidated": 1,
    "reasons": {}
  },
  "google": {
    "enqueued": true,
    "jobId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "mode": "instant",
    "classStatus": 1,
    "objectStatus": 1,
    "message": "sent",
    "error": {
      "step": "text",
      "status": 1
    }
  }
}
POST/v1/google-wallet/sync/{passId}

Google-Wallet-Objekt synchronisieren

Erzwingt einen erneuten Abgleich des Google-Objekts mit dem aktuellen Pass-Inhalt.

Pfad-Parameter

  • passIduuidPflicht

Request-Body (JSON)

  • asyncbooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/google-wallet/sync/{passId}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "async": true
}'
Antwort200
{
  "mode": "sync",
  "jobId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "classStatus": 1,
  "objectStatus": 1
}
GET/v1/workspaces/{workspaceId}/passes

Pässe auflisten

Neueste zuerst, seitenweise über cursor (aus pagination.nextCursor). q sucht die Seriennummer oder den Code (exakt oder Anfang), die Pass-ID und die eigene Kennung (externalId) exakt, den exakten Wert eines Attributs (ab der Rolle org_admin und für Kundensupport jeder Schlüssel, sonst nur die in den Vorlagen deklarierten Schlüssel ohne Personenbezug) und ab der Rolle org_admin sowie für Kundensupport die E-Mail des Kontakts (Anfang). status: active (gültig: nicht entwertet, nicht abgelaufen), expired (abgelaufen, nicht entwertet), voided (entwertet: vom Aussteller, durch die Einlöse-Regel oder als Dublette), removed (vom Inhaber aus dem Wallet entfernt, nicht entwertet), deactivated (Datenbank-Status deactivated: entwertet durch den Aussteller oder entfernt). Mit counts=1 trägt die erste Seite counts je Zustand für dieselben Filter ohne status, dazu notInWallet (gültig, eingeladen, in keiner Wallet) und remindable (davon fällig für „Erinnern“). templateId zeigt nur Pässe einer Vorlage. isTest, isDemo, isInternal (true/1 oder false/0) filtern nach der Markierung als Test-Pass, Demo-Pass oder eigenes Gerät; testDevice=1 zeigt Test-Pässe und eigene Geräte zusammen (Handy-Test), testDevice=0 alle anderen. Die Filter gelten auch für counts. audienceId zeigt nur Pässe, die diese gespeicherte Zielgruppe des Arbeitsbereichs gerade trifft (dieselbe Regel wie ihre Zählung); eine fremde oder unbekannte Zielgruppe ist ein 422 auf audienceId, eine Regel, die sich nicht übersetzen lässt, ebenso. E-Mail und personenbezogene Attribute (customer…, email, name, phone …) sind unter der Rolle org_admin maskiert, z. B. k•••@verve.com; Kundensupport sieht sie ungekürzt. Ein API-Token handelt mit der Rolle seines Erstellers (Org-Owner) und bekommt die Werte ungekürzt.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • qstringoptional
  • templateIduuidoptional
  • statusactive | expired | voided | removed | deactivatedoptional
  • customerIduuidoptional
  • utmSourcestringoptional
  • audienceIduuidoptional
  • isTest0 | 1 | true | falseoptional
  • isDemo0 | 1 | true | falseoptional
  • isInternal0 | 1 | true | falseoptional
  • testDevice0 | 1 | true | falseoptional
  • cursorstringoptional
  • counts0 | 1 | true | falseoptional
  • limitintegeroptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/passes?q=sommer&templateId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01&status=active" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "serial": "ABC123456",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "templateName": "Sommer-Aktion",
      "templateVersion": 1,
      "platform": "apple",
      "status": "active",
      "isTest": true,
      "label": "Sommer-Aktion",
      "isInternal": true,
      "isDemo": true,
      "code": "text",
      "codePending": true,
      "attributes": {},
      "utm": {
        "source": "text",
        "medium": "text",
        "campaign": "text",
        "term": "text",
        "content": "text"
      },
      "claimLinkId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "createdAt": "2026-09-15T10:32:00Z",
      "activatedAt": "2026-09-15T10:32:00Z",
      "deactivatedAt": "2026-09-15T10:32:00Z",
      "voidedAt": "2026-09-15T10:32:00Z",
      "redeemedAt": "2026-09-15T10:32:00Z",
      "validUntil": "2026-09-15T10:32:00Z",
      "redemptionCount": 1,
      "generation": 1,
      "previousTemplateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "expiredAt": "2026-09-15T10:32:00Z",
      "customerId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "customer": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "email": "kunde@example.de"
      },
      "externalId": "bon-4711",
      "invite": {
        "createdAt": "2026-09-15T10:32:00Z",
        "sentAt": "2026-09-15T10:32:00Z",
        "openedAt": "2026-09-15T10:32:00Z"
      }
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  },
  "counts": {
    "all": 1,
    "active": 1,
    "voided": 1,
    "expired": 1,
    "removed": 1,
    "inWallet": 1,
    "inWalletApple": 1,
    "inWalletGoogle": 1,
    "notInWallet": 1,
    "remindable": 1
  }
}
POST/v1/workspaces/{workspaceId}/passes

Pass ausstellen

Stellt einen Pass aus einer veröffentlichten Vorlage aus, z. B. ein Ticket pro Kauf. attributes füllt die Felder der Feldliste ({{attr.<key>}}), Pflichtfelder fehlen → 422 mit fields['attributes.<key>']. code legt den Barcode fest (druckbare Zeichen aus Latin-1, je Vorlage eindeutig, sonst 409 code_in_use); das geht nur, wenn die Barcode-Nachricht der veröffentlichten Vorlage {{code}} enthält, sonst 422 barcode_without_code. Ohne code kommt der Wert aus der Wertquelle der Vorlage, sonst die Seriennummer; code in der Antwort ist dieser Wert und steht im Barcode, wenn die Barcode-Nachricht {{code}} enthält. validUntil ist das Ablaufdatum dieses Passes. Die Antwort enthält den Apple-Download-Link (ohne Ablauf) und den Google-Speichern-Link. Header Idempotency-Key (24 h) macht Wiederholungen sicher. Token-Scope passes:issue; im Free-Plan gesperrt.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • templateIduuidPflicht
  • attributesobjectoptional
  • codestringoptional

    1–120 Zeichen

  • validUntildate-timeoptional
  • platform"apple" | "google" | "both"optional
  • customerobjectoptional
  • emailemailPflicht

    0–254 Zeichen

  • firstNamestringoptional

    1–80 Zeichen

  • lastNamestringoptional

    1–80 Zeichen

  • consenttruePflicht
  • utmobjectoptional
  • sourcestringoptional

    0–200 Zeichen

  • mediumstringoptional

    0–200 Zeichen

  • campaignstringoptional

    0–200 Zeichen

  • termstringoptional

    0–200 Zeichen

  • contentstringoptional

    0–200 Zeichen

  • isTestbooleanoptional

Antworten

  • 201Angelegt
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
  • 503Nicht verfügbar
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/passes" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "attributes": {},
  "code": "text",
  "validUntil": "2026-09-15T10:32:00Z",
  "platform": "both",
  "customer": {
    "email": "kunde@example.de",
    "firstName": "Sommer-Aktion",
    "lastName": "Sommer-Aktion",
    "consent": true
  },
  "utm": {
    "source": "text",
    "medium": "text",
    "campaign": "text",
    "term": "text",
    "content": "text"
  },
  "isTest": true
}'
Antwort201
{
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "serial": "ABC123456",
  "code": "text",
  "validUntil": "2026-09-15T10:32:00Z",
  "apple": {
    "downloadUrl": "https://example.de/hook"
  },
  "google": {
    "saveUrl": "https://example.de/hook"
  }
}
GET/v1/passes/{id}/generations

Pass-Verlauf lesen

Alle Generationen eines Passes: welche Vorlage und welche Version wann galten. Grundlage für Zielgruppen mit „Frühere Vorlage“.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/passes/{id}/generations" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "generation": 1,
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "templateName": "Sommer-Aktion",
      "templateVersion": 1,
      "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "campaignName": "Sommer-Aktion",
      "appliedAt": "2026-09-15T10:32:00Z"
    }
  ]
}
POST/v1/passes/{id}/deactivate

Pass entwerten

Setzt den Pass auf deactivated und entwertet ihn (voidedAt). Das Wallet zeigt ihn nach dem Push als ungültig; fügt der Inhaber ihn erneut hinzu, bleibt er entwertet, der Download-Link antwortet mit 410. Nicht umkehrbar. Ab der Rolle editor. 409, wenn der Pass schon entwertet ist.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • reasonstringoptional

    1–80 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/passes/{id}/deactivate" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "reason": "manual"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "status": "deactivated",
  "deactivatedAt": "2026-09-15T10:32:00Z",
  "voidedAt": "2026-09-15T10:32:00Z"
}
POST/v1/passes/{passId}/erase-personal-data

Personenbezogene Daten löschen

Entfernt Name, E-Mail, Telefon und verknüpfte Kontaktdaten des Passes (DSGVO Art. 17), auch an den anderen Pässen desselben Kontakts. Der Pass selbst bleibt gültig; das Wallet übernimmt die Änderung beim nächsten Abruf. Ab der Rolle org_admin.

Pfad-Parameter

  • passIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/passes/{passId}/erase-personal-data" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "ok": true,
  "customerErased": true,
  "passesScrubbed": 1
}
GET/v1/passes/{id}

Pass lesen

Ein Pass mit Status, Feldern, Code, Gültigkeit, Kontakt, Generationen, Mitteilungen, den letzten 50 Ereignissen und den Nutzungen. Treue-Buchungen im Verlauf (pass.loyalty_changed) tragen loyalty mit Art der Regel, Änderung, Stand danach und Ziel; wallets.firstAddedAt ist das erste Hinzufügen zu einem Wallet (null, solange der Pass nie in einem lag). Jede Rolle im Workspace des Passes; E-Mail und personenbezogene Attribute sind unter org_admin maskiert, Kundensupport sieht sie ungekürzt. access nennt, was die Rolle darf: canEdit (editor+), canErase (org_admin+), contactVisible, canPush (editor+ und Kundensupport, nur aktive Pässe), canResend (editor+ und Kundensupport). API-Token: Scope passes:read, passes:write oder passes:issue.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/passes/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "serial": "ABC123456",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateName": "Sommer-Aktion",
  "templateVersion": 1,
  "platform": "apple",
  "status": "active",
  "isTest": true,
  "label": "Sommer-Aktion",
  "isInternal": true,
  "isDemo": true,
  "code": "text",
  "codePending": true,
  "attributes": {},
  "utm": {
    "source": "text",
    "medium": "text",
    "campaign": "text",
    "term": "text",
    "content": "text"
  },
  "claimLinkId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "activatedAt": "2026-09-15T10:32:00Z",
  "deactivatedAt": "2026-09-15T10:32:00Z",
  "voidedAt": "2026-09-15T10:32:00Z",
  "redeemedAt": "2026-09-15T10:32:00Z",
  "validUntil": "2026-09-15T10:32:00Z",
  "redemptionCount": 1,
  "generation": 1,
  "previousTemplateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "expiredAt": "2026-09-15T10:32:00Z",
  "customerId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "customer": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de"
  },
  "externalId": "bon-4711",
  "invite": {
    "createdAt": "2026-09-15T10:32:00Z",
    "sentAt": "2026-09-15T10:32:00Z",
    "openedAt": "2026-09-15T10:32:00Z"
  },
  "templateValidUntil": "text",
  "generations": [
    {
      "generation": 1,
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "templateName": "Sommer-Aktion",
      "templateVersion": 1,
      "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "campaignName": "Sommer-Aktion",
      "appliedAt": "2026-09-15T10:32:00Z"
    }
  ],
  "messages": [
    {
      "text": "Heute 20 % auf alles. Nur bis Ladenschluss.",
      "at": "text",
      "source": "text"
    }
  ],
  "events": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "type": "text",
      "occurredAt": "2026-09-15T10:32:00Z",
      "source": "text"
    }
  ],
  "redemptions": {
    "count": 1,
    "last": {
      "at": "2026-09-15T10:32:00Z",
      "kind": "redemption",
      "locationName": "Sommer-Aktion"
    }
  },
  "wallets": {
    "appleDevices": 1,
    "google": true,
    "firstAddedAt": "2026-09-15T10:32:00Z",
    "googleMessagesLeft24h": 1
  },
  "access": {
    "role": "super_admin",
    "canEdit": true,
    "canErase": true,
    "contactVisible": true,
    "canPush": true,
    "canResend": true
  }
}
PATCH/v1/passes/{id}

Pass kennzeichnen

Setzt die Bezeichnung (label, z. B. „Karim iPhone“) und die Markierung als eigenes Gerät (isInternal). Andere Felder lehnt die Route mit 422 ab; Attribute und „gültig bis“ ändert PATCH /v1/passes/{id}/attributes, den Inhalt PATCH /v1/passes/{id}/content. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • labelstring | nulloptional
  • isInternalbooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/passes/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "label": "Sommer-Aktion",
  "isInternal": true
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "label": "Sommer-Aktion",
  "isInternal": true
}
PATCH/v1/passes/{id}/content

Inhalt eines Test-Passes ändern

Überschreibt Feldwerte (fieldValues) oder Labels (fieldLabels) eines Test- oder Demo-Passes (Merge; reset: true setzt auf die Vorlage zurück), optional mit pushMessage als Mitteilung. Für Kundenpässe antwortet die Route mit 422: deren Felder ändert PATCH /v1/passes/{id}/attributes, alle Pässe einer Vorlage eine Kampagne. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • fieldValuesobjectoptional
  • fieldLabelsobjectoptional
  • pushMessagestringoptional

    1–160 Zeichen

  • resetbooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/passes/{id}/content" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "fieldValues": {},
  "fieldLabels": {},
  "pushMessage": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "reset": false
}'
Antwort200
{
  "updated": true,
  "enqueued": true,
  "walletDocumentOverride": {}
}
POST/v1/workspaces/{workspaceId}/passes/bulk

Pässe gebündelt ausstellen (bis 100)

Wie POST /v1/workspaces/{workspaceId}/passes, für bis zu 100 Einträge in einem Aufruf. Jeder Eintrag wird für sich ausgestellt: die Antwort nennt je index entweder den Pass mit Links oder den Fehler (code, detail). Ein fehlerhafter Eintrag hält die anderen nicht auf. Synchron; Token-Scope passes:issue.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • itemsobject[]Pflicht

    1–100 Einträge

  • templateIduuidPflicht
  • attributesobjectoptional
  • codestringoptional

    1–120 Zeichen

  • validUntildate-timeoptional
  • platform"apple" | "google" | "both"optional
  • customerobjectoptional
  • emailemailPflicht

    0–254 Zeichen

  • firstNamestringoptional

    1–80 Zeichen

  • lastNamestringoptional

    1–80 Zeichen

  • consenttruePflicht
  • utmobjectoptional
  • sourcestringoptional

    0–200 Zeichen

  • mediumstringoptional

    0–200 Zeichen

  • campaignstringoptional

    0–200 Zeichen

  • termstringoptional

    0–200 Zeichen

  • contentstringoptional

    0–200 Zeichen

  • isTestbooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
  • 503Nicht verfügbar
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/passes/bulk" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
    }
  ]
}'
Antwort200
{
  "results": [
    {
      "index": 1,
      "ok": true,
      "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "serial": "ABC123456",
      "code": "text",
      "validUntil": "2026-09-15T10:32:00Z",
      "apple": {
        "downloadUrl": "https://example.de/hook"
      },
      "google": {
        "saveUrl": "https://example.de/hook"
      }
    }
  ]
}
PATCH/v1/passes/{id}/attributes

Attribute und Gültigkeit eines Passes ändern

Merge: set schreibt Felder (null entfernt), unset entfernt Felder; Pflichtfelder der Feldliste bleiben gefüllt. validUntil setzt das Ablaufdatum dieses Passes (null = Datum der Vorlage); ein Datum in der Zukunft macht einen abgelaufenen Pass wieder gültig. Die Geräte holen den neuen Inhalt; mit notify: "push" erscheint message als Mitteilung. Token-Scope passes:issue oder passes:write.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • setobjectoptional
  • unsetstring[]optional

    0–40 Einträge

  • validUntildate-time | nulloptional
  • notify"silent" | "push"optional
  • messagestringoptional

    1–180 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/passes/{id}/attributes" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "set": {},
  "unset": [
    "text"
  ],
  "validUntil": "2026-09-15T10:32:00Z",
  "notify": "silent",
  "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
}'
Antwort200
{
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "attributes": {},
  "validUntil": "2026-09-15T10:32:00Z",
  "contentUpdatedAt": "2026-09-15T10:32:00Z"
}
POST/v1/workspaces/{workspaceId}/passes/attributes/bulk

Attribute vieler Pässe ändern (bis 1.000)

Setzt Attribute für bis zu 1.000 Pässe des Workspace in einem Aufruf, etwa Region, Tarif oder Charge aus dem eigenen System. Je Eintrag serial und wie bei PATCH /v1/passes/{id}/attributes set (null entfernt) und unset; Pflichtfelder der Feldliste bleiben gefüllt, Kontaktfelder (customer…) gehören nicht in die Attribute. Alles oder nichts: passt ein Eintrag nicht zur Feldliste seiner Vorlage, antwortet die API 422 mit fields['items.<i>.attributes.<key>'] und ändert keinen Pass. Unbekannte Seriennummern stehen in notFound und halten die anderen nicht auf. Geänderte Pässe laden still nach (keine Mitteilung auf dem Sperrbildschirm); unchanged zählt Pässe, bei denen sich nichts ändert. Danach lassen sich die Attribute in Zielgruppen filtern (attributes.<key>). Header Idempotency-Key (24 h) macht Wiederholungen sicher. Token-Scope passes:write oder passes:issue; im Free-Plan gesperrt.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • itemsobject[]Pflicht

    1–1000 Einträge

  • serialstringPflicht

    1–200 Zeichen

  • setobjectoptional
  • unsetstring[]optional

    0–40 Einträge

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/passes/attributes/bulk" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "serial": "ABC123456"
    }
  ]
}'
Antwort200
{
  "updated": 1,
  "unchanged": 1,
  "notFound": [
    "text"
  ]
}
GET/v1/passes/{id}/loyalty

Treue-Verlauf eines Passes

Jede Buchung, neueste zuerst: delta, Stand danach balanceAfter, reason, source (scan, api, inbound, csv, manual, demo, system), kind (earn vergeben, redeem eingelöst, correct korrigiert, welcome Startstempel), occurredAt (Zeitpunkt der Nutzung) und createdAt. Dazu der aktuelle Stand balance, tier, rewardAvailable (eine offene Prämie), goal, stampsLeft und rewards (open: offene Prämien, älteste zuerst; recent: die letzten fünf eingelösten oder verfallenen). Cursor über pagination.nextCursor, limit 1 bis 200 (Standard 50). Jede Rolle im Workspace; Token-Scope passes:read oder passes:write.

Pfad-Parameter

  • iduuidPflicht

Query-Parameter

  • cursorstringoptional
  • limitintegeroptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/passes/{id}/loyalty?cursor=text&limit=50" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "balance": 1,
  "tier": "text",
  "rewardAvailable": true,
  "goal": 1,
  "stampsLeft": 1,
  "rewards": {
    "open": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "status": "earned",
        "label": "Sommer-Aktion",
        "rewardType": "item",
        "rewardValue": 1,
        "goal": 1,
        "earnedAt": "2026-09-15T10:32:00Z",
        "redeemedAt": "2026-09-15T10:32:00Z",
        "redeemedSource": "scan",
        "voidedAt": "2026-09-15T10:32:00Z"
      }
    ],
    "recent": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "status": "earned",
        "label": "Sommer-Aktion",
        "rewardType": "item",
        "rewardValue": 1,
        "goal": 1,
        "earnedAt": "2026-09-15T10:32:00Z",
        "redeemedAt": "2026-09-15T10:32:00Z",
        "redeemedSource": "scan",
        "voidedAt": "2026-09-15T10:32:00Z"
      }
    ]
  },
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "delta": 1,
      "balanceAfter": 1,
      "reason": "text",
      "source": "scan",
      "kind": "earn",
      "occurredAt": "2026-09-15T10:32:00Z",
      "createdAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/passes/{id}/loyalty

Stempel oder Punkte korrigieren

delta (ganze Zahl, ±100.000, nicht 0) bucht auf den Stand des Passes nach der Treue-Regel seiner Vorlage; reason (höchstens 80 Zeichen) steht im Verlauf und ist bei einem Minus Pflicht (422). reward, welcome und demo sind reserviert. Aus der App ist das eine Korrektur: keine Nutzung, zählt nicht für das Tageslimit und nicht als vergebener Stempel. Für einen Stempel als Nutzung gibt es POST /v1/passes/{id}/loyalty/stamp, zum Einlösen POST /v1/passes/{id}/loyalty/redeem. Antwort: Stand danach balance, Stufe tier und rewardAvailable (eine offene Prämie). Erreicht der Stand das Ziel, entsteht eine offene Prämie („Prämie bereit“); fällt er unter das Ziel einer offenen Prämie, verfällt sie. Webhook pass.loyalty_changed. Ohne Treue-Regel 422 loyalty_rule_missing; ein Stand unter 0 409 insufficient_points; ein entwerteter oder abgelaufener Pass 409 pass_voided bzw. pass_expired. Ohne das Modul Treue 403 module_disabled. Editor-Rolle oder höher. Aus einer Browser-Sitzung auch im Free-Plan (Quelle manual; der Test-Stempel aus /demo mit demo: true, nur ein Plus, Quelle demo, zählt nie als echte Buchung); mit API-Token (Scope passes:write) nur im bezahlten Plan, sonst 402 (Quelle api; ein Plus zählt dort als vergebener Stempel, mit Pause und Tageslimit 409 loyalty_paused bzw. loyalty_daily_cap). Header Idempotency-Key (24 h) macht Wiederholungen sicher. 300 Aufrufe je Minute und Person oder Token.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • deltaintegerPflicht

    -100000 bis 100000

  • reasonstringoptional

    1–80 Zeichen

  • demobooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/passes/{id}/loyalty" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "delta": 1,
  "reason": "text",
  "demo": true
}'
Antwort200
{
  "balance": 1,
  "tier": "text",
  "rewardAvailable": true
}
POST/v1/passes/{id}/loyalty/stamp

Stempel geben (Nutzung)

„+1 Stempel“ aus der App (Pass-Detail, Mitglieder): eine Nutzung der Art stamp wie am Scanner, sie steht in den Nutzungen, startet Automatisierungen mit dem Auslöser „genutzt“ und zählt für das Tageslimit des Programms. count (1 bis 10, Standard 1) bucht mehrere Stempel als eine Nutzung; locationId optional. Nur Stempelkarten (sonst 422). Pausiert 409 loyalty_paused, Tageslimit erreicht 409 loyalty_daily_cap („Heute schon gestempelt“), ein entwerteter oder abgelaufener Pass 409. Ohne das Modul Treue 403 module_disabled. Antwort: Stand, Ziel, stampsLeft, offene und letzte Prämien und die eventId der Nutzung. Nur mit Anmeldung im Browser (API-Tokens melden Nutzungen über die Sammel-API), Editor-Rolle oder höher, jeder Plan. Audit pass.loyalty.stamp.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • countintegeroptional

    1 bis 10

  • locationIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/passes/{id}/loyalty/stamp" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "count": 1
}'
Antwort200
{
  "balance": 1,
  "tier": "text",
  "rewardAvailable": true,
  "goal": 1,
  "stampsLeft": 1,
  "rewards": {
    "open": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "status": "earned",
        "label": "Sommer-Aktion",
        "rewardType": "item",
        "rewardValue": 1,
        "goal": 1,
        "earnedAt": "2026-09-15T10:32:00Z",
        "redeemedAt": "2026-09-15T10:32:00Z",
        "redeemedSource": "scan",
        "voidedAt": "2026-09-15T10:32:00Z"
      }
    ],
    "recent": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "status": "earned",
        "label": "Sommer-Aktion",
        "rewardType": "item",
        "rewardValue": 1,
        "goal": 1,
        "earnedAt": "2026-09-15T10:32:00Z",
        "redeemedAt": "2026-09-15T10:32:00Z",
        "redeemedSource": "scan",
        "voidedAt": "2026-09-15T10:32:00Z"
      }
    ]
  },
  "eventId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "redeemed": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "status": "earned",
    "label": "Sommer-Aktion",
    "rewardType": "item",
    "rewardValue": 1,
    "goal": 1,
    "earnedAt": "2026-09-15T10:32:00Z",
    "redeemedAt": "2026-09-15T10:32:00Z",
    "redeemedSource": "scan",
    "voidedAt": "2026-09-15T10:32:00Z"
  }
}
POST/v1/passes/{id}/loyalty/earn

Punkte buchen (Nutzung)

„Punkte buchen“ aus der App (Pass-Detail, Mitglieder) auf einer Punktekarte: eine Nutzung der Art points, sie steht in den Nutzungen und startet Automatisierungen mit dem Auslöser „genutzt“. amountCents (Einkaufsbetrag in Cent) bucht earnPerEuro Punkte je Euro, abgerundet; points (1 bis 100.000) bucht genau diese Punkte und gewinnt, wenn beides kommt (der Betrag steht dann nur an der Nutzung). Eins von beiden ist Pflicht. Nur Punktekarten (eine Stempelkarte 422, dafür POST /v1/passes/{id}/loyalty/stamp). Ohne Punkte je Euro an der Regel und ohne points 422; ein Betrag, der 0 Punkte ergibt, 422. Ein entwerteter oder abgelaufener Pass 409. Ohne das Modul Treue 403 module_disabled. Antwort: Stand, Stufe und die eventId der Nutzung. Nur mit Anmeldung im Browser (API-Tokens melden Nutzungen über die Sammel-API), Editor-Rolle oder höher, jeder Plan. Audit pass.loyalty.earn.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • pointsintegeroptional

    1 bis 100000

  • amountCentsintegeroptional

    1 bis 100000000

  • locationIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/passes/{id}/loyalty/earn" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "points": 1,
  "amountCents": 1250,
  "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}'
Antwort200
{
  "balance": 1,
  "tier": "text",
  "rewardAvailable": true,
  "goal": 1,
  "stampsLeft": 1,
  "rewards": {
    "open": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "status": "earned",
        "label": "Sommer-Aktion",
        "rewardType": "item",
        "rewardValue": 1,
        "goal": 1,
        "earnedAt": "2026-09-15T10:32:00Z",
        "redeemedAt": "2026-09-15T10:32:00Z",
        "redeemedSource": "scan",
        "voidedAt": "2026-09-15T10:32:00Z"
      }
    ],
    "recent": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "status": "earned",
        "label": "Sommer-Aktion",
        "rewardType": "item",
        "rewardValue": 1,
        "goal": 1,
        "earnedAt": "2026-09-15T10:32:00Z",
        "redeemedAt": "2026-09-15T10:32:00Z",
        "redeemedSource": "scan",
        "voidedAt": "2026-09-15T10:32:00Z"
      }
    ]
  },
  "eventId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "redeemed": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "status": "earned",
    "label": "Sommer-Aktion",
    "rewardType": "item",
    "rewardValue": 1,
    "goal": 1,
    "earnedAt": "2026-09-15T10:32:00Z",
    "redeemedAt": "2026-09-15T10:32:00Z",
    "redeemedSource": "scan",
    "voidedAt": "2026-09-15T10:32:00Z"
  }
}
POST/v1/passes/{id}/loyalty/redeem

Prämie einlösen

Löst die offene Prämie rewardId ein, ohne sie die älteste offene. Eine Nutzung der Art redemption mit reason: "reward" wie am Scanner. Gebucht wird nach den Bedingungen, mit denen die Prämie erreicht wurde: carry minus ihr Ziel (der Überhang bleibt, reicht er wieder, ist sofort die nächste Prämie offen), reset minus den ganzen Stand. Geht auch, während das Programm pausiert ist. Keine offene Prämie 409 reward_not_available; ein entwerteter oder abgelaufener Pass 409. Ohne das Modul Treue 403 module_disabled. Antwort: Stand, Ziel, offene und letzte Prämien, redeemed und die eventId der Nutzung. Editor-Rolle oder höher; Sitzung (jeder Plan, Quelle manual) oder API-Token mit passes:write (nur im bezahlten Plan, sonst 402; Quelle api). Header Idempotency-Key (24 h). Audit pass.loyalty.redeem.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • rewardIduuidoptional
  • locationIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/passes/{id}/loyalty/redeem" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Antwort200
{
  "balance": 1,
  "tier": "text",
  "rewardAvailable": true,
  "goal": 1,
  "stampsLeft": 1,
  "rewards": {
    "open": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "status": "earned",
        "label": "Sommer-Aktion",
        "rewardType": "item",
        "rewardValue": 1,
        "goal": 1,
        "earnedAt": "2026-09-15T10:32:00Z",
        "redeemedAt": "2026-09-15T10:32:00Z",
        "redeemedSource": "scan",
        "voidedAt": "2026-09-15T10:32:00Z"
      }
    ],
    "recent": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "status": "earned",
        "label": "Sommer-Aktion",
        "rewardType": "item",
        "rewardValue": 1,
        "goal": 1,
        "earnedAt": "2026-09-15T10:32:00Z",
        "redeemedAt": "2026-09-15T10:32:00Z",
        "redeemedSource": "scan",
        "voidedAt": "2026-09-15T10:32:00Z"
      }
    ]
  },
  "eventId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "redeemed": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "status": "earned",
    "label": "Sommer-Aktion",
    "rewardType": "item",
    "rewardValue": 1,
    "goal": 1,
    "earnedAt": "2026-09-15T10:32:00Z",
    "redeemedAt": "2026-09-15T10:32:00Z",
    "redeemedSource": "scan",
    "voidedAt": "2026-09-15T10:32:00Z"
  }
}
GET/v1/workspaces/{workspaceId}/loyalty/members

Treue-Mitglieder

Echte, aktive Pässe der Programme (oder eines mit program bzw. templateId), mit Stand, Ziel, stampsLeft, Stufe, ältester offener Prämie, letztem Stempel (lastEarnAt), letzter Buchung und Inhaber. segment: near_goal, reward_ready, unclaimed, inactive, new, no_stamp (dieselben Regeln wie die Übersicht). q: Seriennummer, Code oder eigene Kennung, mit Kontaktsicht auch E-Mail und Name. sort: near_goal (am nächsten an der Prämie zuerst, Standard), recent (letzter Stempel), joined (neueste zuerst). Name und E-Mail des Inhabers sieht ungekürzt nur, wer mindestens Org-Admin oder Kundensupport ist, sonst maskiert („k•••@verve.com“). Cursor über pagination.nextCursor, limit 1 bis 200 (Standard 50), total zählt den ganzen Filter. Jede Rolle im Workspace; Token-Scope passes:read. Ohne das Modul Treue 403 module_disabled.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • segmentnear_goal | reward_ready | unclaimed | inactive | new | no_stampoptional
  • programuuidoptional
  • templateIduuidoptional
  • qstringoptional
  • sortnear_goal | recent | joinedoptional
  • cursorstringoptional
  • limitintegeroptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/loyalty/members?segment=near_goal&program=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01&templateId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "serial": "ABC123456",
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "programName": "Sommer-Aktion",
      "kind": "stamps",
      "balance": 1,
      "goal": 1,
      "stampsLeft": 1,
      "tier": "text",
      "openRewards": 1,
      "openReward": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "label": "Sommer-Aktion",
        "rewardType": "text",
        "rewardValue": 1,
        "earnedAt": "2026-09-15T10:32:00Z"
      },
      "lastEarnAt": "2026-09-15T10:32:00Z",
      "lastBookingAt": "2026-09-15T10:32:00Z",
      "joinedAt": "2026-09-15T10:32:00Z",
      "platform": "apple",
      "externalId": "bon-4711",
      "holder": {
        "customerId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "name": "Sommer-Aktion",
        "email": "kunde@example.de"
      }
    }
  ],
  "total": 1,
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
GET/v1/workspaces/{workspaceId}/loyalty/members.csv

Treue-Mitglieder als CSV

Dieselben Filter wie GET …/loyalty/members (segment, program, q, sort), alle Zeilen (höchstens 100.000) als CSV mit Semikolon, UTF-8. Name und E-Mail nur für Org-Admins und den Kundensupport und nur von Kontakten mit aktiver Einwilligung. Editor-Rolle oder höher; Token-Scope passes:read. In einer Übernahme nur zum Lesen 403 impersonation_read_only wie bei den anderen Kontakt-Exporten. 30 Exporte je Minute und Person oder Token. Audit loyalty.members_export. Ohne das Modul Treue 403 module_disabled.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • segmentnear_goal | reward_ready | unclaimed | inactive | new | no_stampoptional
  • programuuidoptional
  • templateIduuidoptional
  • qstringoptional
  • sortnear_goal | recent | joinedoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/loyalty/members.csv?segment=near_goal&program=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01&templateId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
"text"
POST/v1/workspaces/{workspaceId}/passes/import/preview

Pass-Import prüfen (Vorschau)

Erster Schritt eines Imports. multipart/form-data mit file (CSV bis 10 MB, höchstens 20.000 Zeilen, Trennzeichen und Zeichensatz werden erkannt) und templateId (veröffentlichte Vorlage) lädt die Datei hoch und schlägt je Spalte ein Ziel vor; application/json { uploadId, templateId, mapping } prüft dieselbe Datei mit einer geänderten Zuordnung. Ziele: externalId (eigene Kennung, 1–120 Zeichen; ein Pass der Vorlage mit dieser Kennung wird aktualisiert), email, firstName, lastName, validUntil (TT.MM.JJJJ oder ISO in der Zeitzone des Arbeitsbereichs, ein Datum ohne Uhrzeit gilt bis 23:59:59), code (Wert im Barcode, druckbares Latin-1, nur für neue Pässe) und attr.<key> je Feld der Feldliste. Die Antwort nennt uploadId, Kopfzeile, Zuordnung, die ersten 20 Zeilen, wie der Import sie liest (action create oder update), die Fehlerzeilen (doppelte Kennung, ungültige Werte, barcode_without_code, vergebener Code, Pflichtfeld fehlt) und die Zahlen. Es entsteht noch kein Pass. Die Datei wartet 24 Stunden. Ab der Rolle Bearbeiter, Token-Scope passes:issue; im Free-Plan gesperrt.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 413Zu groß
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
  • 503Nicht verfügbar
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/passes/import/preview" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "uploadId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "fileName": "Sommer-Aktion",
  "rowCount": 1,
  "delimiter": ",",
  "headers": [
    "text"
  ],
  "samples": [
    "text"
  ],
  "mapping": [
    "text"
  ],
  "targets": [
    {
      "target": "text",
      "label": "Sommer-Aktion",
      "required": true,
      "type": "text"
    }
  ],
  "missingRequired": [
    "text"
  ],
  "rows": [
    {
      "line": 1,
      "action": "create",
      "externalId": "bon-4711",
      "email": "kunde@example.de",
      "firstName": "Sommer-Aktion",
      "lastName": "Sommer-Aktion",
      "validUntil": "2026-09-15T10:32:00Z",
      "code": "text",
      "attributes": {},
      "error": {
        "line": 1,
        "code": "text",
        "field": "text",
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    }
  ],
  "errors": [
    {
      "line": 1,
      "code": "text",
      "field": "text",
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
    }
  ],
  "errorCount": 1,
  "creates": 1,
  "updates": 1,
  "invitable": 1,
  "barcodeCarriesCode": true,
  "externalIdOnPass": true
}
POST/v1/workspaces/{workspaceId}/passes/import

Pässe importieren

Startet den Import einer Datei aus der Vorschau (uploadId) mit der geprüften Zuordnung und antwortet 202 mit jobId; den Stand liest GET …/passes/import/{jobId}. Der Import läuft in Blöcken zu 100 Zeilen, jede Zeile für sich: eine Fehlerzeile hält die anderen nicht auf. Ein Pass der Vorlage mit derselben externalId wird still aktualisiert (Felder, gültig bis, Kontakt), Zeilen ohne externalId legen jedes Mal neue Pässe an. sendInvites schickt jedem neu angelegten Pass mit E-Mail eine persönliche Einladung (Link zur Seite mit Apple- und Google-Knopf); aktualisierte Pässe bekommen keine neue Mail. Einladungen nur mit legalBasisConfirmed: true, sonst 422 legal_basis_required. Das Monatskontingent wird vor jedem Block geprüft; ist es erschöpft, endet der Import mit failed, fertige Blöcke bleiben. Ein Import je Vorlage zur selben Zeit (sonst 409). Ab der Rolle Bearbeiter, Token-Scope passes:issue; im Free-Plan gesperrt.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • uploadIduuidPflicht
  • templateIduuidPflicht
  • mappingstring | null[]Pflicht

    0–100 Einträge

  • sendInvitesbooleanoptional
  • legalBasisConfirmedbooleanoptional

Antworten

  • 202Angenommen
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 413Zu groß
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
  • 503Nicht verfügbar
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/passes/import" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "uploadId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "mapping": [
    "text"
  ],
  "sendInvites": false,
  "legalBasisConfirmed": false
}'
Antwort202
{
  "jobId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}
GET/v1/workspaces/{workspaceId}/passes/import/{jobId}

Pass-Import lesen

Stand eines Imports: status queued, running, done oder failed; created, updated (still aktualisiert), unchanged, failed und invited (Einladungen in der Queue) wachsen je Block. errors nennt die ersten 200 Fehlerzeilen mit Zeilennummer, detail den Grund, wenn der ganze Import scheiterte. Ab der Rolle Bearbeiter, Token-Scope passes:issue.

Pfad-Parameter

  • workspaceIduuidPflicht
  • jobIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/passes/import/{jobId}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "status": "queued",
  "fileName": "Sommer-Aktion",
  "sendInvites": true,
  "total": 1,
  "created": 1,
  "updated": 1,
  "unchanged": 1,
  "failed": 1,
  "invited": 1,
  "errors": [
    {
      "line": 1,
      "code": "text",
      "field": "text",
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
    }
  ],
  "detail": "text",
  "createdAt": "2026-09-15T10:32:00Z",
  "startedAt": "2026-09-15T10:32:00Z",
  "finishedAt": "2026-09-15T10:32:00Z"
}
POST/v1/workspaces/{workspaceId}/passes/remind

Eingeladene erinnern

Schickt eine Erinnerung an jeden gültigen Pass, der eine Einladung bekommen hat, noch in keiner Wallet liegt und dessen letzte Einladung älter als 3 Tage ist (mit templateId nur Pässe dieser Vorlage). Kontakte, die alles widerrufen haben oder gelöscht sind, bekommen nichts. „In einer Wallet“ heißt: eine Apple-Registrierung; ein nur in Google Wallet gespeicherter Pass meldet sich nicht zurück und bekommt die Erinnerung trotzdem (die Mail sagt, dass sie dann ignoriert werden kann). Jede Erinnerung ist ein neuer persönlicher Link; höchstens 2.000 je Aufruf (more: true = weitere fällig). Antwort sent. Ab der Rolle Bearbeiter, Token-Scope passes:issue; im Free-Plan gesperrt.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • templateIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/passes/remind" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}'
Antwort200
{
  "sent": 1,
  "more": true
}
POST/v1/passes/{id}/resend-invite

Einladung erneut senden

Schickt dem Kontakt eines Passes, der schon eine Einladung hatte, einen neuen persönlichen Link (die älteren bleiben gültig), auch wenn der Inhaber den Pass aus dem Wallet entfernt hat: über den Link legt er ihn wieder ab. 409, wenn der Pass entwertet oder abgelaufen ist (details.reason pass_not_active), noch nie eingeladen wurde (no_invite), keinen Kontakt hat (no_contact) oder der Kontakt alles widerrufen hat (contact_withdrawn); 429 innerhalb von 60 Sekunden nach der letzten Einladung. Ab der Rolle Bearbeiter und für Kundensupport, Token-Scope passes:issue oder passes:write.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 429Rate-Limit
  • 503Nicht verfügbar
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/passes/{id}/resend-invite" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "sent": true
}

Kontakte

Kontakte mit Einwilligung, Export für eigene Systeme.

GET/v1/workspaces/{id}/customers/summary

Kontakte zählen

Gesamt, mit aktiver Einwilligung und widerrufen.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{id}/customers/summary" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "total": 1,
  "consented": 1,
  "revoked": 1,
  "lastCollectedAt": "text"
}
GET/v1/workspaces/{id}/customers/export.csv

Kontakte als CSV exportieren

Nur Kontakte mit aktiver Einwilligung. Jeder Export wird mit Zweck und Anzahl im Audit-Log festgehalten. Org-Admin.

Pfad-Parameter

  • iduuidPflicht

Query-Parameter

  • purposestringoptional

Antworten

  • 200OK
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{id}/customers/export.csv?purpose=text" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{}
POST/v1/workspaces/{workspaceId}/consent-purposes

Zweck der Einwilligung anlegen

Legt warranty, brand_share oder einen eigenen Zweck (custom_<slug>) an. service und marketing_email gibt es in jedem Arbeitsbereich schon, sie ändert PATCH. Höchstens 20 Zwecke. Admin des Arbeitsbereichs, nur mit Browser-Sitzung.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • keystringPflicht
  • labelstringPflicht

    1–80 Zeichen

  • textstringPflicht

    1–1000 Zeichen

  • requiredbooleanoptional
  • activebooleanoptional

Antworten

  • 201Angelegt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/consent-purposes" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "key": "text",
  "label": "Sommer-Aktion",
  "text": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "required": false,
  "active": true
}'
Antwort201
{
  "key": "text",
  "label": "Sommer-Aktion",
  "text": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "required": true,
  "version": 1,
  "active": true,
  "textDraft": true,
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z"
}

Ereignisse

Roh-Ereignisse je Workspace und Pass, eigene Ereignisse schreiben.

GET/v1/workspaces/{workspaceId}/events

Ereignisse abfragen

Roh-Ereignisse des Workspace, neueste zuerst, gefiltert nach type und passId, höchstens 500 je Aufruf (limit). Ohne Blättern: für eine laufende Übernahme in dein System einen Webhook verwenden. payload enthält nie Geräte-Kennungen (deviceLibraryId, Push-Token); E-Mail, Name und Telefon sind unter der Rolle org_admin maskiert (k•••@verve.com), Kundensupport sieht sie ungekürzt.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • typestringoptional
  • passIduuidoptional
  • limitintegeroptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/events?type=text&passId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01&limit=100" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "type": "text",
      "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "payload": null,
      "source": "text",
      "occurredAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/events

Eigenes Ereignis schreiben

Für Signale aus deinem System, z. B. einen Kaufabschluss (purchase), am Pass (passId) oder am Workspace. Nutzungen meldest du über POST /v1/workspaces/{workspaceId}/redemptions oder eine Empfangs-URL. Ab der Rolle editor.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • typestringPflicht

    1–80 Zeichen

  • passIduuid | nulloptional
  • templateIduuid | nulloptional
  • campaignIduuid | nulloptional
  • payloadobjectoptional
  • sourcestringoptional

    0–60 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/events" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "type": "text",
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "payload": {},
  "source": "api"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "type": "text",
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "payload": null,
  "source": "text",
  "occurredAt": "2026-09-15T10:32:00Z"
}
GET/v1/events/{id}

Ereignis lesen

payload wie bei der Liste: ohne Geräte-Kennungen, Kontaktdaten unter org_admin maskiert.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/events/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "type": "text",
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "payload": null,
  "source": "text",
  "occurredAt": "2026-09-15T10:32:00Z"
}

Auswertung

Kennzahlen je Workspace und je UTM-Quelle.

GET/v1/workspaces/{workspaceId}/analytics/dashboard-kpis

Kennzahlen des Workspace

Pässe gesamt und aktiv; neue Pässe, Nutzungen, gesendete und zugestellte Pushes der letzten 7 Tage; dazu abgelaufene und Demo-Pässe, Mitteilungen, Nutzungen und Umsatz gesamt.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/analytics/dashboard-kpis" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "totalPasses": 1,
  "activePasses": 1,
  "passesCreatedLast7d": 1,
  "redemptionsLast7d": 1,
  "pushSentLast7d": 1,
  "pushDeliveredLast7d": 1,
  "demoPasses": 1,
  "expiredPasses": 1,
  "notificationsSent": 1,
  "redemptions": 1,
  "amountCents": 1250,
  "inWalletApple": 1,
  "inWalletGoogle": 1
}
GET/v1/workspaces/{workspaceId}/analytics/source-performance

Leistung je Quelle (UTM)

Ausgestellte Pässe und Nutzungen je UTM-Quelle.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/analytics/source-performance" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "utmSource": "text",
      "passes": 1,
      "redemptions": 1
    }
  ]
}
GET/v1/workspaces/{workspaceId}/analytics/business-case

Business-Case-Daten

Pässe, Nutzungen und Nutzungsquote je UTM-Quelle für das Business-Case-Dashboard.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/analytics/business-case" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "utmSource": "text",
      "passes": 1,
      "redemptions": 1,
      "conversionRate": 1
    }
  ]
}
GET/v1/benchmarks/business-case

Branchen-Benchmarks

Referenzwerte je Kanal, gegen die der Business Case vergleicht.

Antworten

  • 200OK
  • 500Default Response
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/benchmarks/business-case" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
null
GET/v1/workspaces/{workspaceId}/analytics/funnel

Trichter je Quelle, Kanal oder Kampagne

Seitenaufrufe, ausgestellte Pässe, geöffnet (Apple-Download, Google-Speichern-Klick), im Wallet (Apple, Google), Push zugestellt und bestätigt, genutzt und wiederholt genutzt, dazu Budget und Kosten je Wallet-Pass und je Nutzung. Kohorte: die Pässe des Zeitraums mit allen späteren Schritten; dimension = source, channel oder campaign.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • dimensionsource | channel | campaignoptional

    source = UTM-Quelle der Pässe, channel = Kanal der Landing-Seite (Quelle und Seite), campaign = Kampagne (ihre adressierten Pässe).

  • fromstringoptional

    Tag (YYYY-MM-DD, Zeitzone des Workspace) oder Zeitpunkt; Standard: die letzten 30 Tage.

  • tostringoptional
  • claimLinkIduuidoptional

    Nur diese Landing-Seite (source, channel).

  • campaignIduuidoptional

    Nur diese Kampagne (campaign).

  • templateIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/analytics/funnel?dimension=source&from=text&to=text" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "dimension": "source",
  "range": {
    "from": "2026-09-15T10:32:00Z",
    "to": "2026-09-15T10:32:00Z"
  },
  "data": [
    {
      "key": "text",
      "label": "Sommer-Aktion",
      "views": 1,
      "claims": 1,
      "downloadsApple": 1,
      "savesGoogle": 1,
      "addedApple": 1,
      "addedGoogle": 1,
      "pushDelivered": 1,
      "pushConfirmed": 1,
      "redeemedPasses": 1,
      "redemptions": 1,
      "repeatPasses": 1,
      "costCents": 1,
      "costPerAddedCents": 1,
      "costPerRedemptionCents": 1
    }
  ]
}
GET/v1/workspaces/{workspaceId}/analytics/funnel.csv

Trichter als CSV

Dieselben Zeilen wie GET …/analytics/funnel als CSV für Excel (Semikolon, UTF-8 mit BOM).

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • dimensionsource | channel | campaignoptional

    source = UTM-Quelle der Pässe, channel = Kanal der Landing-Seite (Quelle und Seite), campaign = Kampagne (ihre adressierten Pässe).

  • fromstringoptional

    Tag (YYYY-MM-DD, Zeitzone des Workspace) oder Zeitpunkt; Standard: die letzten 30 Tage.

  • tostringoptional
  • claimLinkIduuidoptional

    Nur diese Landing-Seite (source, channel).

  • campaignIduuidoptional

    Nur diese Kampagne (campaign).

  • templateIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/analytics/funnel.csv?dimension=source&from=text&to=text" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
"text"
GET/v1/workspaces/{workspaceId}/analytics/breakdown

Nutzungen und Pässe je Vorlage, Kampagne, Standort oder Quelle

by: template (Vorlage), campaign (Kampagne), location (Filiale wie im Protokoll, ohne Groß-/Kleinschreibung) oder source (Kanal des Passes, utm_source). from/to: Zeitstempel oder Kalendertag in der Zeitzone des Workspace; Vorgabe die letzten 30 Kalendertage, höchstens 366 Tage. campaignId und templateId grenzen ein wie im Protokoll. promotionId grenzt auf eine Aktion ein: bei campaign auf ihre Kampagnen, sonst auf Pässe und Nutzungen ihrer Vorlagen; eine Aktion eines anderen Workspace ist 404 promotion_not_found. Je Zeile: redemptions = Nutzungen im Zeitraum jeder Art (die Zahl des Protokolls mit demselben Filter), davon checkins (Einlass) und stamps (Stempel), amountCents = gemeldete Beträge. passesIssued = neue Pässe im Zeitraum (Vorlage, Quelle) bzw. erreichte Pässe über die ganze Laufzeit (Kampagne, gesendete Empfänger); activePasses = jetzt aktive Pässe (nicht deaktiviert, nicht abgelaufen, nicht entwertet); beide null, wo sie nicht gelten (Standort, Zeile ohne Vorlage oder Kampagne). key null = ohne Vorlage, Kampagne, Filiale bzw. Quelle (direkt); label ist dann leer. Kampagnen erscheinen mit Nutzungen im Zeitraum oder mit Start im Zeitraum. Meiste Nutzungen zuerst, die Zeile ohne key zuletzt, höchstens 500 Zeilen. Jede Rolle im Workspace, auch im Free-Plan.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • bytemplate | campaign | location | sourcePflicht
  • fromstringoptional
  • tostringoptional
  • campaignIduuidoptional
  • templateIduuidoptional
  • promotionIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/analytics/breakdown?by=template&from=2026-09-15T10%3A32%3A00Z&to=2026-09-15T10%3A32%3A00Z" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "by": "template",
  "range": {
    "from": "2026-09-15T10:32:00Z",
    "to": "2026-09-15T10:32:00Z"
  },
  "data": [
    {
      "key": "text",
      "label": "Sommer-Aktion",
      "passesIssued": 1,
      "activePasses": 1,
      "redemptions": 1,
      "checkins": 1,
      "stamps": 1,
      "amountCents": 1250
    }
  ]
}
GET/v1/workspaces/{workspaceId}/loyalty/overview

Treue-Übersicht

Kennzahlen der Programme eines Workspace (oder eines mit templateId bzw. program) für range 7, 30 oder 90 Tage (auch 7d), Tage in der Zeitzone des Workspace, jeweils mit dem Zeitraum davor (prev): Mitglieder, neue Mitglieder, vergebene Stempel und Punkte, erreichte und eingelöste Prämien, Einlösequote (von den im Zeitraum erreichten Prämien die bis jetzt eingelösten, null ohne erreichte), offene Prämien mit Wert. series: je Tag die Werte und der Tag im Zeitraum davor. distribution: Stempelverteilung je Stempelprogramm (höchstens 12 Balken, der letzte ist „Prämie bereit“). segments: Fast geschafft, Prämie bereit, Nicht abgeholt (14 Tage), Lange nicht da (60 Tage), Neu (30 Tage), Noch kein Stempel, nach denselben Regeln wie die Mitglieder-Liste und Zielgruppen. Gezählt werden nur echte Pässe (nicht Test, nicht intern) und keine Demo-Stempel. Bis zu 60 Sekunden zwischengespeichert. Jede Rolle im Workspace; Token-Scope passes:read. Ohne das Modul Treue 403 module_disabled.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • range7 | 30 | 90 | 7d | 30d | 90doptional
  • templateIduuidoptional
  • programuuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/loyalty/overview?range=30&templateId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01&program=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "range": 1,
  "timezone": "Europe/Berlin",
  "from": "2026-09-15T10:32:00Z",
  "to": "2026-09-15T10:32:00Z",
  "prevFrom": "2026-09-15T10:32:00Z",
  "programs": [
    {
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "archived": true,
      "kind": "stamps",
      "goal": 1,
      "reward": "text",
      "rewardType": "text",
      "rewardValue": 1,
      "afterReward": "text",
      "paused": true,
      "members": 1,
      "openRewards": 1,
      "nearGoal": 1
    }
  ],
  "kpis": {
    "members": {
      "value": 1,
      "prev": 1
    },
    "newMembers": {
      "value": 1,
      "prev": 1
    },
    "stampsGiven": {
      "value": 1,
      "prev": 1
    },
    "pointsGiven": {
      "value": 1,
      "prev": 1
    },
    "rewardsEarned": {
      "value": 1,
      "prev": 1
    },
    "rewardsRedeemed": {
      "value": 1,
      "prev": 1
    },
    "redemptionRate": {
      "value": 1,
      "prev": 1,
      "earned": 1,
      "redeemed": 1,
      "prevEarned": 1,
      "prevRedeemed": 1
    },
    "openRewards": {
      "count": 1,
      "valueCents": 1
    }
  },
  "series": [
    {
      "date": "text",
      "stamps": 1,
      "points": 1,
      "rewardsEarned": 1,
      "rewardsRedeemed": 1,
      "newMembers": 1,
      "prevDate": "text",
      "prevStamps": 1,
      "prevPoints": 1,
      "prevRewardsEarned": 1,
      "prevRewardsRedeemed": 1,
      "prevNewMembers": 1
    }
  ],
  "distribution": [
    {
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "goal": 1,
      "buckets": [
        {
          "from": 1,
          "to": 1,
          "count": 1,
          "rewardReady": true
        }
      ]
    }
  ],
  "segments": [
    {
      "key": "near_goal",
      "label": "Sommer-Aktion",
      "count": 1
    }
  ],
  "generatedAt": "2026-09-15T10:32:00Z"
}

Pässe und Kampagnen

Pass-Vorlagen

Vorlagen: Design, Feldliste, Wertquelle, Versionen, Veröffentlichung.

GET/v1/workspaces/{workspaceId}/templates

Vorlagen auflisten

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • statusdraft | published | archivedoptional
  • passTypeboardingPass | coupon | eventTicket | generic | storeCardoptional
  • includeheadoptional
  • promotionIdstringoptional

    Nur Teile dieser Aktion; none = ohne Aktion.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/templates?status=draft&passType=boardingPass&include=head" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "useCase": "coupon",
      "passType": "boardingPass",
      "googleClassType": "loyalty",
      "status": "draft",
      "folderId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "currentVersion": 1,
      "currentDraftVersion": 1,
      "valueSource": {
        "mode": "static",
        "value": "text"
      },
      "attributeSchema": [
        {
          "key": "text",
          "label": "Sommer-Aktion",
          "type": "text",
          "required": false,
          "fromPublicClaim": false
        }
      ],
      "organizationName": "Sommer-Aktion",
      "logoText": "Heute 20 % auf alles. Nur bis Ladenschluss.",
      "description": "Kurze Beschreibung",
      "eventStartsAt": "2026-09-15T10:32:00Z",
      "eventEndsAt": "2026-09-15T10:32:00Z",
      "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "createdAt": "2026-09-15T10:32:00Z",
      "updatedAt": "2026-09-15T10:32:00Z",
      "publishedAt": "2026-09-15T10:32:00Z",
      "archivedAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/templates

Vorlage anlegen

Startet als Entwurf mit einem Start-Design. Änderungen am Design (Felder, Farben, Barcode, Bilder) kommen als neue Version (POST /v1/templates/{id}/versions) und gelten ab dem Veröffentlichen. preset legt eine fertige Vorlage an: stamp_card (Stempelkarte mit Treue-Regel 10 Stempel = 1 Kaffee), membership_card (Mitgliedsausweis, Feldliste name, mitgliedsnr, gueltig_bis), product_pass (Produktpass: produkt, seriennr, kaufdatum) oder insurance_card (Versicherungskarte: name, vertragsnr, tarif). Ein Preset bringt Zweck, Apple-Stil und Google-Klasse mit (useCase, passType, googleClassType dürfen dann fehlen und müssen sonst passen), das Design in der Sprache des Workspace, die Feldliste und die Einlöse-Regel unbegrenzt; alles in einer Transaktion. Ohne eigenen logoText trägt jede neue Vorlage den organizationName als Logo-Text (höchstens 40 Zeichen). Ohne preset sind useCase, passType und googleClassType Pflicht. Ab der Rolle editor. stamp_card braucht das Modul Treue der Organisation, sonst 403 module_disabled (ohne Treue-Regel zeigte die Karte „0 / “). Der Pass-Typ (aus useCase: coupon, loyalty, eventTicket = event, giftCard = giftcard, boardingPass und transit = boarding, sonst generic) muss für die Organisation freigeschaltet sein (capabilities.passTypes in GET /v1/orgs/{id}), sonst 403 pass_type_not_allowed mit details.passType und details.allowed. Bestehende Vorlagen eines nicht mehr freigeschalteten Typs bleiben nutzbar.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–120 Zeichen

  • useCase"coupon" | "loyalty" | "giftCard" | "membership" | "eventTicket" | "boardingPass" | "transit" | "generic"optional
  • passType"boardingPass" | "coupon" | "eventTicket" | "generic" | "storeCard"optional
  • googleClassType"loyalty" | "offer" | "eventTicket" | "flight" | "transit" | "generic" | "giftCard"optional
  • preset"stamp_card" | "membership_card" | "product_pass" | "insurance_card"optional
  • organizationNamestringPflicht

    1–120 Zeichen

  • logoTextstring | nulloptional
  • descriptionstring | nulloptional
  • folderIduuid | nulloptional
  • promotionIduuid | nulloptional

    Aktion, zu der das Teil gehört (GET /v1/workspaces/{id}/promotions); null = ohne Aktion. Fremde Aktion 404 promotion_not_found, archivierte 409 promotion_archived.

  • walletDocumentobjectoptional
  • useCase"coupon" | "loyalty" | "giftCard" | "membership" | "eventTicket" | "boardingPass" | "transit" | "generic"Pflicht
  • identityobjectPflicht
  • passType"boardingPass" | "coupon" | "eventTicket" | "generic" | "storeCard"Pflicht
  • googleClass"loyalty" | "offer" | "eventTicket" | "flight" | "transit" | "generic" | "giftCard"Pflicht
  • serialstringoptional
  • transitType"PKTransitTypeAir" | "PKTransitTypeBus" | "PKTransitTypeTrain" | "PKTransitTypeBoat" | "PKTransitTypeGeneric"optional
  • brandingobjectPflicht
  • backgroundHexstringPflicht
  • foregroundHexstringPflicht
  • labelHexstringPflicht
  • stripLabelHexstringoptional
  • logoTextstringoptional

    0–40 Zeichen

  • suppressStripShinebooleanoptional
  • groupingIdentifierstringoptional
  • landingStyle"classic" | "spotlight" | "card"optional
  • fieldsobjectPflicht
  • headerobject[]optional

    0–3 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • primaryobject[]Pflicht

    0–2 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • secondaryobject[]optional

    0–4 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • auxiliaryobject[]optional

    0–4 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • backobject[]optional
  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • loyaltyobjectoptional
  • pointsLabelstringPflicht

    1–40 Zeichen

  • pointsBalancenumber | stringPflicht
  • secondaryPointsLabelstringoptional

    1–40 Zeichen

  • secondaryPointsBalancenumber | stringoptional
  • accountIdstringoptional
  • accountNamestringoptional
  • tierstringoptional
  • giftCardobjectoptional
  • balancenumberPflicht

    0 bis ∞

  • currencyCodestringPflicht

    3–3 Zeichen

  • barcodesobject[]Pflicht

    1–4 Einträge

  • format"PKBarcodeFormatQR" | "PKBarcodeFormatPDF417" | "PKBarcodeFormatAztec" | "PKBarcodeFormatCode128" | "PKBarcodeFormatEAN13" | "PKBarcodeFormatCode39" | "PKBarcodeFormatCodabar" | "PKBarcodeFormatI2of5"Pflicht
  • messagestringPflicht
  • messageEncodingstringoptional
  • altTextstringoptional
  • rotatingBarcodeobjectoptional
  • totpKeystringPflicht

    16–∞ Zeichen

  • period60optional
  • type"QR_CODE" | "PDF_417"optional
  • imagesobjectPflicht
  • logoAssetIduuidoptional
  • iconAssetIduuidoptional
  • stripAssetIduuidoptional
  • thumbnailAssetIduuidoptional
  • backgroundAssetIduuidoptional
  • footerAssetIduuidoptional
  • heroAssetIduuidoptional
  • googleLogoAssetIduuidoptional
  • locationsobject[]optional

    0–10 Einträge

  • latitudenumberPflicht

    -90 bis 90

  • longitudenumberPflicht

    -180 bis 180

  • altitudenumberoptional
  • relevantTextstringoptional

    0–120 Zeichen

  • maxDistanceintegeroptional

    10 bis 50000

  • beaconsobject[]optional

    0–10 Einträge

  • proximityUuiduuidPflicht
  • majorintegeroptional

    0 bis 65535

  • minorintegeroptional

    0 bis 65535

  • relevantTextstringoptional

    0–120 Zeichen

  • nfcobjectoptional
  • messagestringPflicht
  • encryptionPublicKeystringoptional
  • requiresAuthenticationbooleanoptional
  • smartTapValuestringoptional
  • validityobjectPflicht
  • expirationDatedate-timeoptional
  • relevantDatedate-timeoptional
  • relevantDatesobject[]optional

    0–10 Einträge

  • startDatedate-timePflicht
  • endDatedate-timeoptional
  • voidedbooleanoptional
  • sharingProhibitedbooleanoptional
  • featuredActionsobject[]optional

    0–2 Einträge

  • labelstringPflicht

    1–40 Zeichen

  • urlurioptional
  • placeIdentifierstringoptional
  • typestringoptional
  • identifierstringoptional

    1–60 Zeichen

  • posterobjectoptional
  • enabledbooleanoptional
  • footerLabelstringoptional

    0–40 Zeichen

  • footerValuestringoptional

    0–80 Zeichen

  • fallbackStyle"generic" | "storeCard" | "coupon" | "eventTicket"optional
  • suppressHeaderDarkeningbooleanoptional
  • googleActionobjectoptional
  • labelstringPflicht

    1–30 Zeichen

  • urlstringPflicht

    1–2048 Zeichen

  • coverHintobjectoptional
  • enabledbooleanoptional
  • textstringoptional

    0–48 Zeichen

  • backgroundHexstringoptional
  • textHexstringoptional
  • personalImagesobjectoptional
  • stripobjectoptional
  • attributestringPflicht
  • logoobjectoptional
  • attributestringPflicht
  • appLinkobjectoptional
  • appStoreIdsinteger[]optional
  • launchUrlurioptional
  • backobjectoptional
  • linksobject[]optional
  • labelstringPflicht
  • urluriPflicht
  • textsobject[]optional
  • labelstringPflicht
  • valuestringPflicht
  • semanticsobjectoptional
  • localizationsobjectoptional
  • stampCardobjectoptional
  • goalintegerPflicht

    2 bis 50

  • rewardstringPflicht

    1–60 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/templates" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "useCase": "coupon",
  "passType": "boardingPass",
  "googleClassType": "loyalty",
  "preset": "stamp_card",
  "organizationName": "Sommer-Aktion",
  "logoText": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "description": "Kurze Beschreibung",
  "folderId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "walletDocument": {
    "useCase": "coupon",
    "identity": {
      "passType": "boardingPass",
      "googleClass": "loyalty"
    },
    "branding": {
      "backgroundHex": "text",
      "foregroundHex": "text",
      "labelHex": "Sommer-Aktion"
    },
    "fields": {
      "primary": [
        {
          "key": "text",
          "value": "text"
        }
      ]
    },
    "loyalty": {
      "pointsLabel": "Sommer-Aktion",
      "pointsBalance": 1
    },
    "giftCard": {
      "balance": 1,
      "currencyCode": "EUR"
    },
    "barcodes": [
      {
        "format": "PKBarcodeFormatQR",
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    ],
    "rotatingBarcode": {
      "totpKey": "text"
    },
    "images": {},
    "locations": [
      {
        "latitude": 1,
        "longitude": 1
      }
    ],
    "maxDistance": 10,
    "beacons": [
      {
        "proximityUuid": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
      }
    ],
    "nfc": {
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
    },
    "validity": {},
    "featuredActions": [
      {
        "label": "Sommer-Aktion"
      }
    ],
    "poster": {},
    "googleAction": {
      "label": "Sommer-Aktion",
      "url": "https://example.de/hook"
    },
    "coverHint": {},
    "personalImages": {},
    "appLink": {},
    "back": {},
    "semantics": {},
    "localizations": {}
  },
  "stampCard": {
    "goal": 2,
    "reward": "text"
  }
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "useCase": "coupon",
  "passType": "boardingPass",
  "googleClassType": "loyalty",
  "status": "draft",
  "folderId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "currentVersion": 1,
  "currentDraftVersion": 1,
  "valueSource": {
    "mode": "static",
    "value": "text"
  },
  "attributeSchema": [
    {
      "key": "text",
      "label": "Sommer-Aktion",
      "type": "text",
      "required": false,
      "fromPublicClaim": false
    }
  ],
  "organizationName": "Sommer-Aktion",
  "logoText": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "description": "Kurze Beschreibung",
  "eventStartsAt": "2026-09-15T10:32:00Z",
  "eventEndsAt": "2026-09-15T10:32:00Z",
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "publishedAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ]
}
GET/v1/templates/{id}

Vorlage lesen

Mit Feldliste (attributeSchema) und Wertquelle (valueSource).

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/templates/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "useCase": "coupon",
  "passType": "boardingPass",
  "googleClassType": "loyalty",
  "status": "draft",
  "folderId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "currentVersion": 1,
  "currentDraftVersion": 1,
  "valueSource": {
    "mode": "static",
    "value": "text"
  },
  "attributeSchema": [
    {
      "key": "text",
      "label": "Sommer-Aktion",
      "type": "text",
      "required": false,
      "fromPublicClaim": false
    }
  ],
  "organizationName": "Sommer-Aktion",
  "logoText": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "description": "Kurze Beschreibung",
  "eventStartsAt": "2026-09-15T10:32:00Z",
  "eventEndsAt": "2026-09-15T10:32:00Z",
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "publishedAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ]
}
PATCH/v1/templates/{id}

Vorlage bearbeiten

Name, Organisation, Ordner, Event-Zeitraum, Feldliste (attributeSchema: Schlüssel, Bezeichnung, Typ, Pflicht, über öffentlichen Link setzbar) und Wertquelle (valueSource: fester Wert, Code-Listen oder API deines Systems). Feldliste und Wertquelle gelten sofort für neue Pässe; das Design ändert sich erst mit einer neuen veröffentlichten Version. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • organizationNamestringoptional

    1–120 Zeichen

  • logoTextstring | nulloptional
  • descriptionstring | nulloptional
  • eventStartsAtdate-time | nulloptional
  • eventEndsAtdate-time | nulloptional
  • valueSourceobject | nulloptional
  • attributeSchemaobject[]optional

    0–40 Einträge

  • keystringPflicht
  • labelstringPflicht

    1–60 Zeichen

  • type"text" | "number" | "date"Pflicht
  • requiredbooleanoptional
  • fromPublicClaimbooleanoptional
  • role"eventStart"optional
  • folderIduuid | nulloptional
  • promotionIduuid | nulloptional

    Aktion, zu der das Teil gehört (GET /v1/workspaces/{id}/promotions); null = ohne Aktion. Fremde Aktion 404 promotion_not_found, archivierte 409 promotion_archived.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/templates/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "organizationName": "Sommer-Aktion",
  "logoText": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "description": "Kurze Beschreibung",
  "eventStartsAt": "2026-09-15T10:32:00Z",
  "eventEndsAt": "2026-09-15T10:32:00Z",
  "valueSource": {
    "mode": "static",
    "value": "text"
  },
  "attributeSchema": [
    {
      "key": "text",
      "label": "Sommer-Aktion",
      "type": "text"
    }
  ],
  "folderId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "useCase": "coupon",
  "passType": "boardingPass",
  "googleClassType": "loyalty",
  "status": "draft",
  "folderId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "currentVersion": 1,
  "currentDraftVersion": 1,
  "valueSource": {
    "mode": "static",
    "value": "text"
  },
  "attributeSchema": [
    {
      "key": "text",
      "label": "Sommer-Aktion",
      "type": "text",
      "required": false,
      "fromPublicClaim": false
    }
  ],
  "organizationName": "Sommer-Aktion",
  "logoText": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "description": "Kurze Beschreibung",
  "eventStartsAt": "2026-09-15T10:32:00Z",
  "eventEndsAt": "2026-09-15T10:32:00Z",
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "publishedAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ]
}
DELETE/v1/templates/{id}

Vorlage archivieren

Setzt die Vorlage auf archiviert; ausgestellte Pässe bleiben gültig. Ab der Rolle org_admin.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/templates/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/templates/{id}/unarchive

Archivierte Vorlage wiederherstellen

Holt eine archivierte Vorlage zurück: veröffentlicht, wenn sie eine veröffentlichte Version hat, sonst als Entwurf. 409 conflict, wenn sie nicht archiviert ist. Ab der Rolle org_admin.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/unarchive" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "useCase": "coupon",
  "passType": "boardingPass",
  "googleClassType": "loyalty",
  "status": "draft",
  "folderId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "currentVersion": 1,
  "currentDraftVersion": 1,
  "valueSource": {
    "mode": "static",
    "value": "text"
  },
  "attributeSchema": [
    {
      "key": "text",
      "label": "Sommer-Aktion",
      "type": "text",
      "required": false,
      "fromPublicClaim": false
    }
  ],
  "organizationName": "Sommer-Aktion",
  "logoText": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "description": "Kurze Beschreibung",
  "eventStartsAt": "2026-09-15T10:32:00Z",
  "eventEndsAt": "2026-09-15T10:32:00Z",
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "publishedAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ]
}
GET/v1/templates/{id}/versions

Versionen auflisten

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/templates/{id}/versions" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "version": 1,
      "walletDocument": {},
      "locales": {},
      "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "createdAt": "2026-09-15T10:32:00Z",
      "updatedAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/templates/{id}/versions

Version anlegen

Legt mit dem übergebenen Design (walletDocument) eine neue Version an.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • walletDocumentobjectPflicht
  • useCase"coupon" | "loyalty" | "giftCard" | "membership" | "eventTicket" | "boardingPass" | "transit" | "generic"Pflicht
  • identityobjectPflicht
  • passType"boardingPass" | "coupon" | "eventTicket" | "generic" | "storeCard"Pflicht
  • googleClass"loyalty" | "offer" | "eventTicket" | "flight" | "transit" | "generic" | "giftCard"Pflicht
  • serialstringoptional
  • transitType"PKTransitTypeAir" | "PKTransitTypeBus" | "PKTransitTypeTrain" | "PKTransitTypeBoat" | "PKTransitTypeGeneric"optional
  • brandingobjectPflicht
  • backgroundHexstringPflicht
  • foregroundHexstringPflicht
  • labelHexstringPflicht
  • stripLabelHexstringoptional
  • logoTextstringoptional

    0–40 Zeichen

  • suppressStripShinebooleanoptional
  • groupingIdentifierstringoptional
  • landingStyle"classic" | "spotlight" | "card"optional
  • fieldsobjectPflicht
  • headerobject[]optional

    0–3 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • primaryobject[]Pflicht

    0–2 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • secondaryobject[]optional

    0–4 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • auxiliaryobject[]optional

    0–4 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • backobject[]optional
  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • loyaltyobjectoptional
  • pointsLabelstringPflicht

    1–40 Zeichen

  • pointsBalancenumber | stringPflicht
  • secondaryPointsLabelstringoptional

    1–40 Zeichen

  • secondaryPointsBalancenumber | stringoptional
  • accountIdstringoptional
  • accountNamestringoptional
  • tierstringoptional
  • giftCardobjectoptional
  • balancenumberPflicht

    0 bis ∞

  • currencyCodestringPflicht

    3–3 Zeichen

  • barcodesobject[]Pflicht

    1–4 Einträge

  • format"PKBarcodeFormatQR" | "PKBarcodeFormatPDF417" | "PKBarcodeFormatAztec" | "PKBarcodeFormatCode128" | "PKBarcodeFormatEAN13" | "PKBarcodeFormatCode39" | "PKBarcodeFormatCodabar" | "PKBarcodeFormatI2of5"Pflicht
  • messagestringPflicht
  • messageEncodingstringoptional
  • altTextstringoptional
  • rotatingBarcodeobjectoptional
  • totpKeystringPflicht

    16–∞ Zeichen

  • period60optional
  • type"QR_CODE" | "PDF_417"optional
  • imagesobjectPflicht
  • logoAssetIduuidoptional
  • iconAssetIduuidoptional
  • stripAssetIduuidoptional
  • thumbnailAssetIduuidoptional
  • backgroundAssetIduuidoptional
  • footerAssetIduuidoptional
  • heroAssetIduuidoptional
  • googleLogoAssetIduuidoptional
  • locationsobject[]optional

    0–10 Einträge

  • latitudenumberPflicht

    -90 bis 90

  • longitudenumberPflicht

    -180 bis 180

  • altitudenumberoptional
  • relevantTextstringoptional

    0–120 Zeichen

  • maxDistanceintegeroptional

    10 bis 50000

  • beaconsobject[]optional

    0–10 Einträge

  • proximityUuiduuidPflicht
  • majorintegeroptional

    0 bis 65535

  • minorintegeroptional

    0 bis 65535

  • relevantTextstringoptional

    0–120 Zeichen

  • nfcobjectoptional
  • messagestringPflicht
  • encryptionPublicKeystringoptional
  • requiresAuthenticationbooleanoptional
  • smartTapValuestringoptional
  • validityobjectPflicht
  • expirationDatedate-timeoptional
  • relevantDatedate-timeoptional
  • relevantDatesobject[]optional

    0–10 Einträge

  • startDatedate-timePflicht
  • endDatedate-timeoptional
  • voidedbooleanoptional
  • sharingProhibitedbooleanoptional
  • featuredActionsobject[]optional

    0–2 Einträge

  • labelstringPflicht

    1–40 Zeichen

  • urlurioptional
  • placeIdentifierstringoptional
  • typestringoptional
  • identifierstringoptional

    1–60 Zeichen

  • posterobjectoptional
  • enabledbooleanoptional
  • footerLabelstringoptional

    0–40 Zeichen

  • footerValuestringoptional

    0–80 Zeichen

  • fallbackStyle"generic" | "storeCard" | "coupon" | "eventTicket"optional
  • suppressHeaderDarkeningbooleanoptional
  • googleActionobjectoptional
  • labelstringPflicht

    1–30 Zeichen

  • urlstringPflicht

    1–2048 Zeichen

  • coverHintobjectoptional
  • enabledbooleanoptional
  • textstringoptional

    0–48 Zeichen

  • backgroundHexstringoptional
  • textHexstringoptional
  • personalImagesobjectoptional
  • stripobjectoptional
  • attributestringPflicht
  • logoobjectoptional
  • attributestringPflicht
  • appLinkobjectoptional
  • appStoreIdsinteger[]optional
  • launchUrlurioptional
  • backobjectoptional
  • linksobject[]optional
  • labelstringPflicht
  • urluriPflicht
  • textsobject[]optional
  • labelstringPflicht
  • valuestringPflicht
  • semanticsobjectoptional
  • localizationsobjectoptional
  • localesobjectoptional
  • baseVersionintegeroptional

    -∞ bis 9007199254740991

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/versions" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "walletDocument": {
    "useCase": "coupon",
    "identity": {
      "passType": "boardingPass",
      "googleClass": "loyalty"
    },
    "branding": {
      "backgroundHex": "text",
      "foregroundHex": "text",
      "labelHex": "Sommer-Aktion"
    },
    "fields": {
      "primary": [
        {
          "key": "text",
          "value": "text"
        }
      ]
    },
    "loyalty": {
      "pointsLabel": "Sommer-Aktion",
      "pointsBalance": 1
    },
    "giftCard": {
      "balance": 1,
      "currencyCode": "EUR"
    },
    "barcodes": [
      {
        "format": "PKBarcodeFormatQR",
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    ],
    "rotatingBarcode": {
      "totpKey": "text"
    },
    "images": {},
    "locations": [
      {
        "latitude": 1,
        "longitude": 1
      }
    ],
    "maxDistance": 10,
    "beacons": [
      {
        "proximityUuid": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
      }
    ],
    "nfc": {
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
    },
    "validity": {},
    "featuredActions": [
      {
        "label": "Sommer-Aktion"
      }
    ],
    "poster": {},
    "googleAction": {
      "label": "Sommer-Aktion",
      "url": "https://example.de/hook"
    },
    "coverHint": {},
    "personalImages": {},
    "appLink": {},
    "back": {},
    "semantics": {},
    "localizations": {}
  },
  "locales": {},
  "baseVersion": 1
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "version": 1,
  "walletDocument": {},
  "locales": {},
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z"
}
PUT/v1/templates/{id}/versions/draft

Entwurf speichern

Speichert das Design (walletDocument) als Entwurfsversion der Vorlage. baseVersion und baseRevision verhindern, dass eine andere Sitzung überschrieben wird: passen sie nicht mehr, antwortet die Route mit 409 und dem aktuellen Stand. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • walletDocumentobjectPflicht
  • useCase"coupon" | "loyalty" | "giftCard" | "membership" | "eventTicket" | "boardingPass" | "transit" | "generic"Pflicht
  • identityobjectPflicht
  • passType"boardingPass" | "coupon" | "eventTicket" | "generic" | "storeCard"Pflicht
  • googleClass"loyalty" | "offer" | "eventTicket" | "flight" | "transit" | "generic" | "giftCard"Pflicht
  • serialstringoptional
  • transitType"PKTransitTypeAir" | "PKTransitTypeBus" | "PKTransitTypeTrain" | "PKTransitTypeBoat" | "PKTransitTypeGeneric"optional
  • brandingobjectPflicht
  • backgroundHexstringPflicht
  • foregroundHexstringPflicht
  • labelHexstringPflicht
  • stripLabelHexstringoptional
  • logoTextstringoptional

    0–40 Zeichen

  • suppressStripShinebooleanoptional
  • groupingIdentifierstringoptional
  • landingStyle"classic" | "spotlight" | "card"optional
  • fieldsobjectPflicht
  • headerobject[]optional

    0–3 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • primaryobject[]Pflicht

    0–2 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • secondaryobject[]optional

    0–4 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • auxiliaryobject[]optional

    0–4 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • backobject[]optional
  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • loyaltyobjectoptional
  • pointsLabelstringPflicht

    1–40 Zeichen

  • pointsBalancenumber | stringPflicht
  • secondaryPointsLabelstringoptional

    1–40 Zeichen

  • secondaryPointsBalancenumber | stringoptional
  • accountIdstringoptional
  • accountNamestringoptional
  • tierstringoptional
  • giftCardobjectoptional
  • balancenumberPflicht

    0 bis ∞

  • currencyCodestringPflicht

    3–3 Zeichen

  • barcodesobject[]Pflicht

    1–4 Einträge

  • format"PKBarcodeFormatQR" | "PKBarcodeFormatPDF417" | "PKBarcodeFormatAztec" | "PKBarcodeFormatCode128" | "PKBarcodeFormatEAN13" | "PKBarcodeFormatCode39" | "PKBarcodeFormatCodabar" | "PKBarcodeFormatI2of5"Pflicht
  • messagestringPflicht
  • messageEncodingstringoptional
  • altTextstringoptional
  • rotatingBarcodeobjectoptional
  • totpKeystringPflicht

    16–∞ Zeichen

  • period60optional
  • type"QR_CODE" | "PDF_417"optional
  • imagesobjectPflicht
  • logoAssetIduuidoptional
  • iconAssetIduuidoptional
  • stripAssetIduuidoptional
  • thumbnailAssetIduuidoptional
  • backgroundAssetIduuidoptional
  • footerAssetIduuidoptional
  • heroAssetIduuidoptional
  • googleLogoAssetIduuidoptional
  • locationsobject[]optional

    0–10 Einträge

  • latitudenumberPflicht

    -90 bis 90

  • longitudenumberPflicht

    -180 bis 180

  • altitudenumberoptional
  • relevantTextstringoptional

    0–120 Zeichen

  • maxDistanceintegeroptional

    10 bis 50000

  • beaconsobject[]optional

    0–10 Einträge

  • proximityUuiduuidPflicht
  • majorintegeroptional

    0 bis 65535

  • minorintegeroptional

    0 bis 65535

  • relevantTextstringoptional

    0–120 Zeichen

  • nfcobjectoptional
  • messagestringPflicht
  • encryptionPublicKeystringoptional
  • requiresAuthenticationbooleanoptional
  • smartTapValuestringoptional
  • validityobjectPflicht
  • expirationDatedate-timeoptional
  • relevantDatedate-timeoptional
  • relevantDatesobject[]optional

    0–10 Einträge

  • startDatedate-timePflicht
  • endDatedate-timeoptional
  • voidedbooleanoptional
  • sharingProhibitedbooleanoptional
  • featuredActionsobject[]optional

    0–2 Einträge

  • labelstringPflicht

    1–40 Zeichen

  • urlurioptional
  • placeIdentifierstringoptional
  • typestringoptional
  • identifierstringoptional

    1–60 Zeichen

  • posterobjectoptional
  • enabledbooleanoptional
  • footerLabelstringoptional

    0–40 Zeichen

  • footerValuestringoptional

    0–80 Zeichen

  • fallbackStyle"generic" | "storeCard" | "coupon" | "eventTicket"optional
  • suppressHeaderDarkeningbooleanoptional
  • googleActionobjectoptional
  • labelstringPflicht

    1–30 Zeichen

  • urlstringPflicht

    1–2048 Zeichen

  • coverHintobjectoptional
  • enabledbooleanoptional
  • textstringoptional

    0–48 Zeichen

  • backgroundHexstringoptional
  • textHexstringoptional
  • personalImagesobjectoptional
  • stripobjectoptional
  • attributestringPflicht
  • logoobjectoptional
  • attributestringPflicht
  • appLinkobjectoptional
  • appStoreIdsinteger[]optional
  • launchUrlurioptional
  • backobjectoptional
  • linksobject[]optional
  • labelstringPflicht
  • urluriPflicht
  • textsobject[]optional
  • labelstringPflicht
  • valuestringPflicht
  • semanticsobjectoptional
  • localizationsobjectoptional
  • localesobjectoptional
  • baseVersionintegeroptional

    -∞ bis 9007199254740991

  • baseRevisiondate-timeoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PUT "https://api.dowallet.dev/v1/templates/{id}/versions/draft" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "walletDocument": {
    "useCase": "coupon",
    "identity": {
      "passType": "boardingPass",
      "googleClass": "loyalty"
    },
    "branding": {
      "backgroundHex": "text",
      "foregroundHex": "text",
      "labelHex": "Sommer-Aktion"
    },
    "fields": {
      "primary": [
        {
          "key": "text",
          "value": "text"
        }
      ]
    },
    "loyalty": {
      "pointsLabel": "Sommer-Aktion",
      "pointsBalance": 1
    },
    "giftCard": {
      "balance": 1,
      "currencyCode": "EUR"
    },
    "barcodes": [
      {
        "format": "PKBarcodeFormatQR",
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    ],
    "rotatingBarcode": {
      "totpKey": "text"
    },
    "images": {},
    "locations": [
      {
        "latitude": 1,
        "longitude": 1
      }
    ],
    "maxDistance": 10,
    "beacons": [
      {
        "proximityUuid": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
      }
    ],
    "nfc": {
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
    },
    "validity": {},
    "featuredActions": [
      {
        "label": "Sommer-Aktion"
      }
    ],
    "poster": {},
    "googleAction": {
      "label": "Sommer-Aktion",
      "url": "https://example.de/hook"
    },
    "coverHint": {},
    "personalImages": {},
    "appLink": {},
    "back": {},
    "semantics": {},
    "localizations": {}
  },
  "locales": {},
  "baseVersion": 1,
  "baseRevision": "2026-09-15T10:32:00Z"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "version": 1,
  "walletDocument": {},
  "locales": {},
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z"
}
POST/v1/templates/{id}/preflight

Veröffentlichung prüfen

Prüft das Design vor dem Veröffentlichen: Icon, Barcode mit {{code}}, Platzhalter gegen die Feldliste, Kontraste von Text und Logo auf Apple und Google, Zahl der Felder je Stil, Ablaufdatum. Liefert Fehler und Hinweise.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • walletDocumentobjectoptional
  • useCase"coupon" | "loyalty" | "giftCard" | "membership" | "eventTicket" | "boardingPass" | "transit" | "generic"Pflicht
  • identityobjectPflicht
  • passType"boardingPass" | "coupon" | "eventTicket" | "generic" | "storeCard"Pflicht
  • googleClass"loyalty" | "offer" | "eventTicket" | "flight" | "transit" | "generic" | "giftCard"Pflicht
  • serialstringoptional
  • transitType"PKTransitTypeAir" | "PKTransitTypeBus" | "PKTransitTypeTrain" | "PKTransitTypeBoat" | "PKTransitTypeGeneric"optional
  • brandingobjectPflicht
  • backgroundHexstringPflicht
  • foregroundHexstringPflicht
  • labelHexstringPflicht
  • stripLabelHexstringoptional
  • logoTextstringoptional

    0–40 Zeichen

  • suppressStripShinebooleanoptional
  • groupingIdentifierstringoptional
  • landingStyle"classic" | "spotlight" | "card"optional
  • fieldsobjectPflicht
  • headerobject[]optional

    0–3 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • primaryobject[]Pflicht

    0–2 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • secondaryobject[]optional

    0–4 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • auxiliaryobject[]optional

    0–4 Einträge

  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • backobject[]optional
  • keystringPflicht

    1–64 Zeichen

  • labelstringoptional

    0–120 Zeichen

  • valuestringPflicht
  • changeMessagestringoptional
  • textAlignment"PKTextAlignmentLeft" | "PKTextAlignmentCenter" | "PKTextAlignmentRight" | "PKTextAlignmentNatural"optional
  • numberStyle"PKNumberStyleDecimal" | "PKNumberStylePercent" | "PKNumberStyleScientific" | "PKNumberStyleSpellOut"optional
  • currencyCodestringoptional

    3–3 Zeichen

  • dateStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • timeStyle"PKDateStyleNone" | "PKDateStyleShort" | "PKDateStyleMedium" | "PKDateStyleLong" | "PKDateStyleFull"optional
  • isRelativebooleanoptional
  • ignoresTimeZonebooleanoptional
  • attributedValuestringoptional
  • loyaltyobjectoptional
  • pointsLabelstringPflicht

    1–40 Zeichen

  • pointsBalancenumber | stringPflicht
  • secondaryPointsLabelstringoptional

    1–40 Zeichen

  • secondaryPointsBalancenumber | stringoptional
  • accountIdstringoptional
  • accountNamestringoptional
  • tierstringoptional
  • giftCardobjectoptional
  • balancenumberPflicht

    0 bis ∞

  • currencyCodestringPflicht

    3–3 Zeichen

  • barcodesobject[]Pflicht

    1–4 Einträge

  • format"PKBarcodeFormatQR" | "PKBarcodeFormatPDF417" | "PKBarcodeFormatAztec" | "PKBarcodeFormatCode128" | "PKBarcodeFormatEAN13" | "PKBarcodeFormatCode39" | "PKBarcodeFormatCodabar" | "PKBarcodeFormatI2of5"Pflicht
  • messagestringPflicht
  • messageEncodingstringoptional
  • altTextstringoptional
  • rotatingBarcodeobjectoptional
  • totpKeystringPflicht

    16–∞ Zeichen

  • period60optional
  • type"QR_CODE" | "PDF_417"optional
  • imagesobjectPflicht
  • logoAssetIduuidoptional
  • iconAssetIduuidoptional
  • stripAssetIduuidoptional
  • thumbnailAssetIduuidoptional
  • backgroundAssetIduuidoptional
  • footerAssetIduuidoptional
  • heroAssetIduuidoptional
  • googleLogoAssetIduuidoptional
  • locationsobject[]optional

    0–10 Einträge

  • latitudenumberPflicht

    -90 bis 90

  • longitudenumberPflicht

    -180 bis 180

  • altitudenumberoptional
  • relevantTextstringoptional

    0–120 Zeichen

  • maxDistanceintegeroptional

    10 bis 50000

  • beaconsobject[]optional

    0–10 Einträge

  • proximityUuiduuidPflicht
  • majorintegeroptional

    0 bis 65535

  • minorintegeroptional

    0 bis 65535

  • relevantTextstringoptional

    0–120 Zeichen

  • nfcobjectoptional
  • messagestringPflicht
  • encryptionPublicKeystringoptional
  • requiresAuthenticationbooleanoptional
  • smartTapValuestringoptional
  • validityobjectPflicht
  • expirationDatedate-timeoptional
  • relevantDatedate-timeoptional
  • relevantDatesobject[]optional

    0–10 Einträge

  • startDatedate-timePflicht
  • endDatedate-timeoptional
  • voidedbooleanoptional
  • sharingProhibitedbooleanoptional
  • featuredActionsobject[]optional

    0–2 Einträge

  • labelstringPflicht

    1–40 Zeichen

  • urlurioptional
  • placeIdentifierstringoptional
  • typestringoptional
  • identifierstringoptional

    1–60 Zeichen

  • posterobjectoptional
  • enabledbooleanoptional
  • footerLabelstringoptional

    0–40 Zeichen

  • footerValuestringoptional

    0–80 Zeichen

  • fallbackStyle"generic" | "storeCard" | "coupon" | "eventTicket"optional
  • suppressHeaderDarkeningbooleanoptional
  • googleActionobjectoptional
  • labelstringPflicht

    1–30 Zeichen

  • urlstringPflicht

    1–2048 Zeichen

  • coverHintobjectoptional
  • enabledbooleanoptional
  • textstringoptional

    0–48 Zeichen

  • backgroundHexstringoptional
  • textHexstringoptional
  • personalImagesobjectoptional
  • stripobjectoptional
  • attributestringPflicht
  • logoobjectoptional
  • attributestringPflicht
  • appLinkobjectoptional
  • appStoreIdsinteger[]optional
  • launchUrlurioptional
  • backobjectoptional
  • linksobject[]optional
  • labelstringPflicht
  • urluriPflicht
  • textsobject[]optional
  • labelstringPflicht
  • valuestringPflicht
  • semanticsobjectoptional
  • localizationsobjectoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/preflight" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "walletDocument": {
    "useCase": "coupon",
    "identity": {
      "passType": "boardingPass",
      "googleClass": "loyalty"
    },
    "branding": {
      "backgroundHex": "text",
      "foregroundHex": "text",
      "labelHex": "Sommer-Aktion"
    },
    "fields": {
      "primary": [
        {
          "key": "text",
          "value": "text"
        }
      ]
    },
    "loyalty": {
      "pointsLabel": "Sommer-Aktion",
      "pointsBalance": 1
    },
    "giftCard": {
      "balance": 1,
      "currencyCode": "EUR"
    },
    "barcodes": [
      {
        "format": "PKBarcodeFormatQR",
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    ],
    "rotatingBarcode": {
      "totpKey": "text"
    },
    "images": {},
    "locations": [
      {
        "latitude": 1,
        "longitude": 1
      }
    ],
    "maxDistance": 10,
    "beacons": [
      {
        "proximityUuid": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
      }
    ],
    "nfc": {
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
    },
    "validity": {},
    "featuredActions": [
      {
        "label": "Sommer-Aktion"
      }
    ],
    "poster": {},
    "googleAction": {
      "label": "Sommer-Aktion",
      "url": "https://example.de/hook"
    },
    "coverHint": {},
    "personalImages": {},
    "appLink": {},
    "back": {},
    "semantics": {},
    "localizations": {}
  }
}'
Antwort200
{
  "ok": true,
  "contrastRatio": 1,
  "issues": [
    {
      "severity": "error",
      "code": "text",
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
    }
  ]
}
POST/v1/templates/{id}/contrast

Kontrast messen

Misst für Farben und Bilder, wie beide Wallets sie zeichnen: Vorder- und Beschriftungsfarbe auf der Hintergrundfarbe (Apple, ≥ 4,5:1 und ≥ 3:1), die Textfarbe, die Google Wallet auf dieser Kartenfarbe wählt, und das Logo (Apple-Kopfzeile, Google-Kreis) gegen die Kartenfarbe (≥ 3:1), samt Hinweis auf einen gefüllten Kasten um das Logo. Dieselben Hinweise wie die Prüfung vor dem Veröffentlichen.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • backgroundHexstringPflicht
  • foregroundHexstringPflicht
  • labelHexstringPflicht
  • logoAssetIduuid | nulloptional
  • googleLogoAssetIduuid | nulloptional
  • iconAssetIduuid | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/contrast" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "backgroundHex": "text",
  "foregroundHex": "text",
  "labelHex": "Sommer-Aktion",
  "logoAssetId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "googleLogoAssetId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "iconAssetId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}'
Antwort200
{
  "text": {
    "apple": {
      "foreground": 1,
      "label": 1
    },
    "google": {
      "color": "light",
      "hex": "text",
      "ratio": 1,
      "weak": true
    }
  },
  "logo": {
    "apple": {
      "assetId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "analysis": {
        "width": 1,
        "height": 1,
        "transparentShare": 1,
        "dominant": [
          {
            "hex": null,
            "share": null
          }
        ],
        "boxHex": "text"
      },
      "apple": {
        "backgroundHex": "text",
        "ratio": 1,
        "ok": true
      },
      "google": {
        "backgroundHex": "text",
        "ratio": 1,
        "ok": true
      },
      "opaqueBox": {
        "hex": "text",
        "ratioToBackground": 1
      }
    },
    "google": {
      "assetId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "analysis": {
        "width": 1,
        "height": 1,
        "transparentShare": 1,
        "dominant": [
          {
            "hex": null,
            "share": null
          }
        ],
        "boxHex": "text"
      },
      "apple": {
        "backgroundHex": "text",
        "ratio": 1,
        "ok": true
      },
      "google": {
        "backgroundHex": "text",
        "ratio": 1,
        "ok": true
      },
      "opaqueBox": {
        "hex": "text",
        "ratioToBackground": 1
      }
    }
  },
  "issues": [
    {
      "severity": "warning",
      "code": "text",
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss.",
      "path": "text"
    }
  ]
}
POST/v1/templates/{id}/versions/{version}/publish

Version veröffentlichen

Macht die Version zur aktiven; alle Pässe der Vorlage bekommen das neue Design und werden still an die Wallets gepusht.

Pfad-Parameter

  • iduuidPflicht
  • versionintegerPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/versions/{version}/publish" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "useCase": "coupon",
  "passType": "boardingPass",
  "googleClassType": "loyalty",
  "status": "draft",
  "folderId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "currentVersion": 1,
  "currentDraftVersion": 1,
  "valueSource": {
    "mode": "static",
    "value": "text"
  },
  "attributeSchema": [
    {
      "key": "text",
      "label": "Sommer-Aktion",
      "type": "text",
      "required": false,
      "fromPublicClaim": false
    }
  ],
  "organizationName": "Sommer-Aktion",
  "logoText": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "description": "Kurze Beschreibung",
  "eventStartsAt": "2026-09-15T10:32:00Z",
  "eventEndsAt": "2026-09-15T10:32:00Z",
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "publishedAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ]
}
POST/v1/templates/{id}/preview-pass

Vorschau-Pass aus dem Entwurf

Baut aus dem Entwurf der Vorlage (der Stand, den der Editor speichert, PUT /v1/templates/{id}/versions/draft; ohne Entwurf die neueste Version) einen signierten Apple-Pass zum Ansehen auf dem iPhone. Der Pass ist live: er trägt webServiceURL (das Apple-Wallet-Web-Service dieser API) und ein eigenes authenticationToken, Wallet registriert ihn, und 48 Stunden lang bringt jedes Speichern des Entwurfs (PUT …/versions/draft und jede andere Änderung an Entwurf oder Vorlage) ihn binnen etwa fünf Sekunden per Push auf den aktuellen Stand, mit den Beispielwerten vom Bau. Er läuft durch denselben Bau wie ein ausgestellter Pass (Farben, Bilder, Felder, Standorte, Zertifikat der Organisation oder der Plattform), ist aber kein Pass: keine Zeile, kein Kontingent, keine Webhooks und Ereignisse, Seriennummer preview-…, spätestens 48 Stunden nach dem Bau abgelaufen, nicht teilbar. Jeder Barcode behält Format und Platz, trägt aber einen festen Beispielwert (VORSCHAU-…, bei EAN-13, ITF und Codabar Nullen) mit Hinweis, NFC entfällt, und die Rückseite sagt in der Sprache des Arbeitsbereichs, dass es eine Vorschau ist. sampleValues füllt {{platzhalter}} wie die Beispielwerte im Editor (Schlüssel wie customerName oder attr.stadt, unbekannte werden ignoriert, Werte nach 500 Zeichen gekürzt; code, serial und passId gehören dem Vorschau-Pass). Fehlende Platzhalter wie bei einem neuen Pass. baseVersion und baseRevision wie bei PUT …/versions/draft (was das letzte Speichern geantwortet hat): passt der gespeicherte Stand nicht mehr, 409 conflict mit details.currentRevision. Der Editor speichert vorher, was noch aussteht. Antwort: die .pkpass-Datei als Anhang, dazu Kopfzeilen x-preview-serial (Seriennummer dieser Vorschau, wie in GET …/preview-passes) und x-preview-expires-at (Ende der Vorschau, ISO 8601). Nur mit Anmeldung im Browser (ein API-Token bekommt 403 session_required), ab der Rolle editor, nicht in einer Übernahme nur zum Lesen (403 impersonation_read_only); pausierte Organisation 423; 409 apple_credential_missing ohne nutzbares Apple-Zertifikat (details.reason), 422 preview_invalid mit details.issues (die Fehler der Prüfung vor dem Veröffentlichen), Ratenklasse preview_pass (30 je Stunde und Person) und höchstens 100 Vorschauen je Stunde und Organisation (429 rate_limited). Audit template.preview_pass.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • sampleValuesobjectoptional

    Beispielwerte für Platzhalter, Schlüssel ohne Klammern (customerName, attr.stadt).

  • baseVersionintegeroptional

    currentDraftVersion, die der Editor zuletzt gespeichert hat. · -∞ bis 9007199254740991

  • baseRevisiondate-timeoptional

    updatedAt der Version, die das letzte Speichern geantwortet hat.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/preview-pass" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "sampleValues": {},
  "baseVersion": 1,
  "baseRevision": "2026-09-15T10:32:00Z"
}'
Antwort200
"text"
POST/v1/templates/{id}/preview-pass/link

Link zum Vorschau-Pass fürs Handy

Baut wie POST /v1/templates/{id}/preview-pass einen Live-Vorschau-Pass aus dem Entwurf und gibt statt der Datei einen Link zurück, den das Handy ohne Anmeldung öffnet (GET /v1/preview-pass/{token}, etwa als QR-Code im Editor). Der Link gilt 15 Minuten und für höchstens 5 Downloads; jeder Download liefert denselben Vorschau-Pass (dieselbe serial), zweimal scannen ergibt also keinen zweiten Pass. Der Pass ist live: er trägt webServiceURL (das Apple-Wallet-Web-Service dieser API) und ein eigenes authenticationToken, Wallet registriert ihn, und 48 Stunden lang bringt jedes Speichern des Entwurfs (PUT …/versions/draft und jede andere Änderung an Entwurf oder Vorlage) ihn binnen etwa fünf Sekunden per Push auf den aktuellen Stand, mit den Beispielwerten vom Bau. 201: url (absolut), expiresAt (Ende des Links), passExpiresAt (Ende der Vorschau, 48 Stunden), serial. Body und Fehler wie beim Vorschau-Pass. Nur mit Anmeldung im Browser (ein API-Token bekommt 403 session_required), ab der Rolle editor, nicht in einer Übernahme nur zum Lesen (403 impersonation_read_only); pausierte Organisation 423; 409 apple_credential_missing ohne nutzbares Apple-Zertifikat (details.reason), 422 preview_invalid mit details.issues (die Fehler der Prüfung vor dem Veröffentlichen), Ratenklasse preview_pass (30 je Stunde und Person) und höchstens 100 Vorschauen je Stunde und Organisation (429 rate_limited). Audit template.preview_pass.link.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • sampleValuesobjectoptional

    Beispielwerte für Platzhalter, Schlüssel ohne Klammern (customerName, attr.stadt).

  • baseVersionintegeroptional

    currentDraftVersion, die der Editor zuletzt gespeichert hat. · -∞ bis 9007199254740991

  • baseRevisiondate-timeoptional

    updatedAt der Version, die das letzte Speichern geantwortet hat.

Antworten

  • 201Angelegt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/preview-pass/link" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "sampleValues": {},
  "baseVersion": 1,
  "baseRevision": "2026-09-15T10:32:00Z"
}'
Antwort201
{
  "url": "https://example.de/hook",
  "expiresAt": "2026-09-15T10:32:00Z",
  "passExpiresAt": "2026-09-15T10:32:00Z",
  "serial": "ABC123456"
}
GET/v1/preview-pass/{token}

Vorschau-Pass über den Link öffnen

Ohne Anmeldung: der Live-Vorschau-Pass hinter einem Link aus POST /v1/templates/{id}/preview-pass/link, neu gebaut aus dem aktuellen Entwurf, als .pkpass (Safari auf dem iPhone bietet „Zu Wallet hinzufügen“ an). Jeder Download desselben Links liefert denselben Pass (dieselbe Seriennummer). 404 not_found für einen unbekannten Token und sobald die Vorschau vorzeitig beendet, mit der Vorlage archiviert oder aufgeräumt ist (der Link geht mit ihr), 410 gone, wenn der Link abgelaufen oder aufgebraucht ist oder die Vorschau abgelaufen, aber noch nicht aufgeräumt, 429 rate_limited (Ratenklasse preview_link: je Link und je IP). Lässt sich der Entwurf gerade nicht bauen, kommen die Fehler des Baus (422 preview_invalid, 409 apple_credential_missing, 423) und der Download zählt nicht. HEAD prüft nur (dieselben Codes ohne Bau), baut nichts und zählt keinen Download. Bevorzugt Accept text/html vor application/json (Safari nach dem Scan des QR-Codes), kommen 404, 410 und 429 als kleine HTML-Seite mit demselben Status (ein Satz, was zu tun ist; Deutsch, Englisch oder Französisch nach Accept-Language, sonst Deutsch; Cache-Control: no-store, noindex, CSP ohne Skripte); API-Clients (application/json, */* oder ohne Accept) bekommen weiter den JSON-Umschlag.

Pfad-Parameter

  • tokenstringPflicht

Antworten

  • 200OK
  • 404Nicht gefunden
  • 409Konflikt
  • 410Nicht mehr gültig
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/preview-pass/{token}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
"text"
GET/v1/templates/{id}/preview-passes

Aktive Vorschau-Pässe einer Vorlage

Die Live-Vorschauen dieser Vorlage, die die angemeldete Person gebaut hat und die noch nicht abgelaufen sind (auch für Plattform-Admins nur die eigenen), neueste zuerst: serial, createdAt, expiresAt, devices (Geräte, die Wallet registriert hat) und lastUpdatedAt (letzter Push nach dem Speichern, sonst null). Der Editor zeigt daraus „Live auf 1 Gerät“. Nur mit Anmeldung im Browser (403 session_required für API-Tokens), ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/templates/{id}/preview-passes" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "items": [
    {
      "serial": "ABC123456",
      "createdAt": "2026-09-15T10:32:00Z",
      "expiresAt": "2026-09-15T10:32:00Z",
      "devices": 1,
      "lastUpdatedAt": "2026-09-15T10:32:00Z"
    }
  ]
}
DELETE/v1/templates/{id}/preview-passes/{serial}

Vorschau-Pass beenden

Beendet eine Live-Vorschau vor Ablauf der 48 Stunden: keine Updates mehr, registrierte Geräte und Links fallen weg (Wallet behält den letzten Stand, bis er abläuft). Nur wer sie gebaut hat oder ein Plattform-Admin (sonst 403 permission_denied); unbekannt oder schon abgelaufen 404. Nur mit Anmeldung im Browser (403 session_required für API-Tokens), ab der Rolle editor. Audit template.preview_pass.end.

Pfad-Parameter

  • iduuidPflicht
  • serialstringPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/templates/{id}/preview-passes/{serial}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
GET/v1/workspaces/{workspaceId}/template-folders

Ordner der Vorlagen auflisten

Flache Liste mit parentId; den Baum baut dein Client.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/template-folders" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "parentId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "color": "#005be7",
      "sortOrder": 1,
      "createdAt": "2026-09-15T10:32:00Z",
      "updatedAt": "2026-09-15T10:32:00Z"
    }
  ]
}
POST/v1/workspaces/{workspaceId}/template-folders

Ordner anlegen

Name, Farbe und optional ein Eltern-Ordner (parentId). Ab der Rolle editor.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–60 Zeichen

  • parentIduuid | nulloptional
  • color"brand" | string | nulloptional

Antworten

  • 201Angelegt
  • 400Ungültige Anfrage
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/template-folders" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "parentId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "color": "brand"
}'
Antwort201
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "parentId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "color": "#005be7",
  "sortOrder": 1,
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z"
}
PATCH/v1/template-folders/{id}

Ordner ändern

Name, Farbe, Reihenfolge oder Eltern-Ordner; parentId: null verschiebt ihn nach oben. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–60 Zeichen

  • parentIduuid | nulloptional
  • color"brand" | string | nulloptional
  • sortOrderintegeroptional

    -2147483648 bis 2147483647

Antworten

  • 200OK
  • 400Ungültige Anfrage
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/template-folders/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "parentId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "color": "brand",
  "sortOrder": 1
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "parentId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "color": "#005be7",
  "sortOrder": 1,
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z"
}
DELETE/v1/template-folders/{id}

Ordner löschen

Vorlagen und Unterordner rücken eine Ebene nach oben. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/template-folders/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
GET/v1/templates/{id}/locations

Standorte der Vorlage

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/templates/{id}/locations" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "role": "text",
      "isPrimary": true,
      "name": "Sommer-Aktion",
      "lat": 1,
      "lon": 1,
      "radiusM": 1
    }
  ]
}
POST/v1/templates/{id}/locations

Standort verknüpfen

Hängt einen Standort des Workspace an die Vorlage. Höchstens 10 je Vorlage (Apple): der elfte ist ein 409 location_limit mit details.max; ein schon angehängter Standort ist ein 409 conflict.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • locationIduuidPflicht
  • role"geofence" | "beacon"optional
  • isPrimarybooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/locations" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "role": "geofence",
  "isPrimary": false
}'
Antwort200
{
  "attached": true,
  "repushed": 1
}
DELETE/v1/templates/{id}/locations/{locationId}

Standort-Verknüpfung entfernen

Pfad-Parameter

  • iduuidPflicht
  • locationIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/templates/{id}/locations/{locationId}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "detached": true,
  "repushed": 1
}
GET/v1/templates/{id}/redemption-policy

Einlöse-Regel einer Vorlage lesen

mode: unlimited (beliebig oft), single (einmal), limited (bis maxCount-mal), daily (maxCount-mal je Kalendertag in der Zeitzone des Workspace, leer = einmal). voidAfterRedeem: die Nutzung, die die Regel ausschöpft, entwertet den Pass im Wallet. Eine Vorlage ohne gespeicherte Regel ist unbegrenzt (updatedAt: null). Jede Rolle im Workspace.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/templates/{id}/redemption-policy" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "mode": "unlimited",
  "maxCount": 1,
  "voidAfterRedeem": true,
  "updatedAt": "2026-09-15T10:32:00Z"
}
PUT/v1/templates/{id}/redemption-policy

Einlöse-Regel einer Vorlage setzen

Gilt sofort für jede folgende Nutzung aus jeder Quelle. maxCount ist Pflicht für limited (1 bis 10.000), optional für daily (1 bis 100, Vorgabe einmal am Tag) und sonst leer. voidAfterRedeem nur mit single oder limited. Nutzungen zählen mit Art redemption und checkin, nicht stamp. Editor-Rolle oder höher; Sitzung oder API-Token.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • mode"unlimited" | "single" | "limited" | "daily"Pflicht
  • maxCountinteger | nulloptional
  • voidAfterRedeembooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PUT "https://api.dowallet.dev/v1/templates/{id}/redemption-policy" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "mode": "unlimited",
  "maxCount": 1,
  "voidAfterRedeem": true
}'
Antwort200
{
  "mode": "unlimited",
  "maxCount": 1,
  "voidAfterRedeem": true,
  "updatedAt": "2026-09-15T10:32:00Z"
}
GET/v1/templates/{id}/loyalty-rules

Treue-Regel einer Vorlage lesen

kind stamps: goal Stempel ergeben die Prämie reward; afterReward sagt, was beim Einlösen passiert (carry: minus das Ziel, der Überhang bleibt; reset: die Karte startet bei 0), rewardType und rewardValue die Art und den Wert der Prämie, startStamps die Startstempel beim Ausstellen, dailyCap die Stempel je Karte und Tag, paused ob das Programm pausiert ist. kind points: earnPerEuro Punkte je Euro einer Nutzung mit Betrag (abgerundet), tiers die Stufen aufsteigend nach minPoints. kindLocked: die Art ist fest, weil es echte Buchungen gibt. Eine Vorlage ohne Regel antwortet 404 loyalty_rule_missing. Jede Rolle im Workspace; Token-Scope templates:read.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/templates/{id}/loyalty-rules" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "stamps",
  "goal": 1,
  "reward": "text",
  "earnPerEuro": 1,
  "tiers": [
    {
      "name": "Sommer-Aktion",
      "minPoints": 1
    }
  ],
  "afterReward": "carry",
  "rewardType": "item",
  "rewardValue": 1,
  "startStamps": 1,
  "dailyCap": 1,
  "paused": true,
  "pausedAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "kindLocked": true
}
PUT/v1/templates/{id}/loyalty-rules

Treue-Regel einer Vorlage speichern

Speichert das Programm einer Treuekarte (Zweck loyalty, sonst 422) ausdrücklich, ohne Autosave: gilt sofort für jede folgende Buchung aus jeder Quelle; die Vorlage muss nicht neu veröffentlicht werden. stamps: goal Pflicht (1 bis 100), reward optional (höchstens 60 Zeichen), afterReward carry | reset, rewardType item | percent (rewardValue 1 bis 100) | amount (rewardValue in Cent), startStamps 0 bis Ziel − 1, dailyCap 1 bis 100 oder null, paused true | false. Felder, die fehlen, behalten den gespeicherten Wert. points: goal, reward und die Programm-Einstellungen leer, earnPerEuro optional (bis 1.000, zwei Nachkommastellen), tiers optional (bis 10, aufsteigend nach minPoints, Namen bis 30 Zeichen). Sonst 422 mit fields. baseUpdatedAt: das updatedAt, das der Editor geladen hat; wurde die Regel inzwischen geändert, 409 conflict mit details.currentUpdatedAt. Die Art ändert sich nicht mehr, sobald es echte Buchungen gibt (409 loyalty_kind_locked). Ein niedrigeres Ziel legt für jeden Pass, der es jetzt erreicht, eine offene Prämie an (createdRewards); erreichte Prämien behalten ihre Bedingungen. „Prämie bereit“ dazu geht nicht sofort aus der Anfrage, sondern als Hintergrundjob ab rewardMessagesAt (sofort, zwischen 20 und 9 Uhr Europe/Berlin ab 9 Uhr, große Programme in Abschnitten). Ändern Ziel, Prämie, Stufen oder Art die Anzeige, laden die Pässe neu (still). Editor-Rolle oder höher; Sitzung oder Token mit templates:write. Audit template.loyalty_rules.update. Ohne das Modul Treue der Organisation 403 module_disabled.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • kind"stamps" | "points"Pflicht
  • goalinteger | nulloptional
  • rewardstring | nulloptional
  • earnPerEuronumber | nulloptional
  • tiersobject[]optional

    0–10 Einträge

  • namestringPflicht

    1–30 Zeichen

  • minPointsintegerPflicht

    0 bis 100000000

  • afterReward"carry" | "reset"optional
  • rewardType"item" | "percent" | "amount"optional
  • rewardValueinteger | nulloptional
  • startStampsintegeroptional

    0 bis 99

  • dailyCapinteger | nulloptional
  • pausedbooleanoptional
  • baseUpdatedAtdate-timeoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PUT "https://api.dowallet.dev/v1/templates/{id}/loyalty-rules" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "kind": "stamps",
  "goal": 1,
  "reward": "text",
  "earnPerEuro": 1,
  "tiers": [
    {
      "name": "Sommer-Aktion",
      "minPoints": 1
    }
  ],
  "afterReward": "carry",
  "rewardType": "item",
  "rewardValue": 1,
  "startStamps": 1,
  "dailyCap": 1,
  "paused": true,
  "baseUpdatedAt": "2026-09-15T10:32:00Z"
}'
Antwort200
{
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "stamps",
  "goal": 1,
  "reward": "text",
  "earnPerEuro": 1,
  "tiers": [
    {
      "name": "Sommer-Aktion",
      "minPoints": 1
    }
  ],
  "afterReward": "carry",
  "rewardType": "item",
  "rewardValue": 1,
  "startStamps": 1,
  "dailyCap": 1,
  "paused": true,
  "pausedAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "kindLocked": true,
  "createdRewards": 1,
  "rewardMessagesAt": "2026-09-15T10:32:00Z"
}
DELETE/v1/templates/{id}/loyalty-rules

Treue-Programm entfernen

Entfernt das Programm einer Vorlage, solange es keine echten Daten hat: Buchungen, Mitglieder mit Stand und Prämien zählen nur auf echten Pässen (nicht Test, nicht intern) und ohne Demo-Stempel. Sonst 409 loyalty_rule_in_use mit details.bookings, details.members, details.rewards; das Programm lässt sich dann pausieren. Danach steht jeder Pass der Vorlage auf Stand 0 ohne Stufe, Verlauf und Prämien des Programms sind gelöscht, die Pässe laden neu. Antwort 204. Editor-Rolle oder höher; Token-Scope templates:write. Audit template.loyalty_rule_delete.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/templates/{id}/loyalty-rules" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/templates/{id}/loyalty-rules/preview

Änderung der Treue-Regel vorab prüfen

Derselbe Body wie PUT …/loyalty-rules, gespeichert wird nichts. Antwort: members (echte, aktive Mitglieder), rewardReadyNow und rewardReadyAfter (Mitglieder mit offener Prämie jetzt und nach der Änderung), newRewards und newRewardsMembers (Pässe, die sofort eine Prämie bekämen, alle und nur Mitglieder), passesRepushed (Pässe, die neu laden), kindLocked. Für den Hinweis im Editor: „Mit 8 statt 10 Stempeln hätten 70 Mitglieder sofort eine Prämie.“ Ungültige Werte 422 wie beim Speichern. Editor-Rolle oder höher; Token-Scope templates:write. Ohne das Modul Treue 403 module_disabled.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • kind"stamps" | "points"Pflicht
  • goalinteger | nulloptional
  • rewardstring | nulloptional
  • earnPerEuronumber | nulloptional
  • tiersobject[]optional

    0–10 Einträge

  • namestringPflicht

    1–30 Zeichen

  • minPointsintegerPflicht

    0 bis 100000000

  • afterReward"carry" | "reset"optional
  • rewardType"item" | "percent" | "amount"optional
  • rewardValueinteger | nulloptional
  • startStampsintegeroptional

    0 bis 99

  • dailyCapinteger | nulloptional
  • pausedbooleanoptional
  • baseUpdatedAtdate-timeoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/loyalty-rules/preview" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "kind": "stamps",
  "goal": 1,
  "reward": "text",
  "earnPerEuro": 1,
  "tiers": [
    {
      "name": "Sommer-Aktion",
      "minPoints": 1
    }
  ],
  "afterReward": "carry",
  "rewardType": "item",
  "rewardValue": 1,
  "startStamps": 1,
  "dailyCap": 1,
  "paused": true,
  "baseUpdatedAt": "2026-09-15T10:32:00Z"
}'
Antwort200
{
  "members": 1,
  "rewardReadyNow": 1,
  "rewardReadyAfter": 1,
  "newRewards": 1,
  "newRewardsMembers": 1,
  "passesRepushed": 1,
  "kindLocked": true
}
GET/v1/workspaces/{workspaceId}/loyalty/programs

Treue-Programme eines Workspace

Jedes Programm (die Treue-Regel einer Vorlage) mit Vorlagenname, Zustand der Vorlage (archivierte zuletzt, „Programm entfernen“ geht auch dort), members (echte, aktive Mitglieder), openRewards mit Wert in Cent (Art item und amount) und nearGoal (Mitglieder kurz vor der Prämie). templatesWithoutProgram: Treuekarten ohne Programm (nicht archiviert), für „Programm anlegen“. Jede Rolle im Workspace; Token-Scope templates:read. Ohne das Modul Treue 403 module_disabled.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/loyalty/programs" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "kind": "stamps",
      "goal": 1,
      "reward": "text",
      "earnPerEuro": 1,
      "tiers": [
        {
          "name": "Sommer-Aktion",
          "minPoints": 1
        }
      ],
      "afterReward": "carry",
      "rewardType": "item",
      "rewardValue": 1,
      "startStamps": 1,
      "dailyCap": 1,
      "paused": true,
      "pausedAt": "2026-09-15T10:32:00Z",
      "updatedAt": "2026-09-15T10:32:00Z",
      "name": "Sommer-Aktion",
      "templateStatus": "draft",
      "archived": true,
      "members": 1,
      "openRewards": 1,
      "openRewardsValueCents": 1,
      "nearGoal": 1
    }
  ],
  "templatesWithoutProgram": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "status": "active"
    }
  ]
}
GET/v1/templates/{id}/loyalty-automations

Treue-Automatik einer Vorlage lesen

Die automatischen Nachrichten eines Stempel-Programms: near_goal („Fast geschafft“, Vorgabe aus, params.stampsLeft 1 bis 5) und reward_ready („Prämie bereit“, Vorgabe an, Text wie bisher „Prämie verfügbar: …“). Je Fall: enabled, der Text, der rausgeht (message, eigener Text oder die Vorgabe in der Sprache des Arbeitsbereichs, isDefault), sample mit den Werten des Programms, lockScreenFits (höchstens 90 Zeichen) und die Zahlen der letzten 30 Tage. Höchstens eine Treue-Nachricht je Karte und Tag (außer „Prämie bereit“), höchstens 3 sichtbare Nachrichten je Karte in 24 Stunden. Jede Rolle im Workspace; Token-Scope templates:read. Ohne Treue-Modul 403 module_disabled, ohne Treue-Regel 404 loyalty_rule_missing.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/templates/{id}/loyalty-automations" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "available": true,
  "tokens": [
    "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx"
  ],
  "limits": {
    "messageMax": 1,
    "lockScreenMax": 1,
    "perDay": 1,
    "per24h": 1,
    "quietHours": {
      "from": "text",
      "to": "text",
      "timeZone": "Europe/Berlin"
    }
  },
  "items": [
    {
      "key": "near_goal",
      "enabled": true,
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss.",
      "isDefault": true,
      "defaultMessage": "Heute 20 % auf alles. Nur bis Ladenschluss.",
      "params": {},
      "sample": "text",
      "lockScreenFits": true,
      "capExempt": true,
      "updatedAt": "2026-09-15T10:32:00Z",
      "stats": {
        "sent30d": 1,
        "skipped30d": 1
      }
    }
  ]
}
PUT/v1/templates/{id}/loyalty-automations

Treue-Automatik einer Vorlage speichern

Speichert die genannten Fälle (items, je key höchstens einmal); ein weggelassenes Feld behält seinen Wert. message: eigener Text (1 bis 160 Zeichen, gilt für alle Sprachen) oder null für die Vorgabe in der Sprache der Karte. Erlaubte Platzhalter: {{stampsLeft}}, {{loyaltyReward}}, {{pointsBalance}}, {{loyaltyGoal}}; ein anderer ist 422 mit fields. near_goal.params.stampsLeft (1 bis 5): die Nachricht kommt, sobald noch so viele Stempel oder weniger fehlen, einmal je Runde. Nur für Stempel-Programme (sonst 422). Editor-Rolle oder höher; Sitzung oder Token mit templates:write. Audit template.loyalty_automation_update.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • itemsobject[]Pflicht

    1–2 Einträge

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PUT "https://api.dowallet.dev/v1/templates/{id}/loyalty-automations" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "items": [
    {
      "key": "near_goal"
    }
  ]
}'
Antwort200
{
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "available": true,
  "tokens": [
    "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx"
  ],
  "limits": {
    "messageMax": 1,
    "lockScreenMax": 1,
    "perDay": 1,
    "per24h": 1,
    "quietHours": {
      "from": "text",
      "to": "text",
      "timeZone": "Europe/Berlin"
    }
  },
  "items": [
    {
      "key": "near_goal",
      "enabled": true,
      "message": "Heute 20 % auf alles. Nur bis Ladenschluss.",
      "isDefault": true,
      "defaultMessage": "Heute 20 % auf alles. Nur bis Ladenschluss.",
      "params": {},
      "sample": "text",
      "lockScreenFits": true,
      "capExempt": true,
      "updatedAt": "2026-09-15T10:32:00Z",
      "stats": {
        "sent30d": 1,
        "skipped30d": 1
      }
    }
  ]
}
POST/v1/templates/{id}/loyalty-automations/test-send

Treue-Nachricht an einen Test-Pass senden

Schickt die Nachricht eines Falls (key) sofort an einen Test- oder Demo-Pass dieser Vorlage (passId), mit dem Stand dieses Passes in den Platzhaltern. message probiert einen noch nicht gespeicherten Text aus; ohne ihn geht der gespeicherte Text oder die Vorgabe raus. Die Grenzen je Karte und das Push-Kontingent gelten für den Test nicht. Wie jede Erinnerung nur zwischen 9 und 20 Uhr (Europe/Berlin); in der Ruhezeit 409 mit details.retryAt. Nur für Stempel-Programme. Editor-Rolle oder höher; Sitzung oder Token mit templates:write. Höchstens 5 Tests je Minute.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • key"near_goal" | "reward_ready"Pflicht
  • passIduuidPflicht
  • messagestringoptional

    1–160 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/templates/{id}/loyalty-automations/test-send" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "key": "near_goal",
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
}'
Antwort200
{
  "sent": true,
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
}

Kampagnen

Kampagnen: Push, stille Aktualisierung, Pass ersetzen, Empfänger und Protokoll.

GET/v1/workspaces/{workspaceId}/campaigns

Kampagnen auflisten

Kampagnen eines Workspace, neueste zuerst. metrics trägt den zuletzt berechneten Funnel (sent / delivered / failed / skipped / opened / redeemed), notify den Versandmodus (push | silent). promotionId filtert nach Aktion (none = ohne).

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • promotionIdstringoptional

    Nur Teile dieser Aktion; none = ohne Aktion.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/campaigns?promotionId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "groupName": "Sommer-Aktion",
      "status": "draft",
      "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "audience": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "name": "Sommer-Aktion",
        "filter": null
      },
      "onlyActive": true,
      "audienceCount": 1,
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "notification": null,
      "metrics": {},
      "locationIds": [
        "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
      ],
      "replace": {
        "targetTemplateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
      },
      "pace": "fast",
      "notify": "push",
      "scheduleAt": "2026-09-15T10:32:00Z",
      "publishedAt": "2026-09-15T10:32:00Z",
      "pausedAt": "2026-09-15T10:32:00Z",
      "cancelledAt": "2026-09-15T10:32:00Z",
      "completedAt": "2026-09-15T10:32:00Z",
      "endsAt": "2026-09-15T10:32:00Z",
      "costCents": 1,
      "createdAt": "2026-09-15T10:32:00Z",
      "approvalState": "none",
      "approvalRequired": true
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/campaigns

Kampagne anlegen

Legt eine Kampagne an (Entwurf, oder geplant wenn scheduleAt gesetzt ist). Die Vorlage muss veröffentlicht sein (sonst 422 template_not_published). Empfänger: gespeicherte Zielgruppe (audienceId) oder eigener Filter (audienceFilter), nicht beides; ohne beides alle aktiven Pässe der Vorlage. locationIds nur aus den Standorten der Vorlage, höchstens 10. notify: "silent" setzt replace voraus (sonst 422 auf dem Feld notify) und macht notification.text optional. endsAt ist das geplante Ende für den Kampagnenplan, nur Planung und Anzeige; mit scheduleAt muss es danach liegen (sonst 422, fields.endsAt = ["ends_at_before_start"]).

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–160 Zeichen

  • templateIduuidPflicht
  • groupNamestring | nulloptional

    Kampagnen-Gruppe (höchstens 80 Zeichen). Kampagnen derselben Gruppe stehen in der Liste zusammen; leer oder null = keine Gruppe.

  • promotionIduuid | nulloptional

    Aktion, zu der das Teil gehört (GET /v1/workspaces/{id}/promotions); null = ohne Aktion. Fremde Aktion 404 promotion_not_found, archivierte 409 promotion_archived.

  • audienceIduuid | nulloptional
  • audienceFilterobjectoptional

    Eigener Filter statt einer gespeicherten Zielgruppe, gleiche Sprache wie audiences.filter. Nicht zusammen mit audienceId. Ohne beides: alle aktiven Pässe der Vorlage.

  • notificationobjectoptional
  • textstringoptional
  • localesobjectoptional
  • scheduleAtdate-time | nulloptional
  • endsAtdate-time | nulloptional

    Geplantes Ende der Kampagne (Laufzeit im Kampagnenplan), nur für Planung und Anzeige: beim Erreichen wird nichts gesendet, gestoppt oder beendet. Muss nach scheduleAt liegen, wenn beide gesetzt sind, und nach dem Versand (publishedAt), wenn die Kampagne schon gesendet hat; sonst 422 mit fields.endsAt = ["ends_at_before_start"]. Wurde eine geplante Kampagne früher gesendet, bleibt scheduleAt stehen: das Ende liegt dann auch nach dem geplanten Versandzeitpunkt. null entfernt das Ende.

  • costCentsinteger | nulloptional
  • locationIdsuuid[]optional

    Standorte der Vorlage (höchstens 10), an denen der Kampagnentext auf dem Sperrbildschirm erscheint. Leer = alle Standorte der Vorlage wie gewohnt. · 0–10 Einträge

  • replaceobject | nulloptional
  • targetTemplateIduuidPflicht
  • codePoolIduuid | nulloptional
  • pace"fast" | "gentle"optional
  • notify"push" | "silent"optional

    Delivery mode. "push" appends notification.text to every targeted pass (lock-screen banner on Apple, addMessage on Google). "silent" refreshes the pass content without any message (requires replace); notification.text may be omitted.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/campaigns" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "groupName": "Sommer-Aktion",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audienceFilter": null,
  "notification": {
    "text": "Heute 20 % auf alles. Nur bis Ladenschluss.",
    "locales": {}
  },
  "scheduleAt": "2026-09-15T10:32:00Z",
  "endsAt": "2026-09-15T10:32:00Z",
  "costCents": 1,
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "replace": {
    "targetTemplateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "pace": "fast",
  "notify": "push"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "groupName": "Sommer-Aktion",
  "status": "draft",
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audience": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "name": "Sommer-Aktion",
    "filter": null
  },
  "onlyActive": true,
  "audienceCount": 1,
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "notification": null,
  "metrics": {
    "sent": 1,
    "delivered": 1,
    "failed": 1,
    "skipped": 1,
    "pending": 1,
    "opened": 1,
    "redeemed": 1,
    "deliveredApple": 1,
    "deliveredGoogle": 1,
    "replaced": 1,
    "codesAllocated": 1,
    "refreshedAt": "text"
  },
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "replace": {
    "targetTemplateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "pace": "fast",
  "notify": "push",
  "scheduleAt": "2026-09-15T10:32:00Z",
  "publishedAt": "2026-09-15T10:32:00Z",
  "pausedAt": "2026-09-15T10:32:00Z",
  "cancelledAt": "2026-09-15T10:32:00Z",
  "completedAt": "2026-09-15T10:32:00Z",
  "endsAt": "2026-09-15T10:32:00Z",
  "costCents": 1,
  "createdAt": "2026-09-15T10:32:00Z",
  "approvalState": "none",
  "approvalRequired": true
}
GET/v1/campaigns/{id}

Kampagne mit Kennzahlen und Versand-Protokoll lesen

Eine Kampagne mit ihrem Versand-Protokoll (sendLog, die letzten 50 Zustellzeilen, neueste zuerst), ihrer Zielgruppe (audience: gespeicherte Zielgruppe mit Name und Filter oder der eigene Filter), onlyActive, groupName und locationIds. metrics.delivered / failed / skipped / opened / redeemed werden bei jedem Lesen aus denselben Ereignissen neu berechnet (delivered = auf Apple oder Google erreichte Pässe, pro Pass einmal gezählt) und in die Kampagne zurückgeschrieben, damit Liste und Detail übereinstimmen.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/campaigns/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "groupName": "Sommer-Aktion",
  "status": "draft",
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audience": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "name": "Sommer-Aktion",
    "filter": null
  },
  "onlyActive": true,
  "audienceCount": 1,
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "notification": null,
  "metrics": {
    "sent": 1,
    "delivered": 1,
    "failed": 1,
    "skipped": 1,
    "pending": 1,
    "opened": 1,
    "redeemed": 1,
    "deliveredApple": 1,
    "deliveredGoogle": 1,
    "replaced": 1,
    "codesAllocated": 1,
    "refreshedAt": "text"
  },
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "replace": {
    "targetTemplateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "pace": "fast",
  "notify": "push",
  "scheduleAt": "2026-09-15T10:32:00Z",
  "publishedAt": "2026-09-15T10:32:00Z",
  "pausedAt": "2026-09-15T10:32:00Z",
  "cancelledAt": "2026-09-15T10:32:00Z",
  "completedAt": "2026-09-15T10:32:00Z",
  "endsAt": "2026-09-15T10:32:00Z",
  "costCents": 1,
  "createdAt": "2026-09-15T10:32:00Z",
  "approvalState": "none",
  "approvalRequired": true,
  "sendLog": [
    {
      "at": "2026-09-15T10:32:00Z",
      "kind": "apple",
      "ok": 1,
      "failed": 1,
      "skipped": 1,
      "reason": "text",
      "notify": "push"
    }
  ]
}
PATCH/v1/campaigns/{id}

Kampagne bearbeiten (Entwurf oder geplant)

Ändert eine Kampagne im Entwurf oder im geplanten Zustand. Die entstehende Kombination muss gültig sein: notify: "silent" ohne replace (mitgesendet oder bereits gespeichert) ist ein 422 auf dem Feld notify; audienceId und audienceFilter zusammen sind ein 422 (zum Wechseln das andere Feld auf null setzen); locationIds nur aus den Standorten der Vorlage. Freigabe: ändert der Aufruf Nachricht, Zielgruppe, Standorte, Versandart oder die Ziel-Vorlage (Wert anders als gespeichert), fällt approvalState auf none zurück und der Verlauf bekommt einen Eintrag. Name, Gruppe, Versandtempo und scheduleAt lassen die Freigabe stehen, Planen und Umplanen nach der Freigabe also auch. endsAt (geplantes Ende für den Kampagnenplan, nur Planung und Anzeige) lässt die Freigabe ebenfalls stehen und muss nach scheduleAt liegen, nach dem Aufruf und mit dem gespeicherten Wert gerechnet (sonst 422, fields.endsAt = ["ends_at_before_start"]). Ein Body nur mit endsAt ändert auch eine laufende, pausierte oder abgeschlossene Kampagne (dort muss es nach publishedAt und nach scheduleAt liegen, auch wenn sie früher gesendet wurde); jede andere Änderung an ihr ist 409. Eine abgebrochene Kampagne bleibt gesperrt (409).

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–160 Zeichen

  • groupNamestring | nulloptional

    Kampagnen-Gruppe (höchstens 80 Zeichen). Kampagnen derselben Gruppe stehen in der Liste zusammen; leer oder null = keine Gruppe.

  • promotionIduuid | nulloptional

    Aktion, zu der das Teil gehört (GET /v1/workspaces/{id}/promotions); null = ohne Aktion. Fremde Aktion 404 promotion_not_found, archivierte 409 promotion_archived.

  • audienceIduuid | nulloptional
  • audienceFilterobjectoptional

    Eigener Filter statt einer gespeicherten Zielgruppe, gleiche Sprache wie audiences.filter. Nicht zusammen mit audienceId. Ohne beides: alle aktiven Pässe der Vorlage.

  • notificationobjectoptional
  • textstringoptional
  • localesobjectoptional
  • scheduleAtdate-time | nulloptional
  • endsAtdate-time | nulloptional

    Geplantes Ende der Kampagne (Laufzeit im Kampagnenplan), nur für Planung und Anzeige: beim Erreichen wird nichts gesendet, gestoppt oder beendet. Muss nach scheduleAt liegen, wenn beide gesetzt sind, und nach dem Versand (publishedAt), wenn die Kampagne schon gesendet hat; sonst 422 mit fields.endsAt = ["ends_at_before_start"]. Wurde eine geplante Kampagne früher gesendet, bleibt scheduleAt stehen: das Ende liegt dann auch nach dem geplanten Versandzeitpunkt. null entfernt das Ende.

  • costCentsinteger | nulloptional
  • locationIdsuuid[] | nulloptional
  • replaceobject | nulloptional
  • targetTemplateIduuidPflicht
  • codePoolIduuid | nulloptional
  • pace"fast" | "gentle"optional
  • notify"push" | "silent"optional

    Delivery mode. "push" appends notification.text to every targeted pass (lock-screen banner on Apple, addMessage on Google). "silent" refreshes the pass content without any message (requires replace); notification.text may be omitted.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/campaigns/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "groupName": "Sommer-Aktion",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audienceFilter": null,
  "notification": {
    "text": "Heute 20 % auf alles. Nur bis Ladenschluss.",
    "locales": {}
  },
  "scheduleAt": "2026-09-15T10:32:00Z",
  "endsAt": "2026-09-15T10:32:00Z",
  "costCents": 1,
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "replace": {
    "targetTemplateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "pace": "fast",
  "notify": "push"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "groupName": "Sommer-Aktion",
  "status": "draft",
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audience": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "name": "Sommer-Aktion",
    "filter": null
  },
  "onlyActive": true,
  "audienceCount": 1,
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "notification": null,
  "metrics": {
    "sent": 1,
    "delivered": 1,
    "failed": 1,
    "skipped": 1,
    "pending": 1,
    "opened": 1,
    "redeemed": 1,
    "deliveredApple": 1,
    "deliveredGoogle": 1,
    "replaced": 1,
    "codesAllocated": 1,
    "refreshedAt": "text"
  },
  "locationIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "replace": {
    "targetTemplateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "pace": "fast",
  "notify": "push",
  "scheduleAt": "2026-09-15T10:32:00Z",
  "publishedAt": "2026-09-15T10:32:00Z",
  "pausedAt": "2026-09-15T10:32:00Z",
  "cancelledAt": "2026-09-15T10:32:00Z",
  "completedAt": "2026-09-15T10:32:00Z",
  "endsAt": "2026-09-15T10:32:00Z",
  "costCents": 1,
  "createdAt": "2026-09-15T10:32:00Z",
  "approvalState": "none",
  "approvalRequired": true
}
GET/v1/campaigns/{id}/recipients

Empfänger mit Zustell-Ergebnis

Adressierte Pässe einer Kampagne mit ihrem Ergebnis pro Pass, aus denselben Zustellereignissen wie das Versand-Protokoll. outcome: confirmed = Gerät hat die Aktualisierung geholt, delivered = von APNs oder Google angenommen, failed, skipped (mit reason), pending = noch kein Ergebnis. counts gilt immer für alle Empfänger, total und pagination für die Auswahl aus filter und q. Seitenweise mit cursor (aus pagination.nextCursor) oder offset. Name und E-Mail stehen nur mit Einwilligung des Pass-Inhabers in der Antwort und nur ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Query-Parameter

  • filterconfirmed | delivered | failed | skipped | pending | redeemed | alloptional

    Ergebnis-Filter: confirmed, delivered, failed, skipped, pending, redeemed oder all (Standard).

  • outcomeconfirmed | delivered | failed | skipped | pending | redeemed | alloptional

    Älterer Name für filter; filter hat Vorrang.

  • qstringoptional

    Suche in der Seriennummer, ab der Rolle editor auch in Name und E-Mail.

  • cursorstringoptional

    Aus pagination.nextCursor der vorigen Seite; ersetzt offset.

  • limitintegeroptional
  • offsetintegeroptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/campaigns/{id}/recipients?filter=confirmed&outcome=confirmed&q=sommer" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "serial": "ABC123456",
      "platform": "text",
      "status": "active",
      "isTest": true,
      "outcome": "confirmed",
      "reason": "text",
      "apple": {
        "outcome": "confirmed",
        "reason": "text"
      },
      "google": {
        "outcome": "confirmed",
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss.",
        "reason": "text"
      },
      "redeemed": true,
      "redeemedAt": "2026-09-15T10:32:00Z",
      "locationName": "Sommer-Aktion",
      "lastEventAt": "text",
      "customerName": "Sommer-Aktion",
      "customerEmail": "kunde@example.de"
    }
  ],
  "total": 1,
  "counts": {
    "all": 1,
    "confirmed": 1,
    "delivered": 1,
    "failed": 1,
    "skipped": 1,
    "pending": 1,
    "redeemed": 1
  },
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
GET/v1/campaigns/{id}/recipients.csv

Empfänger als CSV exportieren

Alle adressierten Pässe der Kampagne mit Ergebnis, letzter Nutzung (Zeitpunkt und Filiale) und, mit Einwilligung des Pass-Inhabers, Name und E-Mail. filter und q wie bei GET /v1/campaigns/{id}/recipients, ohne Seiten. Semikolon als Trennzeichen, UTF-8 mit BOM und CRLF, damit ein deutsches Excel die Spalten richtig öffnet; Zellen, die mit = + - @ beginnen, bekommen ein vorangestelltes Apostroph und bleiben Text. Ab der Rolle editor, jeder Export steht mit Anzahl und Auswahl im Audit-Log (campaign.recipients_export).

Pfad-Parameter

  • iduuidPflicht

Query-Parameter

  • filterconfirmed | delivered | failed | skipped | pending | redeemed | alloptional

    Ergebnis-Filter: confirmed, delivered, failed, skipped, pending, redeemed oder all (Standard).

  • outcomeconfirmed | delivered | failed | skipped | pending | redeemed | alloptional

    Älterer Name für filter; filter hat Vorrang.

  • qstringoptional

    Suche in der Seriennummer, ab der Rolle editor auch in Name und E-Mail.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/campaigns/{id}/recipients.csv?filter=confirmed&outcome=confirmed&q=sommer" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
"text"
POST/v1/campaigns/{id}/publish

Kampagne veröffentlichen oder planen

Friert die Zielgruppe ein (jeder Pass eine Zeile, ohne Obergrenze) und startet den Versand in Stapeln à 100 Pässen: „fast“ alle Stapel sofort, „gentle“ ein Stapel pro Minute. Jeder Stapel prüft vorher den Status: Pausieren hält den nächsten Stapel an, Fortsetzen plant die offenen Stapel neu ein, Beenden überspringt den Rest. Push-Kampagnen schreiben notification.text auf jeden Pass, wenn sein Stapel dran ist. Stille Kampagnen tauschen nur den Inhalt (replace) und lassen die Wallets aktualisieren, ohne Nachricht und ohne Benachrichtigung. Eine geplante Kampagne sendet zum geplanten Zeitpunkt von selbst; vorher antwortet diese Route mit 409 scheduled_in_future, außer mit now=true. Verlangt der Arbeitsbereich eine Freigabe (approvalRequired) und ist approvalState nicht approved, antwortet sie mit 409 approval_required; das gilt genauso für die geplante Ausführung, die eine solche Kampagne einmal in den Entwurf zurücksetzt.

Pfad-Parameter

  • iduuidPflicht

Query-Parameter

  • now0 | 1 | true | falseoptional

    true = eine geplante Kampagne jetzt sofort senden statt zum geplanten Zeitpunkt.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/campaigns/{id}/publish?now=0" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "enqueued": 1,
  "audienceCount": 1
}
POST/v1/campaigns/{id}/pause

Kampagne pausieren

Hält den Versand an: kein weiterer Stapel geht raus, bereits übergebene Stapel laufen zu Ende. Nur für laufende Kampagnen (sonst 409).

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/campaigns/{id}/pause" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/campaigns/{id}/resume

Kampagne fortsetzen

Setzt eine pausierte Kampagne fort. Wirkt mit dem nächsten Stapel: die offenen Stapel werden neu eingeplant, bei „fast“ sofort, bei „gentle“ weiter ein Stapel pro Minute (der erste eine Minute nach dem letzten gesendeten). Nur für pausierte Kampagnen (sonst 409).

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/campaigns/{id}/resume" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/campaigns/{id}/cancel

Kampagne abbrechen

Beendet eine Kampagne endgültig: alle Pässe, deren Stapel noch nicht raus ist, werden übersprungen.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/campaigns/{id}/cancel" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
GET/v1/workspaces/{workspaceId}/plan

Kampagnenplan lesen

Kampagnen und aktive oder pausierte Automatisierungen des Workspace als Zeitstrahl, sortiert nach start (ohne start zuletzt), dann nach Name. from/to: Kalendertage (YYYY-MM-DD) in Europe/Berlin, from ab Tagesbeginn, to bis Tagesende. Vorgabe: sechs Wochen, Montag der Woche vor zwei Wochen bis Sonntag der Woche in drei Wochen; fehlt nur eines, gilt für das andere dieselbe Länge von sechs Wochen. Jahre 2000 bis 2100. Höchstens 366 Tage, from nicht nach to (sonst 422 validation_failed). Ein Eintrag steht im Plan, wenn er den Zeitraum berührt: Kampagne von publishedAt (sonst scheduleAt) bis endsAt (sonst bei completed oder cancelled bis completedAt bzw. cancelledAt, sonst offen), Automatisierung von activatedAt bis pausedAt (aktiv: offen). Ein Entwurf zählt nur an seinen Tagen (scheduleAt, endsAt), ein Entwurf ohne beide fehlt, archivierte Automatisierungen fehlen. endsAt ist nur Planung und Anzeige: beim Erreichen wird nichts gesendet oder gestoppt. summary zählt die Einträge des Zeitraums. Jede Rolle im Workspace; Token-Scope campaigns:read.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • fromstringoptional

    Erster Tag des Zeitraums (YYYY-MM-DD, Europe/Berlin, ab Tagesbeginn, Jahr 2000 bis 2100). Vorgabe: Montag der Woche vor zwei Wochen.

  • tostringoptional

    Letzter Tag des Zeitraums (YYYY-MM-DD, Europe/Berlin, bis Tagesende, Jahr 2000 bis 2100). Vorgabe: Sonntag der Woche in drei Wochen (sechs Wochen ab from). Höchstens 366 Tage ab from (sonst 422).

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/plan?from=text&to=text" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "from": "text",
  "to": "text",
  "timezone": "Europe/Berlin",
  "summary": {
    "campaigns": 1,
    "running": 1,
    "scheduled": 1,
    "flowsActive": 1
  },
  "items": [
    {
      "kind": "campaign",
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "status": "draft",
      "start": "2026-09-15T10:32:00Z",
      "end": "2026-09-15T10:32:00Z",
      "openEnded": true,
      "planned": true,
      "templates": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "name": "Sommer-Aktion",
          "background": "text",
          "foreground": "text",
          "logoUrl": "https://example.de/hook"
        }
      ],
      "audienceName": "Sommer-Aktion",
      "recipients": 1,
      "metrics": {
        "sent": 1,
        "redemptions": 1
      },
      "href": "text"
    }
  ]
}
POST/v1/campaigns/{id}/request-review

Kampagne zur Freigabe senden

Setzt approvalState auf in_review und schreibt die Anfrage mit optionalem Kommentar (höchstens 2000 Zeichen) in den Verlauf. Jede Person, die im Arbeitsbereich freigeben darf, bekommt eine Mail mit Direktlink, außer der anfragenden. Ab der Rolle editor, nur für Entwürfe und geplante Kampagnen, aus none oder changes_requested (sonst 409 conflict).

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • commentstring | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/campaigns/{id}/request-review" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Antwort200
{
  "approvalState": "none",
  "notified": 1
}
POST/v1/campaigns/{id}/approve

Kampagne freigeben

Gibt eine Kampagne in in_review frei (approvalState approved), optional mit Kommentar. Danach geht „Senden“ oder „Planen“; eine geplante Kampagne sendet zu ihrer Zeit. Nur wer im Arbeitsbereich freigeben darf (Inhaber, Admins, Häkchen „darf Kampagnen freigeben“), und nie die Person, die angefragt hat (409 conflict, Vier-Augen-Regel). Die anfragende Person bekommt eine Mail.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • commentstring | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/campaigns/{id}/approve" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{}'
Antwort200
{
  "approvalState": "none",
  "notified": 1
}
POST/v1/campaigns/{id}/request-changes

Änderungen an einer Kampagne anfordern

Setzt eine Kampagne in in_review auf changes_requested, mit Pflicht-Kommentar (was sich ändern soll). Rechte wie beim Freigeben, nie die anfragende Person (409 conflict). Die anfragende Person bekommt eine Mail und sendet die Kampagne nach der Änderung erneut zur Freigabe.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • commentstringPflicht

    1–2000 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/campaigns/{id}/request-changes" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "comment": "text"
}'
Antwort200
{
  "approvalState": "none",
  "notified": 1
}
POST/v1/campaigns/{id}/comments

Kampagne kommentieren

Schreibt einen Kommentar (1 bis 2000 Zeichen) in den Verlauf der Kampagne, ohne den Zustand der Freigabe zu ändern. Jede Rolle im Arbeitsbereich.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • commentstringPflicht

    1–2000 Zeichen

Antworten

  • 201Angelegt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/campaigns/{id}/comments" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "comment": "text"
}'
Antwort201
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "actor": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "name": "Sommer-Aktion"
  },
  "decision": "requested",
  "comment": "text",
  "note": "schedule_blocked",
  "createdAt": "2026-09-15T10:32:00Z"
}
GET/v1/campaigns/{id}/reviews

Verlauf der Freigabe lesen

Anfragen, Freigaben, angeforderte Änderungen und Kommentare der Kampagne, älteste zuerst. actor null = System. me sagt, was die aufrufende Person gerade darf: canDecide (freigeben oder Änderungen anfordern) und isRequester (hat die offene Anfrage gestellt). Jede Rolle im Arbeitsbereich.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/campaigns/{id}/reviews" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "actor": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "name": "Sommer-Aktion"
      },
      "decision": "requested",
      "comment": "text",
      "note": "schedule_blocked",
      "createdAt": "2026-09-15T10:32:00Z"
    }
  ],
  "approvalState": "none",
  "me": {
    "canApprove": true,
    "isRequester": true,
    "canDecide": true
  }
}
GET/v1/workspaces/{workspaceId}/approval-settings

Freigabe-Regeln lesen

Ob Kampagnen des Arbeitsbereichs vor dem Senden eine Freigabe brauchen, und wer freigeben darf (Inhaber, Admins und Personen mit dem Häkchen). Jede Rolle im Arbeitsbereich darf lesen, damit Bearbeiter vor dem Senden wissen, dass eine Freigabe nötig ist; E-Mail-Adressen der Freigeber nur für Admins.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/approval-settings" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "required": true,
  "updatedAt": "2026-09-15T10:32:00Z",
  "approvers": [
    {
      "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "email": "kunde@example.de",
      "canApprove": true
    }
  ]
}
PUT/v1/workspaces/{workspaceId}/approval-settings

Freigabe-Regeln ändern

Schaltet die Pflicht zur Freigabe für Kampagnen des Arbeitsbereichs an oder aus. Admin des Arbeitsbereichs, nur mit Browser-Sitzung (ein API-Token soll die Vier-Augen-Regel nicht abschalten). Mit der Pflicht antwortet jedes Senden ohne Freigabe mit 409 approval_required, und eine geplante Kampagne ohne Freigabe wird zu ihrer Zeit angehalten. Audit workspace.approval_settings.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • requiredbooleanPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PUT "https://api.dowallet.dev/v1/workspaces/{workspaceId}/approval-settings" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "required": true
}'
Antwort200
{
  "required": true,
  "updatedAt": "2026-09-15T10:32:00Z",
  "approvers": [
    {
      "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "email": "kunde@example.de",
      "canApprove": true
    }
  ]
}
GET/v1/workspaces/{workspaceId}/approvals/inbox

Freigaben für die Mitteilungszentrale

pending: Kampagnen in in_review, die die anfragende Person freigeben darf (nicht ihre eigenen Anfragen). decided: eigene Anfragen der letzten 7 Tage mit Entscheidung (freigegeben oder Änderungen angefordert), solange die Kampagne in diesem Zustand und noch nicht gesendet ist. blocked: eigene oder selbst angefragte Kampagnen, deren geplanter Versand in den letzten 7 Tagen mangels Freigabe angehalten wurde und die noch Entwurf sind. Jede Rolle im Arbeitsbereich, je Liste höchstens 20.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/approvals/inbox" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "pending": [
    {
      "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "status": "draft",
      "scheduleAt": "2026-09-15T10:32:00Z",
      "requestedAt": "2026-09-15T10:32:00Z",
      "requestedBy": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "name": "Sommer-Aktion"
      },
      "comment": "text"
    }
  ],
  "decided": [
    {
      "reviewId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "decision": "approved",
      "decidedAt": "2026-09-15T10:32:00Z",
      "decidedBy": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "name": "Sommer-Aktion"
      },
      "comment": "text"
    }
  ],
  "blocked": [
    {
      "reviewId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "campaignId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "blockedAt": "2026-09-15T10:32:00Z"
    }
  ]
}

Zielgruppen

Zielgruppen aus Pass-Attributen und Verhalten.

GET/v1/workspaces/{workspaceId}/audiences

Zielgruppen auflisten

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/audiences" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "filter": null,
      "estimatedCount": 1,
      "lastEstimatedAt": "2026-09-15T10:32:00Z",
      "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "createdAt": "2026-09-15T10:32:00Z",
      "usedByCampaigns": 1,
      "usedByFlows": 1,
      "usedByAudiences": 1
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/audiences

Zielgruppe anlegen

Legt eine gespeicherte Zielgruppe an. filter ist ein DSL-Baum (Blatt { field, op, value, type? }, Zweige { and: [...] } / { or: [...] }, Verneinung { not: … }) oder die ältere Form { onlyActiveAtStart, filters: [{ attribute, operator, value }] }; jede andere Form (etwa eine Liste ohne { and }) ist 422. Höchstens 30 eigene Bedingungen und 4 Ebenen aus and/or; audience.member setzt eine andere Zielgruppe desselben Arbeitsbereichs ein (höchstens 3 ineinander, ein Kreis ist 422). contact.name und contact.email_domain nur ab der Rolle Admin. Felder und Operatoren: docs/audiences.md. Der Filter wird vor dem Speichern übersetzt: ein unbekanntes Feld, ein Operator, der nicht zum Feld passt, oder ein falscher Wert ist ein 422 validation_failed auf filter mit details.field (das Feld der Regel) und details.path (Stelle im Baum). type an attributes.<key> (string, number, date, boolean) vergleicht typgerecht: Zahlen numerisch (Werte ohne Zahl treffen nie), Daten als Tag. Die Antwort trägt die gezählte Größe (estimatedCount). Nur bezahlte Pläne (402).

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–120 Zeichen

  • filterobjectPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/audiences" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "filter": null
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "filter": null,
  "estimatedCount": 1,
  "lastEstimatedAt": "2026-09-15T10:32:00Z",
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z"
}
POST/v1/audiences/{id}/estimate

Reichweite neu berechnen

Zählt eine gespeicherte Zielgruppe neu. Ab der Rolle Bearbeiter wird die Zahl an der Zielgruppe gespeichert (estimatedCount), Betrachter bekommen sie nur zurück. Mit templateId im Body zählt sie so, wie eine Kampagne dieser Vorlage sie erreicht (nur Pässe der Vorlage, ohne Test-Pässe) und speichert nichts. Ein Filter, der sich nicht übersetzen lässt, ist ein 422. Ratenklasse audience_count.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • templateIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/audiences/{id}/estimate" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}'
Antwort200
{
  "count": 1,
  "passIdsSample": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "estimatedGoogleCapped": 1
}
PATCH/v1/audiences/{id}

Zielgruppe bearbeiten

Benennt eine Zielgruppe um oder ändert ihre Regel. Der neue Filter wird wie beim Anlegen übersetzt (422 validation_failed auf filter mit details.field). Ein leerer Filter (keine Regel außer „nur aktive Pässe“) ersetzt eine Regel nur mit clear: true, sonst 422: so wird eine Zielgruppe nie aus Versehen zu allen Pässen. Ändert sich die Regel, verliert jede Kampagne im Entwurf oder geplant, die diese Zielgruppe nutzt, ihre Freigabe (approvalState none, Verlauf „Nach Freigabe geändert“, Audit campaign.review_reset); Umbenennen nicht. Setzen andere Zielgruppen, ungesendete Kampagnen oder nicht archivierte Automatisierungen diese Zielgruppe ein (audience.member), müssen sie mit der neuen Regel gültig bleiben (höchstens 3 Zielgruppen ineinander vom äußersten Filter, 200 Bedingungen), sonst 422 mit ihrem Namen. Regeln auf contact.name und contact.email_domain nur ab der Rolle Admin, außer die Regel bleibt unverändert. Nur bezahlte Pläne (402).

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • filterobjectoptional
  • clearbooleanoptional

    true = ein leerer Filter darf die bestehende Regel ersetzen (die Zielgruppe erreicht danach alle Pässe).

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/audiences/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "filter": null,
  "clear": true
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "filter": null,
  "estimatedCount": 1,
  "lastEstimatedAt": "2026-09-15T10:32:00Z",
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z"
}
DELETE/v1/audiences/{id}

Zielgruppe löschen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/audiences/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/workspaces/{workspaceId}/audiences/preview

Zielgruppe schätzen (ohne Speichern)

Zählt einen Filter, ohne ihn zu speichern, und liefert bis zu 25 Pässe als Stichprobe, neueste zuerst. Mit templateId zählt sie so, wie eine Kampagne dieser Vorlage die Zielgruppe erreicht: nur Pässe der Vorlage, ohne Test-Pässe. Ein Filter, der sich nicht übersetzen lässt, ist ein 422 validation_failed mit details.field. Regeln auf contact.name und contact.email_domain nur ab der Rolle Admin (Fähigkeit contacts:read_unmasked), sonst 422.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • filterobjectPflicht
  • templateIduuidoptional

    Vorlage einer Kampagne: die Zählung gilt nur für ihre Pässe, ohne Test-Pässe, wie beim Senden.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/audiences/preview" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "filter": null,
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}'
Antwort200
{
  "count": 1,
  "sample": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "serial": "ABC123456",
      "platform": "text",
      "status": "active",
      "createdAt": "text",
      "utmSource": "text"
    }
  ]
}
GET/v1/audiences/{id}/members.csv

Mitglieder einer Zielgruppe als CSV exportieren

Alle Pässe, die die gespeicherte Zielgruppe gerade erreicht (wie die Zählung, ohne Vorlagen-Umfang), neueste zuerst: Seriennummer, Vorlage, Plattform, Zustand, erstellt, gültig bis, eigene Kennung, Treue-Stand und Stufe. Ab der Rolle Admin zusätzlich E-Mail, Vorname, Nachname, Sprache und „Kontakt seit“ des Kontakts, nur wenn sein Service-Zweck nicht widerrufen ist, und je aktivem Zweck eine Spalte zweck_<key> (ja, nein, widerrufen am). Semikolon als Trennzeichen, UTF-8 mit BOM, Formel-Zeichen am Zellanfang werden entschärft. Ab der Rolle editor, nur bezahlte Pläne (402), Ratenklasse audience_count, Audit audience.members_export mit Anzahl.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/audiences/{id}/members.csv" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
"text"
GET/v1/workspaces/{workspaceId}/audiences/attribute-keys

Attribut-Schlüssel für Zielgruppen

Die Schlüssel, nach denen eine Zielgruppe mit attributes.<key> filtern kann: aus den Feldlisten der Vorlagen (declared) und aus einer Stichprobe der neuesten 5.000 Pässe des Workspace. count = Pässe der Stichprobe mit einem Wert, sample = bis zu 5 häufige Werte (leer bei personenbezogenen Schlüsseln wie E-Mail, Name oder Telefon), label und type aus der Feldliste, valueType (string, number, date, boolean) aus der Feldliste oder der Stichprobe: danach vergleicht ein Filter mit type typgerecht. Kontaktfelder (customerEmail, customerName …) erscheinen nicht. Jede Rolle im Workspace; Token-Scope audiences:read.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 429Rate-Limit
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/audiences/attribute-keys" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "key": "text",
      "count": 1,
      "sample": [
        "text"
      ],
      "declared": true,
      "label": "Sommer-Aktion",
      "type": "text",
      "valueType": "string"
    }
  ]
}

Automatisierungen

Automatisierungen: ereignisgesteuerte Push- und E-Mail-Strecken.

GET/v1/workspaces/{workspaceId}/flows

Automatisierungen auflisten

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/flows" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "status": "draft",
      "trigger": {
        "type": "event_date"
      },
      "definition": {
        "steps": [
          {
            "type": null,
            "timing": null,
            "message": null
          }
        ]
      },
      "definitionVersion": 1,
      "source": "text",
      "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "audienceFilter": null,
      "triggerUrl": "https://example.de/hook",
      "activatedAt": "2026-09-15T10:32:00Z",
      "pausedAt": "2026-09-15T10:32:00Z",
      "createdAt": "2026-09-15T10:32:00Z",
      "updatedAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/flows

Automatisierung anlegen

Legt einen Entwurf an: Vorlage, Auslöser und Schritte (Push, Inhalt ändern, Standort-Hinweis, E-Mail). Zielgruppe: audienceId (gespeicherte Zielgruppe) oder audienceFilter (eigener Filter, Sprache wie audiences.filter), nicht beides (422); sie gilt für jeden Auslöser. Auslöser zusätzlich zu Pass hinzugefügt/entfernt, Event-Datum und festem Datum: redeemed (Nutzung, optional kinds), external_event (key, Auslöser-URL POST /v1/workspaces/:workspaceId/triggers/:key) und pass_date (field validUntil oder attr.<schlüssel>, offsetDays −365…365). Texte und Feldwerte der Schritte dürfen Formeln {{= … }} enthalten (Variablen event.…, attr.…, pointsBalance); eine ungültige Formel → 422 expression_invalid mit dem Feld. E-Mail-Schritte gehen bei jedem Auslöser, verschickt wird nur mit Marketing-Einwilligung.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–120 Zeichen

  • templateIduuidPflicht
  • triggerobjectPflicht
  • definitionobjectPflicht
  • stepsobject[]Pflicht

    1–6 Einträge

  • source"manual" | "template" | "ai"optional
  • audienceIduuid | nulloptional

    Gespeicherte Zielgruppe des Workspace; nur Pässe darin laufen durch den Ablauf. null entfernt sie. Nicht zusammen mit audienceFilter.

  • audienceFilterobjectoptional

    Eigener Filter statt einer gespeicherten Zielgruppe, gleiche Sprache wie audiences.filter. null entfernt ihn. Nicht zusammen mit audienceId. Ohne beides: alle Pässe der Vorlage.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/flows" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "trigger": {
    "type": "event_date"
  },
  "definition": {
    "steps": [
      {
        "type": "push",
        "timing": {
          "offsetMinutes": 1
        },
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    ]
  },
  "source": "manual",
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audienceFilter": null
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "status": "draft",
  "trigger": {
    "type": "event_date"
  },
  "definition": {
    "steps": [
      {
        "type": "push",
        "timing": {
          "anchor": "trigger",
          "offsetMinutes": 1
        },
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    ]
  },
  "definitionVersion": 1,
  "source": "text",
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audienceFilter": null,
  "triggerUrl": "https://example.de/hook",
  "stats": {
    "enrolled": 1,
    "active": 1,
    "completed": 1,
    "cancelled": 1,
    "failed": 1,
    "enrolled30d": 1,
    "redeemedSinceEnrol": 1,
    "redemptionRate": 1
  },
  "activatedAt": "2026-09-15T10:32:00Z",
  "pausedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z"
}
GET/v1/flows/{id}

Automatisierung lesen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/flows/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "status": "draft",
  "trigger": {
    "type": "event_date"
  },
  "definition": {
    "steps": [
      {
        "type": "push",
        "timing": {
          "anchor": "trigger",
          "offsetMinutes": 1
        },
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    ]
  },
  "definitionVersion": 1,
  "source": "text",
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audienceFilter": null,
  "triggerUrl": "https://example.de/hook",
  "stats": {
    "enrolled": 1,
    "active": 1,
    "completed": 1,
    "cancelled": 1,
    "failed": 1,
    "enrolled30d": 1,
    "redeemedSinceEnrol": 1,
    "redemptionRate": 1
  },
  "activatedAt": "2026-09-15T10:32:00Z",
  "pausedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z"
}
PATCH/v1/flows/{id}

Automatisierung bearbeiten

Nur im Entwurf oder pausiert (sonst 409); die Vorlage nur im Entwurf. Zielgruppe: audienceId (gespeicherte Zielgruppe) oder audienceFilter (eigener Filter, Sprache wie audiences.filter), nicht beides (422); sie gilt für jeden Auslöser. Auslöser zusätzlich zu Pass hinzugefügt/entfernt, Event-Datum und festem Datum: redeemed (Nutzung, optional kinds), external_event (key, Auslöser-URL POST /v1/workspaces/:workspaceId/triggers/:key) und pass_date (field validUntil oder attr.<schlüssel>, offsetDays −365…365). Texte und Feldwerte der Schritte dürfen Formeln {{= … }} enthalten (Variablen event.…, attr.…, pointsBalance); eine ungültige Formel → 422 expression_invalid mit dem Feld. E-Mail-Schritte gehen bei jedem Auslöser, verschickt wird nur mit Marketing-Einwilligung.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • templateIduuidoptional
  • triggerobjectoptional
  • definitionobjectoptional
  • stepsobject[]Pflicht

    1–6 Einträge

  • audienceIduuid | nulloptional

    Gespeicherte Zielgruppe des Workspace; nur Pässe darin laufen durch den Ablauf. null entfernt sie. Nicht zusammen mit audienceFilter.

  • audienceFilterobjectoptional

    Eigener Filter statt einer gespeicherten Zielgruppe, gleiche Sprache wie audiences.filter. null entfernt ihn. Nicht zusammen mit audienceId. Ohne beides: alle Pässe der Vorlage.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/flows/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "trigger": {
    "type": "event_date"
  },
  "definition": {
    "steps": [
      {
        "type": "push",
        "timing": {
          "offsetMinutes": 1
        },
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    ]
  },
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audienceFilter": null
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "status": "draft",
  "trigger": {
    "type": "event_date"
  },
  "definition": {
    "steps": [
      {
        "type": "push",
        "timing": {
          "anchor": "trigger",
          "offsetMinutes": 1
        },
        "message": "Heute 20 % auf alles. Nur bis Ladenschluss."
      }
    ]
  },
  "definitionVersion": 1,
  "source": "text",
  "audienceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "audienceFilter": null,
  "triggerUrl": "https://example.de/hook",
  "stats": {
    "enrolled": 1,
    "active": 1,
    "completed": 1,
    "cancelled": 1,
    "failed": 1,
    "enrolled30d": 1,
    "redeemedSinceEnrol": 1,
    "redemptionRate": 1
  },
  "activatedAt": "2026-09-15T10:32:00Z",
  "pausedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z"
}
POST/v1/flows/{id}/activate

Automatisierung aktivieren

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/flows/{id}/activate" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "status": "active",
  "enrollTargets": 1
}
POST/v1/flows/{id}/pause

Automatisierung pausieren

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/flows/{id}/pause" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "status": "paused"
}
POST/v1/flows/{id}/archive

Automatisierung archivieren

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/flows/{id}/archive" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "status": "archived"
}
GET/v1/flows/{id}/stats

Statistik der Automatisierung

Einschreibungen nach Zustand, je Schritt ausgeführt, übersprungen und offen, dazu die Einlösequote: redeemedSinceEnrol = Einschreibungen, deren Pass danach mindestens eine Nutzung hatte, redemptionRate = redeemedSinceEnrol / enrolled (null ohne Einschreibung), enrolled30d = Einschreibungen der letzten 30 Tage.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/flows/{id}/stats" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "enrolled": 1,
  "active": 1,
  "completed": 1,
  "cancelled": 1,
  "failed": 1,
  "enrolled30d": 1,
  "redeemedSinceEnrol": 1,
  "redemptionRate": 1,
  "perStep": [
    {
      "index": 1,
      "type": "text",
      "executed": 1,
      "skipped": 1,
      "pending": 1,
      "skippedQuota": 1,
      "skippedNoEmail": 1,
      "skippedNoLocation": 1,
      "failed": 1
    }
  ]
}
POST/v1/flows/{id}/dry-run

Probelauf an einem Test-Pass

Führt alle gespeicherten Schritte sofort nacheinander an einem Test- oder Demo-Pass aus, mit echten Pushes. payload ist die Beispiel-Nutzlast für die Formeln (event.…), etwa { "goals": 3 } für ein externes Ereignis; höchstens 16 KB. Ein Schritt, dessen Formel nicht rechnet, steht als failed mit detail in der Antwort, der Pass behält dann seinen Inhalt.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • passIduuidPflicht
  • payloadobjectoptional

    Beispiel-Nutzlast des Auslösers für die Formeln (event.…).

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/flows/{id}/dry-run" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "payload": {}
}'
Antwort200
{
  "steps": [
    {
      "index": 1,
      "type": "text",
      "outcome": "text"
    }
  ]
}
POST/v1/flows/{id}/steps/{index}/test

Einzelnen Schritt an einen Test-Pass senden

Pfad-Parameter

  • iduuidPflicht
  • indexintegerPflicht

Request-Body (JSON)

  • passIduuidPflicht
  • payloadobjectoptional

    Beispiel-Nutzlast des Auslösers für die Formeln (event.…).

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/flows/{id}/steps/{index}/test" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "payload": {}
}'
Antwort200
{
  "index": 1,
  "type": "text",
  "outcome": "text",
  "detail": "text"
}
POST/v1/workspaces/{workspaceId}/triggers/{key}

Ereignis melden (Auslöser einer Automatisierung)

Startet jede aktive Automatisierung dieses Workspace mit dem Auslöser „Externes Ereignis“ und diesem key (2–40 Zeichen a–z, 0–9, _ und -). Eingeschrieben werden die aktiven Pässe der Vorlage des Flows in seiner Zielgruppe, mit serial nur dieser eine Pass, mit testOnly: true nur Test-Pässe. payload (JSON-Objekt, höchstens 16 KB) steht den Formeln der Schritte als event.<pfad> zur Verfügung, etwa „Rabatt {{= min(event.goals*5, 25) }} %“. Jeder Aufruf ist ein eigenes Vorkommen: ein Pass läuft bei jedem Aufruf erneut durch den Ablauf; ein laufender Durchlauf desselben Passes wird dabei beendet. Header Idempotency-Key (24 h) macht Wiederholungen sicher. Grenzen: 120 Aufrufe pro Minute je Person oder Token. Ein Aufruf an alle Pässe (ohne serial, ohne testOnly) sperrt jede Automatisierung, die er startet, für 60 Sekunden; ist jede passende Automatisierung gesperrt → 429 rate_limited mit Retry-After. Aufrufe mit serial und Testereignisse sperren nichts. Antwort 202 mit matchedFlows und enrolled; die Schritte laufen danach im Hintergrund. Rolle Editor oder höher, Token-Scope events:write; im Free-Plan gesperrt (402). Unbekannte serial → 404.

Pfad-Parameter

  • workspaceIduuidPflicht
  • keystringPflicht

Request-Body (JSON)

  • payloadobjectoptional

    Nutzlast des Ereignisses als JSON-Objekt, höchstens 16 KB, in den Formeln der Schritte als event.<pfad> (etwa event.goals).

  • serialstringoptional

    Nur dieser Pass (Seriennummer). Ohne: alle aktiven Pässe der Vorlage in der Zielgruppe des Flows. · 1–200 Zeichen

  • testOnlybooleanoptional

    true = nur Test-Pässe (Seite Test-Pass, Test-Landing-Seite), zum Ausprobieren („Testereignis senden“). Sonst nur echte Pässe.

Antworten

  • 202Angenommen
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/triggers/{key}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "payload": {},
  "serial": "ABC123456",
  "testOnly": false
}'
Antwort202
{
  "matchedFlows": 1,
  "enrolled": 1
}

Standorte

Standorte für Hinweise auf dem Sperrbildschirm in der Nähe.

GET/v1/workspaces/{workspaceId}/locations

Standorte auflisten

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/locations" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "address": "text",
      "zip": "text",
      "city": "text",
      "lat": 1,
      "lon": 1,
      "radiusM": 1,
      "beaconUuid": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "beaconMajor": 1,
      "beaconMinor": 1,
      "externalRef": "text",
      "createdAt": "2026-09-15T10:32:00Z",
      "updatedAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/locations

Standort anlegen

Legt einen Standort an. Straße (address), PLZ (zip) und Stadt (city) sind getrennte Felder; der Radius liegt zwischen 10 und 5.000 m. externalRef ist die Filialnummer, je Workspace eindeutig (vergeben: 409 conflict mit details.locationId). Viele Standorte auf einmal: POST /v1/workspaces/:workspaceId/locations/import. Im kostenlosen Paket nicht enthalten (402).

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–120 Zeichen

  • addressstring | nulloptional

    Straße und Hausnummer. Leer oder null = ohne Adresse.

  • zipstring | nulloptional

    Postleitzahl. Fehlen zip und city, wird eine Adresse der Form „Straße 1, 18055, Rostock“ aufgeteilt.

  • citystring | nulloptional

    Stadt.

  • latnumberPflicht

    -90 bis 90

  • lonnumberPflicht

    -180 bis 180

  • radiusMintegeroptional

    10 bis 50000

  • externalRefstring | nulloptional

    Filialnummer (Kasse, Clearing), je Workspace eindeutig; eine vergebene Nummer ist ein 409 conflict. Leer oder null = ohne.

  • beaconUuiduuid | nulloptional

    iBeacon-UUID. null entfernt den Beacon samt Major und Minor.

  • beaconMajorinteger | nulloptional
  • beaconMinorinteger | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/locations" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "address": "text",
  "zip": "text",
  "city": "text",
  "lat": 1,
  "lon": 1,
  "radiusM": 150,
  "externalRef": "text",
  "beaconUuid": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "beaconMajor": 1,
  "beaconMinor": 1
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "address": "text",
  "zip": "text",
  "city": "text",
  "lat": 1,
  "lon": 1,
  "radiusM": 1,
  "beaconUuid": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "beaconMajor": 1,
  "beaconMinor": 1,
  "externalRef": "text",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z"
}
PATCH/v1/locations/{id}

Standort bearbeiten

Ändert einen Standort. Nur mitgeschickte Felder ändern sich; null oder leer löscht Straße, PLZ, Stadt oder Filialnummer, beaconUuid: null entfernt den Beacon. Ändern sich Koordinaten, Radius oder Beacon, lädt jeder aktive Pass der Vorlagen mit diesem Standort neu (repushed = Zahl dieser Pässe).

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • addressstring | nulloptional

    Straße und Hausnummer. Leer oder null = ohne Adresse.

  • zipstring | nulloptional

    Postleitzahl. Fehlen zip und city, wird eine Adresse der Form „Straße 1, 18055, Rostock“ aufgeteilt.

  • citystring | nulloptional

    Stadt.

  • latnumberoptional

    -90 bis 90

  • lonnumberoptional

    -180 bis 180

  • radiusMintegeroptional

    10 bis 50000

  • externalRefstring | nulloptional

    Filialnummer (Kasse, Clearing), je Workspace eindeutig; eine vergebene Nummer ist ein 409 conflict. Leer oder null = ohne.

  • beaconUuiduuid | nulloptional

    iBeacon-UUID. null entfernt den Beacon samt Major und Minor.

  • beaconMajorinteger | nulloptional
  • beaconMinorinteger | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/locations/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "address": "text",
  "zip": "text",
  "city": "text",
  "lat": 1,
  "lon": 1,
  "radiusM": 10,
  "externalRef": "text",
  "beaconUuid": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "beaconMajor": 1,
  "beaconMinor": 1
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "address": "text",
  "zip": "text",
  "city": "text",
  "lat": 1,
  "lon": 1,
  "radiusM": 1,
  "beaconUuid": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "beaconMajor": 1,
  "beaconMinor": 1,
  "externalRef": "text",
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "repushed": 1
}
DELETE/v1/locations/{id}

Standort löschen

Löscht einen Standort. Er fällt aus jeder Vorlage, deren aktive Pässe danach ohne ihn neu laden.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/locations/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/workspaces/{workspaceId}/locations/import

Standorte importieren

Legt bis zu 2.000 Standorte je Aufruf an oder gleicht sie ab. Jede Zeile braucht name, lat und lon (kein Geocoding); der Radius liegt zwischen 10 und 5.000 m (ohne Angabe 150). mode: "upsert" ändert den Standort mit derselben Filialnummer (externalRef) statt einen zweiten anzulegen, mode: "create" meldet eine vergebene Nummer als Fehler der Zeile. dryRun: true prüft nur und schreibt nichts. Die Antwort nennt je Zeile (results[].index = Position in rows) ok, action (created | updated) und bei Fehlern error.code und einen deutschen Satz; eine falsche Zeile hält die anderen nicht auf. Ändert ein Abgleich Koordinaten, Radius oder Beacon eines Standorts an einer Vorlage, laden deren aktive Pässe neu (repushed). Ab der Rolle Bearbeiter, Sitzung oder API-Token (Scope locations:write). Im kostenlosen Paket nicht enthalten (402).

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • rowsobject[]Pflicht

    1–2000 Einträge

  • namestringPflicht

    Name der Filiale, 1 bis 120 Zeichen.

  • addressstringoptional

    Straße und Hausnummer, höchstens 240 Zeichen. · nullbar

  • zipstringoptional

    PLZ, höchstens 16 Zeichen. · nullbar

  • citystringoptional

    Stadt, höchstens 120 Zeichen. · nullbar

  • latnumberPflicht

    Breitengrad, -90 bis 90. Pflicht, es gibt kein Geocoding.

  • lonnumberPflicht

    Längengrad, -180 bis 180. Pflicht.

  • radiusMnumberoptional

    Radius in Metern, ganze Zahl von 10 bis 5.000. Ohne Angabe 150 (neu) bzw. unverändert (Abgleich). · nullbar

  • externalRefstringoptional

    Filialnummer, höchstens 80 Zeichen, je Workspace eindeutig. Schlüssel für mode upsert. · nullbar

  • beaconUuidstringoptional

    iBeacon-UUID. · nullbar

  • beaconMajornumberoptional

    iBeacon-Major, 0 bis 65535; nur mit beaconUuid. · nullbar

  • beaconMinornumberoptional

    iBeacon-Minor, 0 bis 65535; nur mit beaconUuid. · nullbar

  • mode"create" | "upsert"optional

    create = jede Zeile neu; upsert = Zeilen mit vorhandener Filialnummer ändern diesen Standort.

  • dryRunbooleanoptional

    true = nur prüfen, nichts schreiben (Probelauf).

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/locations/import" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "rows": [
    {
      "name": "Sommer-Aktion",
      "lat": 1,
      "lon": 1
    }
  ],
  "mode": "create",
  "dryRun": false
}'
Antwort200
{
  "results": [
    {
      "index": 1,
      "ok": true
    }
  ],
  "created": 1,
  "updated": 1,
  "failed": 1,
  "dryRun": true,
  "repushed": 1
}

Code-Listen

Code-Listen mit eindeutigen Codes, die eine Vorlage beim Ausstellen vergibt, und die Wertquelle „API deines Systems“.

GET/v1/workspaces/{workspaceId}/code-pools/stats

Code-Listen mit Verfügbarkeit

Je Liste: produktive Codes (gesamt, frei, vergeben), Testcodes getrennt, Warnschwelle lowThreshold (null = Standardregel unter 10 % Rest), promotionId (Aktion, null = ohne) und low (mit Schwelle: frei ≤ lowThreshold). Gelöschte Listen fehlen.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/code-pools/stats" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "exhaustionPolicy": "fallback",
      "fallbackPattern": "text",
      "total": 1,
      "available": 1,
      "assigned": 1,
      "inActivePasses": 1,
      "inInactivePasses": 1,
      "assigned7d": 1,
      "lastAssignedAt": "text",
      "lowThreshold": 1,
      "low": true,
      "lowNotifiedAt": "text",
      "test": {
        "total": 1,
        "available": 1,
        "assigned": 1
      },
      "templates": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "name": "Sommer-Aktion",
          "onExhausted": "block"
        }
      ],
      "campaigns": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "name": "Sommer-Aktion"
        }
      ],
      "landingPages": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion"
        }
      ],
      "createdAt": "text"
    }
  ]
}
PATCH/v1/code-pools/{id}

Code-Liste umbenennen, Warnschwelle oder Erschöpfungsregel ändern

lowThreshold: ab wie vielen freien Codes die Liste als knapp gilt (null = Standardregel, unter 10 % Rest). Liegt die Liste danach über der Schwelle, gilt eine spätere Unterschreitung wieder als neu und bekommt wieder eine Mail.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • exhaustionPolicy"fallback" | "fail" | "block"optional
  • fallbackPatternstring | nulloptional
  • lowThresholdinteger | nulloptional
  • promotionIduuid | nulloptional

    Aktion, zu der das Teil gehört (GET /v1/workspaces/{id}/promotions); null = ohne Aktion. Fremde Aktion 404 promotion_not_found, archivierte 409 promotion_archived.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/code-pools/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "exhaustionPolicy": "fallback",
  "fallbackPattern": "text",
  "lowThreshold": 1,
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "allocationStrategy": "round_robin",
  "utmSourceFilter": {},
  "exhaustionPolicy": "fallback",
  "fallbackPattern": "text",
  "totalCount": 1,
  "assignedCount": 1,
  "lowThreshold": 1,
  "createdAt": "2026-09-15T10:32:00Z"
}
DELETE/v1/code-pools/{id}

Code-Liste löschen

Ab der Rolle org_admin. Wird die Liste noch genutzt (Vorlage, offene Kampagne „Pass ersetzen“, aktive Landing-Seite), antwortet die Route mit 409 in_use und nennt die Nutzer in details (templates, campaigns, landingPages). Sonst werden die freien Codes entfernt und die Liste archiviert; vergebene Codes bleiben in den Pässen und im Zuteilungs-Protokoll.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/code-pools/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
GET/v1/value-source/variables

Platzhalter für API-Wertquellen

Alle Variablen, die in URL und Request-Body einer API-Wertquelle als {{name}} verwendet werden können, z. B. {{pass.serial}}, {{utm.source}}, {{attr.<key>}}.

Antworten

  • 200OK
  • 401Nicht angemeldet
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/value-source/variables" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "name": "Sommer-Aktion",
      "description": "Kurze Beschreibung"
    }
  ]
}
POST/v1/workspaces/{workspaceId}/value-source/test

API-Wertquelle testen

Ruft deinen Endpunkt mit Testdaten auf und zeigt Wert oder Fehler samt Antwortzeit. Nichts wird gespeichert.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • mode"static"Pflicht
  • valuestringPflicht

    1–120 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/value-source/test" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "mode": "static",
  "value": "text"
}'
Antwort200
{
  "ok": true,
  "value": "text",
  "error": "text",
  "ms": 1
}
GET/v1/workspaces/{workspaceId}/code-pools

Code-Listen auflisten

Die Code-Listen des Workspace, ohne gelöschte.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • promotionIdstringoptional

    Nur Teile dieser Aktion; none = ohne Aktion.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/code-pools?promotionId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "allocationStrategy": "round_robin",
      "utmSourceFilter": {},
      "exhaustionPolicy": "fallback",
      "fallbackPattern": "text",
      "totalCount": 1,
      "assignedCount": 1,
      "lowThreshold": 1,
      "createdAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/code-pools

Code-Liste anlegen

Legt eine Liste an, optional gleich mit dem ersten Block Codes (values, bis 50.000) oder mit erzeugten Codes (generate), in einer Transaktion: scheitert der Import, bleibt keine leere Liste zurück. Weitere Blöcke über POST /v1/code-pools/{id}/bulk. Nicht im Free-Plan (402).

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–120 Zeichen

  • templateIduuid | nulloptional
  • promotionIduuid | nulloptional

    Aktion, zu der das Teil gehört (GET /v1/workspaces/{id}/promotions); null = ohne Aktion. Fremde Aktion 404 promotion_not_found, archivierte 409 promotion_archived.

  • allocationStrategy"round_robin" | "random" | "sequential"optional
  • utmSourceFilterobjectoptional
  • exhaustionPolicy"fallback" | "fail" | "block"optional
  • fallbackPatternstringoptional

    nullbar

  • lowThresholdinteger | nulloptional
  • valuesstring[]optional

    1–50000 Einträge

  • generateobjectoptional
  • countintegerPflicht

    1 bis 50000

  • prefixstringoptional

    0–12 Zeichen

  • lengthintegeroptional

    6 bis 16

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/code-pools" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "allocationStrategy": "sequential",
  "utmSourceFilter": {},
  "exhaustionPolicy": "fail",
  "fallbackPattern": "text",
  "lowThreshold": 1,
  "values": [
    "text"
  ],
  "generate": {
    "count": 1,
    "prefix": "text",
    "length": 8
  }
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "promotionId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "allocationStrategy": "round_robin",
  "utmSourceFilter": {},
  "exhaustionPolicy": "fallback",
  "fallbackPattern": "text",
  "totalCount": 1,
  "assignedCount": 1,
  "lowThreshold": 1,
  "createdAt": "2026-09-15T10:32:00Z"
}
POST/v1/code-pools/{id}/bulk

Codes in eine Liste importieren

Bis 50.000 Codes je Aufruf; größere Importe in Blöcken nacheinander. Codes, die in der Liste schon stehen, werden übersprungen (duplicates). test: true importiert in den Testbereich der Liste. Nicht im Free-Plan (402).

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • valuesstring[]Pflicht

    1–50000 Einträge

  • testbooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/code-pools/{id}/bulk" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "values": [
    "text"
  ],
  "test": false
}'
Antwort200
{
  "inserted": 1,
  "duplicates": 1
}
POST/v1/code-pools/{id}/generate

Codes für eine Liste erzeugen

Erzeugt count neue Codes (bis 50.000 je Aufruf) aus prefix und einem Zufallsteil der Länge length (6 bis 16 Zeichen, ohne 0/O und 1/I), eindeutig in der Liste. Antwort: generated neue Codes, total produktive Codes der Liste danach. Nicht im Free-Plan (402).

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • countintegerPflicht

    1 bis 50000

  • prefixstringoptional

    0–12 Zeichen

  • lengthintegeroptional

    6 bis 16

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/code-pools/{id}/generate" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "count": 1,
  "prefix": "text",
  "length": 8
}'
Antwort200
{
  "generated": 1,
  "total": 1
}
POST/v1/code-pools/{id}/test-codes/generate

Testcodes für eine Code-Liste erzeugen

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • countintegeroptional

    1 bis 500

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/code-pools/{id}/test-codes/generate" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "count": 20
}'
Antwort200
{
  "inserted": 1,
  "test": {
    "total": 1,
    "available": 1,
    "assigned": 1
  }
}
DELETE/v1/code-pools/{id}/test-codes

Testcodes einer Code-Liste zurücksetzen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/code-pools/{id}/test-codes" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "deleted": 1,
  "revoked": 1
}
GET/v1/code-pools/{id}/assignments.csv

Zuteilungen einer Code-Liste als CSV

Eine Zeile je vergebenem produktivem Code: code;seriennummer;utm_source;zugeteilt_am;ersatz (Zeitpunkt ISO 8601 in UTC, ersatz = ja, wenn die Liste als Ersatz für eine ausgefallene API diente). Semikolon, UTF-8 mit BOM und CRLF für ein deutsches Excel; Zellen, die mit = + - @ beginnen, bleiben Text. Ab der Rolle editor, jeder Export steht mit Anzahl im Audit-Log (code_pool.assignments_export). Auch für gelöschte Listen.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/code-pools/{id}/assignments.csv" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
"text"

Bilder

Bilder für Logo, Strip, Icon und Hero.

GET/v1/workspaces/{workspaceId}/assets

Bilder auflisten

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • kindlogo | icon | strip | thumbnail | background | footer | hero | cover | landingoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/assets?kind=logo" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "kind": "logo",
      "originalKey": "text",
      "derivatives": {},
      "mime": "text",
      "width": 1,
      "height": 1,
      "sizeBytes": 1,
      "originalFilename": "Sommer-Aktion",
      "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "createdAt": "2026-09-15T10:32:00Z",
      "signedUrl": "https://example.de/hook"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/workspaces/{workspaceId}/assets

Bild hochladen

Multipart. Logo, Icon, Strip oder Hero; doWallet erzeugt die Wallet-Varianten (1x/2x/3x) selbst.

Pfad-Parameter

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 413Zu groß
  • 415Default Response
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/assets" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "logo",
  "originalKey": "text",
  "derivatives": {},
  "mime": "text",
  "width": 1,
  "height": 1,
  "sizeBytes": 1,
  "originalFilename": "Sommer-Aktion",
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "signedUrl": "https://example.de/hook"
}
GET/v1/assets/{id}

Bild lesen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/assets/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "logo",
  "originalKey": "text",
  "derivatives": {},
  "mime": "text",
  "width": 1,
  "height": 1,
  "sizeBytes": 1,
  "originalFilename": "Sommer-Aktion",
  "createdById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "signedUrl": "https://example.de/hook"
}
DELETE/v1/assets/{id}

Bild löschen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/assets/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)

Konto

Anmeldung und Sitzung

Anmeldung, Sitzung, Passkeys und Zwei-Faktor für Nutzerkonten.

POST/v1/auth/sign-in

Anmelden mit Passwort

Setzt die Sitzungs-Cookies der Web-App. Bei aktivierter Zwei-Faktor-Authentifizierung folgt mfaRequired mit einem Challenge-Token.

Request-Body (JSON)

  • identifierstringPflicht

    1–∞ Zeichen

  • passwordstringPflicht

    1–∞ Zeichen

  • captchaTokenstringoptional

    1–∞ Zeichen

Antworten

  • 200OK
  • 400Ungültige Anfrage
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/sign-in" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "identifier": "text",
  "password": "text",
  "captchaToken": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx"
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "scopes": [
      "text"
    ],
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "isPlatformAdmin": true
  },
  "activeOrg": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "activeOrgRole": "super_admin",
  "activeOrgWideRole": "super_admin",
  "mfaEnrolled": true,
  "activeWorkspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "availableWorkspaces": [
    {
      "org": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "name": "Sommer-Aktion"
      },
      "workspaces": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion",
          "name": "Sommer-Aktion"
        }
      ]
    }
  ],
  "impersonation": {
    "superAdminUserId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "expiresAt": "2026-09-15T10:32:00Z",
    "mode": "read_only"
  },
  "customerMode": {
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "editUnlockedUntil": "2026-09-15T10:32:00Z",
    "unlockMinutes": 1
  }
}
POST/v1/auth/sign-in/mfa-verify

Zweiten Faktor bestätigen

Request-Body (JSON)

  • challengeTokenstringPflicht

    8–∞ Zeichen

  • codestringPflicht

    6–20 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 410Nicht mehr gültig
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/sign-in/mfa-verify" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "challengeToken": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx",
  "code": "text"
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "scopes": [
      "text"
    ],
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "isPlatformAdmin": true,
    "accessExpiresAt": "text",
    "tourCompletedAt": "text"
  },
  "activeOrg": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "activeOrgRole": "super_admin",
  "activeOrgWideRole": "super_admin",
  "mfaEnrolled": true,
  "activeWorkspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "availableWorkspaces": [
    {
      "org": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "name": "Sommer-Aktion"
      },
      "workspaces": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion",
          "name": "Sommer-Aktion"
        }
      ]
    }
  ],
  "impersonation": {
    "superAdminUserId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "expiresAt": "2026-09-15T10:32:00Z",
    "mode": "read_only"
  },
  "customerMode": {
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "editUnlockedUntil": "2026-09-15T10:32:00Z",
    "unlockMinutes": 1
  }
}
POST/v1/auth/sign-in/passkey-options

Zweiter Schritt mit Passkey: Optionen

Request-Body (JSON)

  • challengeTokenstringPflicht

    8–200 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 410Nicht mehr gültig
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/sign-in/passkey-options" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "challengeToken": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx"
}'
Antwort200
{
  "challenge": "text",
  "rpId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "timeout": 1,
  "userVerification": "text",
  "allowCredentials": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "type": "public-key"
    }
  ]
}
POST/v1/auth/sign-in/passkey-verify

Zweiter Schritt mit Passkey: Bestätigung

Request-Body (JSON)

  • challengeTokenstringPflicht

    8–200 Zeichen

  • responseobjectPflicht

Antworten

  • 200OK
  • 400Ungültige Anfrage
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 410Nicht mehr gültig
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/sign-in/passkey-verify" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "challengeToken": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx",
  "response": null
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "scopes": [
      "text"
    ],
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "isPlatformAdmin": true,
    "accessExpiresAt": "text",
    "tourCompletedAt": "text"
  },
  "activeOrg": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "activeOrgRole": "super_admin",
  "activeOrgWideRole": "super_admin",
  "mfaEnrolled": true,
  "activeWorkspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "availableWorkspaces": [
    {
      "org": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "name": "Sommer-Aktion"
      },
      "workspaces": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion",
          "name": "Sommer-Aktion"
        }
      ]
    }
  ],
  "impersonation": {
    "superAdminUserId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "expiresAt": "2026-09-15T10:32:00Z",
    "mode": "read_only"
  },
  "customerMode": {
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "editUnlockedUntil": "2026-09-15T10:32:00Z",
    "unlockMinutes": 1
  }
}
POST/v1/auth/passkeys/login-options

Passkey-Anmeldung: Optionen

Antworten

  • 200OK
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/passkeys/login-options" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
null
POST/v1/auth/passkeys/login-verify

Passkey-Anmeldung: Bestätigung

Request-Body (JSON)

  • responseobjectPflicht

Antworten

  • 200OK
  • 400Ungültige Anfrage
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/passkeys/login-verify" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "response": null
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "scopes": [
      "text"
    ],
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "isPlatformAdmin": true,
    "accessExpiresAt": "text",
    "tourCompletedAt": "text"
  },
  "activeOrg": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "activeOrgRole": "super_admin",
  "activeOrgWideRole": "super_admin",
  "mfaEnrolled": true,
  "activeWorkspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "availableWorkspaces": [
    {
      "org": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "name": "Sommer-Aktion"
      },
      "workspaces": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion",
          "name": "Sommer-Aktion"
        }
      ]
    }
  ],
  "impersonation": {
    "superAdminUserId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "expiresAt": "2026-09-15T10:32:00Z",
    "mode": "read_only"
  },
  "customerMode": {
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "editUnlockedUntil": "2026-09-15T10:32:00Z",
    "unlockMinutes": 1
  }
}
POST/v1/auth/sign-out

Abmelden

Antworten

  • 204Kein Inhalt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/sign-out" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/auth/active-workspace

Aktiven Workspace wechseln

Request-Body (JSON)

  • workspaceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/active-workspace" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "scopes": [
      "text"
    ],
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "isPlatformAdmin": true,
    "accessExpiresAt": "text",
    "tourCompletedAt": "text"
  },
  "activeOrg": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "activeOrgRole": "super_admin",
  "activeOrgWideRole": "super_admin",
  "mfaEnrolled": true,
  "activeWorkspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "availableWorkspaces": [
    {
      "org": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "name": "Sommer-Aktion"
      },
      "workspaces": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion",
          "name": "Sommer-Aktion"
        }
      ]
    }
  ],
  "impersonation": {
    "superAdminUserId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "expiresAt": "2026-09-15T10:32:00Z",
    "mode": "read_only"
  },
  "customerMode": {
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "editUnlockedUntil": "2026-09-15T10:32:00Z",
    "unlockMinutes": 1
  }
}
POST/v1/auth/otp-request

Anmeldecode per E-Mail anfordern

Antwortet immer 204. Die E-Mail enthält einen 6-stelligen Code und einen Direkt-Link, beide 10 Minuten gültig und einmal verwendbar.

Request-Body (JSON)

  • emailemailPflicht
  • brandstringoptional

    Kurzname der Marke, von deren Anmeldung die Anfrage kommt (/anmelden/<slug>). Wirkt nur für Mitglieder dieser Organisation mit geprüfter App-Marke. · 0–80 Zeichen

  • captchaTokenstringoptional

    Token des doCaptcha-Widgets auf dem Formular. Pflicht, sobald die API mit doCaptcha läuft (sonst 400, details.reason captcha_required oder captcha_failed). · 1–4096 Zeichen

Antworten

  • 204Kein Inhalt
  • 400Ungültige Anfrage
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/otp-request" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "kunde@example.de",
  "brand": "text",
  "captchaToken": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx"
}'
Antwort204
(kein Inhalt)
POST/v1/auth/otp-verify

Anmeldecode einlösen

Request-Body (JSON)

  • emailemailPflicht
  • codestringPflicht

    4–12 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/otp-verify" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "kunde@example.de",
  "code": "text"
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "scopes": [
      "text"
    ],
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "isPlatformAdmin": true
  },
  "activeOrg": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "activeOrgRole": "super_admin",
  "activeOrgWideRole": "super_admin",
  "mfaEnrolled": true,
  "activeWorkspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "availableWorkspaces": [
    {
      "org": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "name": "Sommer-Aktion"
      },
      "workspaces": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion",
          "name": "Sommer-Aktion"
        }
      ]
    }
  ],
  "impersonation": {
    "superAdminUserId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "expiresAt": "2026-09-15T10:32:00Z",
    "mode": "read_only"
  },
  "customerMode": {
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "editUnlockedUntil": "2026-09-15T10:32:00Z",
    "unlockMinutes": 1
  }
}
POST/v1/auth/otp-link-verify

Anmelde-Link einlösen

Request-Body (JSON)

  • tokenstringPflicht

    20–200 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/otp-link-verify" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "token": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx"
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "scopes": [
      "text"
    ],
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "isPlatformAdmin": true
  },
  "activeOrg": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "activeOrgRole": "super_admin",
  "activeOrgWideRole": "super_admin",
  "mfaEnrolled": true,
  "activeWorkspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "availableWorkspaces": [
    {
      "org": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "name": "Sommer-Aktion"
      },
      "workspaces": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion",
          "name": "Sommer-Aktion"
        }
      ]
    }
  ],
  "impersonation": {
    "superAdminUserId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "expiresAt": "2026-09-15T10:32:00Z",
    "mode": "read_only"
  },
  "customerMode": {
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "editUnlockedUntil": "2026-09-15T10:32:00Z",
    "unlockMinutes": 1
  }
}
POST/v1/auth/password-reset-request

Passwort-Zurücksetzen anfordern

Request-Body (JSON)

  • emailemailPflicht
  • brandstringoptional

    Kurzname der Marke, von deren Anmeldung die Anfrage kommt (/anmelden/<slug>). Wirkt nur für Mitglieder dieser Organisation mit geprüfter App-Marke. · 0–80 Zeichen

  • captchaTokenstringoptional

    Token des doCaptcha-Widgets auf dem Formular. Pflicht, sobald die API mit doCaptcha läuft (sonst 400, details.reason captcha_required oder captcha_failed). · 1–4096 Zeichen

Antworten

  • 204Kein Inhalt
  • 400Ungültige Anfrage
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/password-reset-request" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "kunde@example.de",
  "brand": "text",
  "captchaToken": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx"
}'
Antwort204
(kein Inhalt)
GET/v1/auth/password-reset/{token}

Link zum Zurücksetzen prüfen

Sagt, ob der Link aus der E-Mail noch gilt, bevor jemand ein neues Passwort setzt.

Pfad-Parameter

  • tokenstringPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 410Nicht mehr gültig
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/auth/password-reset/{token}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/auth/password-reset-complete

Neues Passwort setzen

Request-Body (JSON)

  • tokenstringPflicht

    8–∞ Zeichen

  • newPasswordstringPflicht

    4–∞ Zeichen

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 410Nicht mehr gültig
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/password-reset-complete" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "token": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx",
  "newPassword": "text"
}'
Antwort204
(kein Inhalt)
POST/v1/auth/sessions/revoke-others

Alle anderen Sitzungen beenden

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/sessions/revoke-others" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "revoked": 1
}
POST/v1/auth/change-password

Passwort ändern

Request-Body (JSON)

  • currentPasswordstringPflicht

    1–∞ Zeichen

  • newPasswordstringPflicht

    4–∞ Zeichen

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/change-password" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "currentPassword": "text",
  "newPassword": "text"
}'
Antwort204
(kein Inhalt)
PATCH/v1/users/me

Eigenes Profil ändern

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • locale"de-DE" | "fr-FR" | "en-US"optional
  • tourCompletedbooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/users/me" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "locale": "de-DE",
  "tourCompleted": true
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "email": "kunde@example.de",
  "name": "Sommer-Aktion",
  "locale": "de",
  "isPlatformAdmin": true,
  "tourCompletedAt": "text"
}
GET/v1/users/me/notification-preferences

Eigene Team-Mails lesen

Je Art (approvals, credentialExpiry, codeStock) an oder aus.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/users/me/notification-preferences" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "approvals": true,
  "credentialExpiry": true,
  "codeStock": true,
  "ownerTickets": true,
  "ownerModuleRequests": true,
  "ownerOverdueInvoices": true
}
PATCH/v1/users/me/notification-preferences

Eigene Team-Mails an- und abschalten

Nur die übergebenen Arten ändern sich; die Glocke zeigt die Hinweise weiter.

Request-Body (JSON)

  • approvalsbooleanoptional
  • credentialExpirybooleanoptional
  • codeStockbooleanoptional
  • ownerTicketsbooleanoptional
  • ownerModuleRequestsbooleanoptional
  • ownerOverdueInvoicesbooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/users/me/notification-preferences" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "approvals": true,
  "credentialExpiry": true,
  "codeStock": true,
  "ownerTickets": true,
  "ownerModuleRequests": true,
  "ownerOverdueInvoices": true
}'
Antwort200
{
  "approvals": true,
  "credentialExpiry": true,
  "codeStock": true,
  "ownerTickets": true,
  "ownerModuleRequests": true,
  "ownerOverdueInvoices": true
}
GET/v1/auth/me

Eigene Sitzung lesen

Nutzer, aktive Organisation mit ihrem Funktionsumfang (activeOrg.capabilities, dasselbe Objekt wie in GET /v1/orgs/{id}), Rolle, aktiver Workspace.

Antworten

  • 200OK
  • 401Nicht angemeldet
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/auth/me" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "scopes": [
      "text"
    ],
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "isPlatformAdmin": true,
    "accessExpiresAt": "text",
    "tourCompletedAt": "text"
  },
  "activeOrg": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "activeOrgRole": "super_admin",
  "activeOrgWideRole": "super_admin",
  "mfaEnrolled": true,
  "activeWorkspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "availableWorkspaces": [
    {
      "org": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "name": "Sommer-Aktion"
      },
      "workspaces": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion",
          "name": "Sommer-Aktion"
        }
      ]
    }
  ],
  "impersonation": {
    "superAdminUserId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "expiresAt": "2026-09-15T10:32:00Z",
    "mode": "read_only"
  },
  "customerMode": {
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "editUnlockedUntil": "2026-09-15T10:32:00Z",
    "unlockMinutes": 1
  }
}
POST/v1/auth/passkeys/register-options

Passkey registrieren: Optionen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/passkeys/register-options" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
null
POST/v1/auth/passkeys/register-verify

Passkey registrieren: Bestätigung

Request-Body (JSON)

  • responseobjectPflicht
  • deviceNamestringoptional

    0–80 Zeichen

Antworten

  • 200OK
  • 400Ungültige Anfrage
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/passkeys/register-verify" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "response": null,
  "deviceName": "Sommer-Aktion"
}'
Antwort200
{
  "ok": true,
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}
GET/v1/auth/passkeys

Passkeys auflisten

Antworten

  • 200OK
  • 401Nicht angemeldet
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/auth/passkeys" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "deviceName": "Sommer-Aktion",
      "createdAt": "text",
      "lastUsedAt": "text"
    }
  ]
}
DELETE/v1/auth/passkeys/{id}

Passkey entfernen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/auth/passkeys/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
GET/v1/auth/mfa/status

Zwei-Faktor-Status

Antworten

  • 200OK
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/auth/mfa/status" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "enrolled": true,
  "verifiedAt": "2026-09-15T10:32:00Z",
  "recoveryCodesRemaining": 1
}
POST/v1/auth/mfa/setup

Zwei-Faktor einrichten

Liefert Secret und QR-Code für eine Authenticator-App.

Antworten

  • 200OK
  • 403Keine Berechtigung
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/mfa/setup" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "otpauth": "text",
  "secret": "text",
  "recoveryCodes": [
    "text"
  ]
}
POST/v1/auth/mfa/verify

Zwei-Faktor bestätigen

Aktiviert 2FA und gibt die Wiederherstellungscodes einmalig zurück.

Request-Body (JSON)

  • codestringPflicht

    6–8 Zeichen

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/mfa/verify" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "code": "text"
}'
Antwort204
(kein Inhalt)
POST/v1/auth/mfa/disable

Zwei-Faktor deaktivieren

Request-Body (JSON)

  • codestringPflicht

    6–20 Zeichen

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/auth/mfa/disable" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "code": "text"
}'
Antwort204
(kein Inhalt)

Organisation

Organisation: Profil, Branding, Rechnungen, E-Mail-Absender.

GET/v1/orgs/{id}/onboarding

Onboarding-Fortschritt

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{id}/onboarding" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "completed": 1,
  "total": 1,
  "steps": [
    {
      "key": "text",
      "label": "Sommer-Aktion",
      "done": true,
      "hint": "text"
    }
  ]
}
GET/v1/orgs/{id}/invoices

Rechnungen auflisten

Ohne Entwürfe. Enthält, ob PDF und E-Rechnung vorliegen.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{id}/invoices" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "number": "text",
      "amountCents": 1250,
      "currency": "EUR",
      "status": "active",
      "issuedAt": "text",
      "dueAt": "text",
      "paidAt": "text",
      "hasPdf": true,
      "hasEinvoice": true,
      "einvoiceFilename": "Sommer-Aktion",
      "hasProof": true,
      "proofUploadedAt": "text"
    }
  ]
}
GET/v1/orgs/{id}/invoices/{invoiceId}/payment-proof

Zahlungsnachweis herunterladen

Pfad-Parameter

  • iduuidPflicht
  • invoiceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{id}/invoices/{invoiceId}/payment-proof" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "url": "https://example.de/hook"
}
POST/v1/orgs/{id}/invoices/{invoiceId}/payment-proof

Zahlungsnachweis hochladen

PDF, PNG oder JPEG bis 10 MB. Die Rechnung wechselt in die Prüfung.

Pfad-Parameter

  • iduuidPflicht
  • invoiceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 413Zu groß
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{id}/invoices/{invoiceId}/payment-proof" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "number": "text",
  "amountCents": 1250,
  "currency": "EUR",
  "status": "active",
  "issuedAt": "text",
  "dueAt": "text",
  "paidAt": "text",
  "hasPdf": true,
  "hasEinvoice": true,
  "einvoiceFilename": "Sommer-Aktion",
  "hasProof": true,
  "proofUploadedAt": "text"
}
GET/v1/orgs/{id}/invoices/{invoiceId}/pdf

Rechnungs-PDF herunterladen

Liefert eine kurzlebige signierte URL.

Pfad-Parameter

  • iduuidPflicht
  • invoiceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{id}/invoices/{invoiceId}/pdf" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "url": "https://example.de/hook"
}
GET/v1/orgs/{id}/invoices/{invoiceId}/einvoice

E-Rechnung herunterladen

XRechnung (XML) oder ZUGFeRD (PDF), als signierte URL.

Pfad-Parameter

  • iduuidPflicht
  • invoiceIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{id}/invoices/{invoiceId}/einvoice" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "url": "https://example.de/hook",
  "filename": "Sommer-Aktion"
}
PUT/v1/orgs/{id}/onboarding-case

Anwendungsfall und Kundentyp festlegen

Speichert die Wahl aus dem ersten Login (/welcome): case ist der Anwendungsfall (loyalty, coupon, membership, eventTicket oder skipped), das optionale accountKind der Kundentyp (agency Agentur mit Kunden, brand eigene Marke, small Verein, Café oder kleines Geschäft). Ohne accountKind bleibt der gespeicherte Typ unverändert. Erlaubt ab Admin der ganzen Organisation.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • case"loyalty" | "coupon" | "membership" | "eventTicket" | "skipped"Pflicht
  • accountKind"agency" | "brand" | "small"optional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X PUT "https://api.dowallet.dev/v1/orgs/{id}/onboarding-case" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "case": "loyalty",
  "accountKind": "agency"
}'
Antwort200
{
  "case": "text",
  "accountKind": "agency",
  "modules": {
    "loyalty": {
      "enabled": true,
      "since": "text",
      "source": "backoffice",
      "requestedAt": "text"
    }
  }
}
GET/v1/orgs/{id}/modules

Module der Organisation

Jedes Modul mit Stand: eingeschaltet seit, Quelle, offene Anfrage. Module schaltet doWallet ein; die Organisation fragt sie mit POST /v1/orgs/{id}/modules/{key}/request an. canRequest: die aufrufende Person darf anfragen (Admin der ganzen Organisation). Lesen darf jedes Mitglied der Organisation.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{id}/modules" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "enabled": true,
      "since": "text",
      "source": "backoffice",
      "requestedAt": "text",
      "key": "loyalty",
      "label": "Sommer-Aktion",
      "description": "Kurze Beschreibung"
    }
  ],
  "canRequest": true
}
POST/v1/orgs/{id}/modules/{key}/request

Modul anfragen

Fragt ein Modul für die Organisation an (loyalty Treue, landingPages Landing-Seiten, campaigns Kampagnen, flows Automatisierungen, audiences Zielgruppen, locations Standorte, codePools Code-Listen, api Entwickler). doWallet schaltet es nach Absprache ein; die Anfrage erscheint dort in der Mitteilungszentrale. Erlaubt ab Admin der ganzen Organisation, nur mit Browser-Sitzung. Eine offene Anfrage bleibt bestehen (created false). Ist das Modul schon eingeschaltet: 409 mit details.reason module_active.

Pfad-Parameter

  • iduuidPflicht
  • keystringPflicht

    Modul: loyalty Treue, landingPages Landing-Seiten, campaigns Kampagnen, flows Automatisierungen, audiences Zielgruppen, locations Standorte, codePools Code-Listen, api Entwickler (API-Schlüssel, Webhooks, Anbindung).

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{id}/modules/{key}/request" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "module": {
    "enabled": true,
    "since": "text",
    "source": "backoffice",
    "requestedAt": "text"
  },
  "created": true
}
GET/v1/orgs/{id}/usage

Verbrauch und Kontingente

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{id}/usage" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "passesThisMonth": 1,
  "pushesThisMonth": 1,
  "quotas": {
    "passesPerMonth": 1,
    "pushesPerMonth": 1,
    "storageBytes": 1,
    "workspaces": 1,
    "teamMembers": 1
  }
}
GET/v1/orgs

Organisationen des Nutzers

Query-Parameter

  • cursorstringoptional
  • limitintegeroptional

Antworten

  • 200OK
  • 401Nicht angemeldet
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs?cursor=text&limit=50" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "slug": "sommer-aktion",
      "name": "Sommer-Aktion",
      "status": "active",
      "billingProfile": {},
      "quotas": {},
      "brandingLogoUrl": "https://example.de/hook",
      "branding": {},
      "entitlements": {
        "whiteLabel": false,
        "embedSdk": false,
        "scanner": false,
        "modules": {
          "loyalty": {
            "enabled": false,
            "since": null,
            "source": null,
            "requestedAt": null
          },
          "landingPages": {
            "enabled": false,
            "since": null,
            "source": null,
            "requestedAt": null
          },
          "campaigns": {
            "enabled": false,
            "since": null,
            "source": null,
            "requestedAt": null
          },
          "flows": {
            "enabled": false,
            "since": null,
            "source": null,
            "requestedAt": null
          },
          "audiences": {
            "enabled": false,
            "since": null,
            "source": null,
            "requestedAt": null
          },
          "locations": {
            "enabled": false,
            "since": null,
            "source": null,
            "requestedAt": null
          },
          "codePools": {
            "enabled": false,
            "since": null,
            "source": null,
            "requestedAt": null
          },
          "api": {
            "enabled": false,
            "since": null,
            "source": null,
            "requestedAt": null
          }
        }
      },
      "capabilities": {
        "industry": "retail",
        "passTypes": [
          "coupon"
        ],
        "modules": {
          "loyalty": true,
          "landingPages": true,
          "campaigns": true,
          "flows": true,
          "audiences": true,
          "locations": true,
          "codePools": true,
          "api": true
        },
        "scanner": true,
        "whiteLabel": true,
        "plan": "free",
        "accountKind": "agency"
      },
      "subdomain": "text",
      "appBrand": {
        "live": {
          "slug": null,
          "appName": null,
          "logoUrl": null,
          "logoWhiteUrl": null,
          "iconUrl": null,
          "primaryColor": null,
          "poweredByDoWallet": null,
          "verifiedAt": null
        },
        "state": "notEntitled",
        "missing": [
          "appName"
        ],
        "verifiedAt": "text"
      },
      "frozen": false,
      "frozenReason": "text",
      "paymentReminder": {},
      "auditRetentionDays": "text",
      "accountKind": "agency",
      "overdue": {
        "count": 1,
        "totalCents": 1
      },
      "billingSummary": {
        "packageName": "Sommer-Aktion",
        "tagline": "text",
        "badges": [
          "text"
        ],
        "priceCents": 1,
        "currency": "EUR",
        "period": "text",
        "durationMonths": 1,
        "perMessageFeeMicros": 1,
        "status": "active"
      },
      "createdAt": "2026-09-15T10:32:00Z",
      "updatedAt": "2026-09-15T10:32:00Z",
      "deletedAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
GET/v1/orgs/me

Aktive Organisation

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/me" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "status": "active",
  "billingProfile": {},
  "quotas": {},
  "brandingLogoUrl": "https://example.de/hook",
  "branding": {},
  "entitlements": {
    "whiteLabel": false,
    "embedSdk": false,
    "scanner": false,
    "modules": {
      "loyalty": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "landingPages": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "campaigns": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "flows": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "audiences": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "locations": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "codePools": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "api": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      }
    }
  },
  "capabilities": {
    "industry": "retail",
    "passTypes": [
      "coupon"
    ],
    "modules": {
      "loyalty": true,
      "landingPages": true,
      "campaigns": true,
      "flows": true,
      "audiences": true,
      "locations": true,
      "codePools": true,
      "api": true
    },
    "scanner": true,
    "whiteLabel": true,
    "plan": "free",
    "accountKind": "agency"
  },
  "subdomain": "text",
  "appBrand": {
    "live": {
      "slug": "sommer-aktion",
      "appName": "Sommer-Aktion",
      "logoUrl": "https://example.de/hook",
      "logoWhiteUrl": "https://example.de/hook",
      "iconUrl": "https://example.de/hook",
      "primaryColor": "#005be7",
      "poweredByDoWallet": true,
      "verifiedAt": "text"
    },
    "state": "notEntitled",
    "missing": [
      "appName"
    ],
    "verifiedAt": "text"
  },
  "frozen": false,
  "frozenReason": "text",
  "paymentReminder": {},
  "auditRetentionDays": "text",
  "accountKind": "agency",
  "overdue": {
    "count": 1,
    "totalCents": 1
  },
  "billingSummary": {
    "packageName": "Sommer-Aktion",
    "tagline": "text",
    "badges": [
      "text"
    ],
    "priceCents": 1,
    "currency": "EUR",
    "period": "text",
    "durationMonths": 1,
    "perMessageFeeMicros": 1,
    "status": "active"
  },
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "deletedAt": "2026-09-15T10:32:00Z"
}
GET/v1/orgs/{id}

Organisation lesen

Name, Status, Branding, Freigaben und capabilities, der Funktionsumfang: Branche (industry), erlaubte Pass-Typen (passTypes, nie leer, in der Reihenfolge der Branche), Module (modules: loyalty, landingPages, campaigns, flows, audiences, locations, codePools, api, je an oder aus), scanner, whiteLabel, plan und accountKind. Ist ein Modul aus, antworten seine Routen 403 module_disabled; eine neue Vorlage eines nicht erlaubten Pass-Typs 403 pass_type_not_allowed. Rechnungsdaten nur für Mitglieder der ganzen Organisation.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "status": "active",
  "billingProfile": {},
  "quotas": {},
  "brandingLogoUrl": "https://example.de/hook",
  "branding": {},
  "entitlements": {
    "whiteLabel": false,
    "embedSdk": false,
    "scanner": false,
    "modules": {
      "loyalty": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "landingPages": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "campaigns": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "flows": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "audiences": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "locations": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "codePools": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "api": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      }
    }
  },
  "capabilities": {
    "industry": "retail",
    "passTypes": [
      "coupon"
    ],
    "modules": {
      "loyalty": true,
      "landingPages": true,
      "campaigns": true,
      "flows": true,
      "audiences": true,
      "locations": true,
      "codePools": true,
      "api": true
    },
    "scanner": true,
    "whiteLabel": true,
    "plan": "free",
    "accountKind": "agency"
  },
  "subdomain": "text",
  "appBrand": {
    "live": {
      "slug": "sommer-aktion",
      "appName": "Sommer-Aktion",
      "logoUrl": "https://example.de/hook",
      "logoWhiteUrl": "https://example.de/hook",
      "iconUrl": "https://example.de/hook",
      "primaryColor": "#005be7",
      "poweredByDoWallet": true,
      "verifiedAt": "text"
    },
    "state": "notEntitled",
    "missing": [
      "appName"
    ],
    "verifiedAt": "text"
  },
  "frozen": false,
  "frozenReason": "text",
  "paymentReminder": {},
  "auditRetentionDays": "text",
  "accountKind": "agency",
  "overdue": {
    "count": 1,
    "totalCents": 1
  },
  "billingSummary": {
    "packageName": "Sommer-Aktion",
    "tagline": "text",
    "badges": [
      "text"
    ],
    "priceCents": 1,
    "currency": "EUR",
    "period": "text",
    "durationMonths": 1,
    "perMessageFeeMicros": 1,
    "status": "active"
  },
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "deletedAt": "2026-09-15T10:32:00Z"
}
PATCH/v1/orgs/{id}

Organisation ändern

Name, Rechnungsprofil (USt-ID, Adresse, Rechnungs-E-Mail; feldweise gemergt, ein leerer Text entfernt ein Feld) und Kundentyp accountKind (agency, brand, small; null = unbekannt). Erlaubt ab Admin der ganzen Organisation.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • billingProfileobjectoptional
  • vatIdstringoptional

    0–40 Zeichen

  • addressstringoptional

    0–500 Zeichen

  • contactEmailemail | ""optional
  • brandingLogoUrluri | nulloptional
  • accountKind"agency" | "brand" | "small" | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/orgs/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "billingProfile": {
    "vatId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "address": "text",
    "contactEmail": "kunde@example.de"
  },
  "brandingLogoUrl": "https://example.de/hook",
  "accountKind": "agency"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "status": "active",
  "billingProfile": {},
  "quotas": {},
  "brandingLogoUrl": "https://example.de/hook",
  "branding": {},
  "entitlements": {
    "whiteLabel": false,
    "embedSdk": false,
    "scanner": false,
    "modules": {
      "loyalty": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "landingPages": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "campaigns": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "flows": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "audiences": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "locations": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "codePools": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      },
      "api": {
        "enabled": false,
        "since": null,
        "source": null,
        "requestedAt": null
      }
    }
  },
  "capabilities": {
    "industry": "retail",
    "passTypes": [
      "coupon"
    ],
    "modules": {
      "loyalty": true,
      "landingPages": true,
      "campaigns": true,
      "flows": true,
      "audiences": true,
      "locations": true,
      "codePools": true,
      "api": true
    },
    "scanner": true,
    "whiteLabel": true,
    "plan": "free",
    "accountKind": "agency"
  },
  "subdomain": "text",
  "appBrand": {
    "live": {
      "slug": "sommer-aktion",
      "appName": "Sommer-Aktion",
      "logoUrl": "https://example.de/hook",
      "logoWhiteUrl": "https://example.de/hook",
      "iconUrl": "https://example.de/hook",
      "primaryColor": "#005be7",
      "poweredByDoWallet": true,
      "verifiedAt": "text"
    },
    "state": "notEntitled",
    "missing": [
      "appName"
    ],
    "verifiedAt": "text"
  },
  "frozen": false,
  "frozenReason": "text",
  "paymentReminder": {},
  "auditRetentionDays": "text",
  "accountKind": "agency",
  "overdue": {
    "count": 1,
    "totalCents": 1
  },
  "billingSummary": {
    "packageName": "Sommer-Aktion",
    "tagline": "text",
    "badges": [
      "text"
    ],
    "priceCents": 1,
    "currency": "EUR",
    "period": "text",
    "durationMonths": 1,
    "perMessageFeeMicros": 1,
    "status": "active"
  },
  "createdAt": "2026-09-15T10:32:00Z",
  "updatedAt": "2026-09-15T10:32:00Z",
  "deletedAt": "2026-09-15T10:32:00Z"
}
PATCH/v1/orgs/{id}/branding

Marke ändern

Logo, Farben, Schrift, Support-E-Mail, App-Name und App-Icon der Organisation, als Merge-Patch: nur gesendete Felder ändern sich, null entfernt ein Feld. Erlaubt ab Admin der ganzen Organisation. poweredByDoWallet: false blendet „Powered by doWallet“ auf Landing-Seiten und in der App aus und braucht die White-Label-Freigabe (sonst 403). App-Name, Logos, Icon und Primärfarbe wirken in App, Anmeldung und Team-Mails erst, wenn doWallet die Marke geprüft hat (appBrand in der Org-Antwort).

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • logoUrluri | nulloptional
  • logoWhiteUrluri | nulloptional
  • primaryColorstring | nulloptional
  • surfaceColorstringoptional
  • textColorstringoptional
  • mutedColorstringoptional
  • fontFamilystringoptional

    0–80 Zeichen

  • fontCssSrcurioptional
  • poweredByDoWalletbooleanoptional
  • supportEmailemail | nulloptional
  • embedOriginsstring[]optional

    0–20 Einträge

  • appNamestring | nulloptional
  • iconUrluri | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/orgs/{id}/branding" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "logoUrl": "https://example.de/hook",
  "logoWhiteUrl": "https://example.de/hook",
  "primaryColor": "#005be7",
  "surfaceColor": "#005be7",
  "textColor": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "mutedColor": "#005be7",
  "fontFamily": "text",
  "fontCssSrc": "https://example.de/hook",
  "poweredByDoWallet": true,
  "supportEmail": "kunde@example.de",
  "embedOrigins": [
    "text"
  ],
  "appName": "Sommer-Aktion",
  "iconUrl": "https://example.de/hook"
}'
Antwort200
{
  "logoUrl": "https://example.de/hook",
  "logoWhiteUrl": "https://example.de/hook",
  "primaryColor": "#005be7",
  "surfaceColor": "#005be7",
  "textColor": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "mutedColor": "#005be7",
  "fontFamily": "text",
  "fontCssSrc": "https://example.de/hook",
  "poweredByDoWallet": true,
  "supportEmail": "kunde@example.de",
  "embedOrigins": [
    "text"
  ],
  "appName": "Sommer-Aktion",
  "iconUrl": "https://example.de/hook"
}
POST/v1/orgs/{id}/white-label/request

White-Label anfragen

Fragt das Add-on White-Label für die Organisation an. doWallet bucht es nach Absprache; bis dahin bleibt „Powered by doWallet“ stehen. Erlaubt ab Admin der ganzen Organisation, auch Plattform-Admins nur mit Mitgliedschaft oder in einer übernommenen Sitzung (ohne bucht das Backoffice direkt). Eine offene Anfrage bleibt bestehen (created false). Ist White-Label schon gebucht oder im Paket enthalten: 409 mit details.reason white_label_active.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{id}/white-label/request" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "whiteLabelAddon": {
    "booked": true,
    "since": "text",
    "requestedAt": "text"
  },
  "created": true
}
GET/v1/orgs/{id}/email-settings

E-Mail-Absender lesen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{id}/email-settings" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "senderName": "Sommer-Aktion",
  "replyTo": "text",
  "smtp": {
    "host": "text",
    "port": 1,
    "user": "text",
    "fromAddress": "text",
    "hasPassword": true
  },
  "verifiedAt": "text",
  "effectiveFrom": "text"
}
PATCH/v1/orgs/{id}/email-settings

E-Mail-Absender ändern

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • senderNamestring | nulloptional
  • replyToemail | nulloptional
  • smtpobject | nulloptional
  • hoststringPflicht

    1–255 Zeichen

  • portintegerPflicht

    1 bis 65535

  • userstringPflicht

    1–255 Zeichen

  • passwordstringoptional

    1–512 Zeichen

  • fromAddressemailPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/orgs/{id}/email-settings" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "senderName": "Sommer-Aktion",
  "replyTo": "kunde@example.de",
  "smtp": {
    "host": "text",
    "port": 1,
    "user": "text",
    "fromAddress": "kunde@example.de"
  }
}'
Antwort200
{
  "senderName": "Sommer-Aktion",
  "replyTo": "text",
  "smtp": {
    "host": "text",
    "port": 1,
    "user": "text",
    "fromAddress": "text",
    "hasPassword": true
  },
  "verifiedAt": "text",
  "effectiveFrom": "text"
}
POST/v1/orgs/{id}/email-settings/test

Test-E-Mail senden

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 502Default Response
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{id}/email-settings/test" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "sent": true,
  "to": "text",
  "via": "platform",
  "effectiveFrom": "text"
}

Workspaces

Workspaces (Filialen, Marken) innerhalb einer Organisation.

GET/v1/orgs/{orgId}/workspaces

Workspaces auflisten

Pfad-Parameter

  • orgIduuidPflicht

Query-Parameter

  • cursorstringoptional
  • limitintegeroptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/workspaces?cursor=text&limit=50" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "slug": "sommer-aktion",
      "name": "Sommer-Aktion",
      "timezone": "Europe/Berlin",
      "defaultLocale": "de",
      "brandColor": "#005be7",
      "environment": "production",
      "logoUrl": "https://example.de/hook",
      "stage": "test",
      "liveAt": "2026-09-15T10:32:00Z",
      "archivedAt": "2026-09-15T10:32:00Z",
      "credentialMode": "inherit",
      "createdAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/orgs/{orgId}/workspaces

Workspace anlegen

Pfad-Parameter

  • orgIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–120 Zeichen

  • slugstringoptional

    2–60 Zeichen

  • timezonestringoptional
  • defaultLocalestringoptional
  • brandColorstringoptional
  • credentialMode"inherit" | "own"optional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/workspaces" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "slug": "sommer-aktion",
  "timezone": "Europe/Berlin",
  "defaultLocale": "de",
  "brandColor": "#005be7",
  "credentialMode": "inherit"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "timezone": "Europe/Berlin",
  "defaultLocale": "de",
  "brandColor": "#005be7",
  "environment": "production",
  "logoUrl": "https://example.de/hook",
  "stage": "test",
  "liveAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "credentialMode": "inherit",
  "pinnedAt": "2026-09-15T10:32:00Z",
  "lastOpenedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}
GET/v1/workspaces/{id}

Workspace lesen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "timezone": "Europe/Berlin",
  "defaultLocale": "de",
  "brandColor": "#005be7",
  "environment": "production",
  "logoUrl": "https://example.de/hook",
  "stage": "test",
  "liveAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "credentialMode": "inherit",
  "pinnedAt": "2026-09-15T10:32:00Z",
  "lastOpenedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}
PATCH/v1/workspaces/{id}

Workspace ändern

Name, Zeitzone, Standardsprache, Sandbox oder Production.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • timezonestringoptional
  • defaultLocalestringoptional
  • brandColorstring | nulloptional
  • environment"production" | "sandbox"optional
  • stage"test" | "live"optional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/workspaces/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "timezone": "Europe/Berlin",
  "defaultLocale": "de",
  "brandColor": "#005be7",
  "environment": "production",
  "stage": "test"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "timezone": "Europe/Berlin",
  "defaultLocale": "de",
  "brandColor": "#005be7",
  "environment": "production",
  "logoUrl": "https://example.de/hook",
  "stage": "test",
  "liveAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "credentialMode": "inherit",
  "pinnedAt": "2026-09-15T10:32:00Z",
  "lastOpenedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}
PUT/v1/workspaces/{id}/pin

Workspace anpinnen

Pinnt den Workspace für die angemeldete Person im Menü an. Höchstens drei je Organisation, sonst 409 pin_limit.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X PUT "https://api.dowallet.dev/v1/workspaces/{id}/pin" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "timezone": "Europe/Berlin",
  "defaultLocale": "de",
  "brandColor": "#005be7",
  "environment": "production",
  "logoUrl": "https://example.de/hook",
  "stage": "test",
  "liveAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "credentialMode": "inherit",
  "pinnedAt": "2026-09-15T10:32:00Z",
  "lastOpenedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}
DELETE/v1/workspaces/{id}/pin

Workspace lösen

Nimmt den Workspace für die angemeldete Person aus „Angepinnt“. Idempotent.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/workspaces/{id}/pin" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "timezone": "Europe/Berlin",
  "defaultLocale": "de",
  "brandColor": "#005be7",
  "environment": "production",
  "logoUrl": "https://example.de/hook",
  "stage": "test",
  "liveAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "credentialMode": "inherit",
  "pinnedAt": "2026-09-15T10:32:00Z",
  "lastOpenedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}
POST/v1/workspaces/{id}/archive

Workspace archivieren

Setzt den Workspace auf archiviert. Seine aktiven Pässe laufen sofort ab (Wallet zeigt „Abgelaufen“), nichts wird entwertet oder gelöscht. Geplante Kampagnen gehen zurück in den Entwurf, aktive Automatisierungen werden pausiert. Ein archivierter Workspace stellt keine Pässe aus (409 workspace_archived) und zählt nicht gegen die Workspace-Grenze. Der letzte offene Workspace einer Organisation lässt sich nicht archivieren (409). Wiederholt ohne Wirkung. Nur Admins der ganzen Organisation.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{id}/archive" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "timezone": "Europe/Berlin",
  "defaultLocale": "de",
  "brandColor": "#005be7",
  "environment": "production",
  "logoUrl": "https://example.de/hook",
  "stage": "test",
  "liveAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "credentialMode": "inherit",
  "pinnedAt": "2026-09-15T10:32:00Z",
  "lastOpenedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z",
  "expiredPasses": 1
}
POST/v1/workspaces/{id}/unarchive

Workspace reaktivieren

Öffnet einen archivierten Workspace wieder. Die Workspace-Grenze des Pakets gilt (402 workspace_limit_reached). Seine Pässe bleiben abgelaufen, Kampagnen und Automatisierungen bleiben, wie sie sind. Nur Admins der ganzen Organisation.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 402Default Response
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{id}/unarchive" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "slug": "sommer-aktion",
  "name": "Sommer-Aktion",
  "timezone": "Europe/Berlin",
  "defaultLocale": "de",
  "brandColor": "#005be7",
  "environment": "production",
  "logoUrl": "https://example.de/hook",
  "stage": "test",
  "liveAt": "2026-09-15T10:32:00Z",
  "archivedAt": "2026-09-15T10:32:00Z",
  "credentialMode": "inherit",
  "pinnedAt": "2026-09-15T10:32:00Z",
  "lastOpenedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}

Team

Rollen der Team-Mitglieder.

GET/v1/orgs/{orgId}/memberships

Team auflisten

Mitgliedschaften der Organisation für jede org-weite Rolle. Mit workspaceId nur die Mitgliedschaften dieses Arbeitsbereichs; Admins eines einzelnen Arbeitsbereichs brauchen diesen Filter und sehen nur ihren Arbeitsbereich. canApprove sagt, ob die Person Kampagnen freigeben darf.

Pfad-Parameter

  • orgIduuidPflicht

Query-Parameter

  • workspaceIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/memberships?workspaceId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "role": "super_admin",
      "canApprove": true,
      "invitedBy": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "createdAt": "2026-09-15T10:32:00Z",
      "user": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "email": "kunde@example.de",
        "name": "Sommer-Aktion"
      }
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/orgs/{orgId}/memberships

Mitglied hinzufügen

Pfad-Parameter

  • orgIduuidPflicht

Request-Body (JSON)

  • userIduuidPflicht
  • workspaceIduuid | nulloptional
  • role"org_owner" | "org_admin" | "editor" | "support" | "viewer"Pflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/memberships" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "role": "org_owner"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "role": "super_admin",
  "canApprove": true,
  "invitedBy": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion"
  }
}
PATCH/v1/memberships/{id}

Rolle oder Freigabe ändern

Ändert die Rolle (role) und/oder das Freigabe-Recht (canApprove: darf Kampagnen freigeben) einer Mitgliedschaft; mindestens eines der Felder, sonst 422. Org-weite Admins ändern jede Mitgliedschaft, Inhaber-Mitgliedschaften und die Rolle Inhaber nur Inhaber. Admins eines einzelnen Arbeitsbereichs ändern nur Mitgliedschaften dieses Arbeitsbereichs mit niedrigerer Rolle als ihrer, höchstens bis zur eigenen Rolle und nie auf Inhaber. Nur mit angemeldeter Sitzung.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • role"org_owner" | "org_admin" | "editor" | "support" | "viewer"optional
  • canApprovebooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/memberships/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "role": "org_owner",
  "canApprove": true
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "role": "super_admin",
  "canApprove": true,
  "invitedBy": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion"
  }
}
DELETE/v1/memberships/{id}

Mitglied entfernen

Entfernt eine Mitgliedschaft. Org-weite Inhaber entfernen jede; Admins eines Arbeitsbereichs (auch org-weite Admins) entfernen Mitgliedschaften dieses Arbeitsbereichs mit niedrigerer Rolle als ihrer. Nur mit angemeldeter Sitzung.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/memberships/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)

Einladungen

Einladungen ins Team.

GET/v1/orgs/{orgId}/invitations

Einladungen auflisten

Alle Einladungen der Organisation für org-weite Admins. Mit workspaceId nur die Einladungen dieses Arbeitsbereichs; Admins eines einzelnen Arbeitsbereichs brauchen diesen Filter und sehen nur ihren Arbeitsbereich.

Pfad-Parameter

  • orgIduuidPflicht

Query-Parameter

  • workspaceIduuidoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/invitations?workspaceId=3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "email": "kunde@example.de",
      "name": "Sommer-Aktion",
      "role": "super_admin",
      "canApprove": true,
      "status": "pending",
      "invitedBy": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "createdAt": "2026-09-15T10:32:00Z",
      "expiresAt": "2026-09-15T10:32:00Z",
      "acceptedAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/orgs/{orgId}/invitations

Person einladen

Lädt eine Person per E-Mail ein, org-weit oder in einen Arbeitsbereich (workspaceId), optional mit Namen (name, Anrede in der Mail) und als Freigeber (canApprove: darf Kampagnen freigeben). Org-weite Admins laden überall ein, Inhaber nur durch Inhaber. Admins eines einzelnen Arbeitsbereichs laden nur dorthin ein, höchstens mit der eigenen Rolle und nie als Inhaber; ohne workspaceId 403. Nur mit angemeldeter Sitzung.

Pfad-Parameter

  • orgIduuidPflicht

Request-Body (JSON)

  • emailemailPflicht
  • namestringoptional

    1–120 Zeichen

  • role"org_owner" | "org_admin" | "editor" | "support" | "viewer"Pflicht
  • workspaceIduuid | nulloptional
  • canApprovebooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/invitations" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "kunde@example.de",
  "name": "Sommer-Aktion",
  "role": "org_owner",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "canApprove": true
}'
Antwort200
{
  "invitation": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "role": "super_admin",
    "canApprove": true,
    "status": "pending",
    "invitedBy": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "createdAt": "2026-09-15T10:32:00Z",
    "expiresAt": "2026-09-15T10:32:00Z",
    "acceptedAt": "2026-09-15T10:32:00Z"
  },
  "acceptUrl": "https://example.de/hook",
  "emailQueued": true,
  "emailProblem": "kunde@example.de"
}
GET/v1/invitations/by-token/{token}

Einladung per Token lesen

Pfad-Parameter

  • tokenstringPflicht

Antworten

  • 200OK
  • 404Nicht gefunden
  • 410Nicht mehr gültig
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/invitations/by-token/{token}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "email": "kunde@example.de",
  "name": "Sommer-Aktion",
  "role": "text",
  "canApprove": true,
  "org": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "workspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "existingUser": true
}
POST/v1/invitations/accept

Einladung annehmen

Setzt Passwort und legt die Mitgliedschaft an; AGB-Zustimmung ist Pflicht.

Request-Body (JSON)

  • tokenstringPflicht
  • passwordstringoptional

    10–∞ Zeichen

  • namestringoptional

    1–120 Zeichen

  • acceptTermsbooleanoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 410Nicht mehr gültig
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/invitations/accept" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "token": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx",
  "password": "text",
  "name": "Sommer-Aktion",
  "acceptTerms": true
}'
Antwort200
{
  "token": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "scopes": [
      "text"
    ],
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "user": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "email": "kunde@example.de",
    "name": "Sommer-Aktion",
    "isPlatformAdmin": true,
    "accessExpiresAt": "text",
    "tourCompletedAt": "text"
  },
  "activeOrg": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "activeOrgRole": "super_admin",
  "activeOrgWideRole": "super_admin",
  "mfaEnrolled": true,
  "activeWorkspace": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "slug": "sommer-aktion",
    "name": "Sommer-Aktion"
  },
  "availableWorkspaces": [
    {
      "org": {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "name": "Sommer-Aktion"
      },
      "workspaces": [
        {
          "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
          "slug": "sommer-aktion",
          "name": "Sommer-Aktion"
        }
      ]
    }
  ],
  "impersonation": {
    "superAdminUserId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "expiresAt": "2026-09-15T10:32:00Z",
    "mode": "read_only"
  },
  "customerMode": {
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "editUnlockedUntil": "2026-09-15T10:32:00Z",
    "unlockMinutes": 1
  }
}
DELETE/v1/invitations/{id}

Einladung zurückziehen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/invitations/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)

Wallet-Zertifikate

Apple- und Google-Zertifikate der Organisation.

GET/v1/orgs/{orgId}/wallet-credentials

Zertifikate auflisten

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/wallet-credentials" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "kind": "apple",
      "environment": "development",
      "metadata": {},
      "certExpiresAt": "text",
      "certStatus": "ok",
      "isPlatformDefault": true,
      "pushable": true,
      "warnings": [
        "sandbox_environment"
      ],
      "uploadedById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "createdAt": "2026-09-15T10:32:00Z",
      "revokedAt": "2026-09-15T10:32:00Z"
    }
  ],
  "pagination": {
    "nextCursor": "text",
    "hasMore": true
  }
}
POST/v1/orgs/{orgId}/wallet-credentials

Zertifikat hochladen

Apple: Pass-Type-ID-Zertifikat plus Schlüssel; Google: Service-Account-JSON mit Issuer-ID. Verschlüsselt gespeichert.

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 413Zu groß
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/wallet-credentials" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "apple",
  "environment": "development",
  "metadata": {
    "passTypeId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "teamId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "certExpiresAt": "text",
    "organizationName": "Sommer-Aktion",
    "issuerId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "serviceAccountEmail": "kunde@example.de",
    "projectId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "certExpiresAt": "text",
  "certStatus": "ok",
  "isPlatformDefault": true,
  "pushable": true,
  "warnings": [
    "sandbox_environment"
  ],
  "uploadedById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "revokedAt": "2026-09-15T10:32:00Z"
}
GET/v1/orgs/{orgId}/wallet-config

Wallet-Konfiguration lesen

Was für Apple und Google aktiv ist: eigene Zertifikate oder die doWallet-Standardkonfiguration.

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/wallet-config" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "apple": {
    "own": true,
    "platformDefault": true
  },
  "google": {
    "own": true,
    "platformDefault": true
  },
  "blessed": true,
  "blessedAt": "text"
}
POST/v1/orgs/{orgId}/apple-csr

Apple-CSR erzeugen

doWallet erzeugt Schlüssel und Zertifikatsanforderung; du lädst die CSR im Apple-Developer-Portal hoch.

Pfad-Parameter

  • orgIduuidPflicht

Request-Body (JSON)

  • commonNamestringoptional

    0–120 Zeichen

  • emailemailoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/apple-csr" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "commonName": "Sommer-Aktion",
  "email": "kunde@example.de"
}'
Antwort200
{
  "csrPem": "text"
}
POST/v1/orgs/{orgId}/apple-csr/complete

Apple-Zertifikat einspielen

Das von Apple ausgestellte Zertifikat zur vorher erzeugten CSR.

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/apple-csr/complete" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "apple",
  "environment": "development",
  "metadata": {
    "passTypeId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "teamId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "certExpiresAt": "text",
    "organizationName": "Sommer-Aktion",
    "issuerId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "serviceAccountEmail": "kunde@example.de",
    "projectId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "certExpiresAt": "text",
  "certStatus": "ok",
  "isPlatformDefault": true,
  "pushable": true,
  "warnings": [
    "sandbox_environment"
  ],
  "uploadedById": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "createdAt": "2026-09-15T10:32:00Z",
  "revokedAt": "2026-09-15T10:32:00Z"
}
DELETE/v1/wallet-credentials/{id}

Zertifikat entfernen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/wallet-credentials/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)

E-Mail

E-Mail-Einstellungen und Test-Versand.

POST/v1/workspaces/{workspaceId}/emails/preview

E-Mail-Vorschau rendern

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • templateKind"announcement" | "offer" | "winback" | "event_reminder"Pflicht
  • templateIduuidPflicht
  • subjectstringoptional

    0–160 Zeichen

  • bodystringoptional

    0–4000 Zeichen

  • slotsobjectoptional
  • ctaLabelstringoptional

    0–60 Zeichen

  • ctaUrlurioptional
  • offerValuestringoptional

    0–40 Zeichen

  • imageAssetIduuidoptional
  • includeWalletLinkbooleanoptional
  • localestringoptional

    0–10 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/emails/preview" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "templateKind": "announcement",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "subject": "text",
  "body": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "slots": {
    "ctaLabel": "Sommer-Aktion",
    "ctaUrl": "https://example.de/hook",
    "offerValue": "text",
    "imageAssetId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "includeWalletLink": true,
  "locale": "de"
}'
Antwort200
{
  "subject": "text",
  "html": "text",
  "text": "Heute 20 % auf alles. Nur bis Ladenschluss."
}
POST/v1/workspaces/{workspaceId}/emails/test

Test-E-Mail senden

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • templateKind"announcement" | "offer" | "winback" | "event_reminder"Pflicht
  • templateIduuidPflicht
  • subjectstringoptional

    0–160 Zeichen

  • bodystringoptional

    0–4000 Zeichen

  • slotsobjectoptional
  • ctaLabelstringoptional

    0–60 Zeichen

  • ctaUrlurioptional
  • offerValuestringoptional

    0–40 Zeichen

  • imageAssetIduuidoptional
  • includeWalletLinkbooleanoptional
  • localestringoptional

    0–10 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 502Default Response
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/emails/test" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "templateKind": "announcement",
  "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "subject": "text",
  "body": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "slots": {
    "ctaLabel": "Sommer-Aktion",
    "ctaUrl": "https://example.de/hook",
    "offerValue": "text",
    "imageAssetId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  },
  "includeWalletLink": true,
  "locale": "de"
}'
Antwort200
{
  "sent": true,
  "to": "text"
}

Support

Support-Tickets.

GET/v1/orgs/{orgId}/support/tickets

Support-Tickets der Organisation

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/support/tickets" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
[
  {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "subject": "text",
    "status": "open",
    "priority": "low",
    "createdByName": "Sommer-Aktion",
    "createdByEmail": "kunde@example.de",
    "messageCount": 1,
    "createdAt": "text",
    "lastReplyAt": "text",
    "isTest": true
  }
]
POST/v1/orgs/{orgId}/support/tickets

Support-Ticket eröffnen

Pfad-Parameter

  • orgIduuidPflicht

Request-Body (JSON)

  • subjectstringPflicht

    2–160 Zeichen

  • bodystringPflicht

    2–5000 Zeichen

  • priority"low" | "normal" | "high"optional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/support/tickets" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "subject": "text",
  "body": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "priority": "low"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}
GET/v1/support/tickets

Alle Tickets (Plattform)

Query-Parameter

  • statusopen | in_progress | resolvedoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/support/tickets?status=open" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
[
  {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "subject": "text",
    "status": "open",
    "priority": "low",
    "createdByName": "Sommer-Aktion",
    "createdByEmail": "kunde@example.de",
    "messageCount": 1,
    "createdAt": "text",
    "lastReplyAt": "text",
    "isTest": true
  }
]
GET/v1/support/tickets/{id}

Ticket lesen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/support/tickets/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "ticket": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "orgName": "Sommer-Aktion",
    "subject": "text",
    "status": "open",
    "priority": "low",
    "createdByName": "Sommer-Aktion",
    "createdByEmail": "kunde@example.de",
    "messageCount": 1,
    "createdAt": "text",
    "lastReplyAt": "text",
    "isTest": true
  },
  "messages": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "authorName": "Sommer-Aktion",
      "body": "Heute 20 % auf alles. Nur bis Ladenschluss.",
      "staff": true,
      "createdAt": "text"
    }
  ]
}
PATCH/v1/support/tickets/{id}

Ticket-Status ändern

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • status"open" | "in_progress" | "resolved"optional
  • priority"low" | "normal" | "high"optional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/support/tickets/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "status": "open",
  "priority": "low"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "orgName": "Sommer-Aktion",
  "subject": "text",
  "status": "open",
  "priority": "low",
  "createdByName": "Sommer-Aktion",
  "createdByEmail": "kunde@example.de",
  "messageCount": 1,
  "createdAt": "text",
  "lastReplyAt": "text",
  "isTest": true
}
POST/v1/support/tickets/{id}/messages

Nachricht im Ticket senden

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • bodystringPflicht

    1–5000 Zeichen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/support/tickets/{id}/messages" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "body": "Heute 20 % auf alles. Nur bis Ladenschluss."
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "authorName": "Sommer-Aktion",
  "body": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "staff": true,
  "createdAt": "text"
}

Datenschutz

Datenexport, Löschung und Betroffenenrechte.

GET/v1/orgs/{orgId}/avv.pdf

Auftragsverarbeitungsvertrag (PDF)

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/avv.pdf" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
null
POST/v1/orgs/{orgId}/data-export

Datenexport der Organisation anfordern

DSGVO Art. 20. Asynchron; der Download erscheint unter data-exports.

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/data-export" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "org",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "status": "queued",
  "archivePath": "text",
  "bytesWritten": "text",
  "error": "text",
  "downloadUrl": "https://example.de/hook",
  "createdAt": "2026-09-15T10:32:00Z",
  "startedAt": "2026-09-15T10:32:00Z",
  "completedAt": "2026-09-15T10:32:00Z",
  "expiresAt": "2026-09-15T10:32:00Z"
}
GET/v1/orgs/{orgId}/data-exports

Datenexporte auflisten

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/data-exports" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "kind": "org",
      "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "status": "queued",
      "archivePath": "text",
      "bytesWritten": "text",
      "error": "text",
      "downloadUrl": "https://example.de/hook",
      "createdAt": "2026-09-15T10:32:00Z",
      "startedAt": "2026-09-15T10:32:00Z",
      "completedAt": "2026-09-15T10:32:00Z",
      "expiresAt": "2026-09-15T10:32:00Z"
    }
  ]
}
POST/v1/users/me/data-export

Eigenen Datenexport anfordern

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/users/me/data-export" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "org",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "status": "queued",
  "archivePath": "text",
  "bytesWritten": "text",
  "error": "text",
  "downloadUrl": "https://example.de/hook",
  "createdAt": "2026-09-15T10:32:00Z",
  "startedAt": "2026-09-15T10:32:00Z",
  "completedAt": "2026-09-15T10:32:00Z",
  "expiresAt": "2026-09-15T10:32:00Z"
}
GET/v1/orgs/{orgId}/data-deletion

Geplante Löschung der Organisation lesen

Die eingeplante Löschung mit Datum oder null. Nur Inhaber der Organisation.

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/orgs/{orgId}/data-deletion" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "pending": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "kind": "org",
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "status": "queued",
    "scheduledFor": "2026-09-15T10:32:00Z",
    "cancelledAt": "2026-09-15T10:32:00Z",
    "executedAt": "2026-09-15T10:32:00Z",
    "createdAt": "2026-09-15T10:32:00Z"
  }
}
POST/v1/orgs/{orgId}/data-deletion

Löschung der Organisation einplanen

Mit Karenzzeit; bis dahin abbrechbar. Rechnungen bleiben gemäß Aufbewahrungspflicht.

Pfad-Parameter

  • orgIduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/orgs/{orgId}/data-deletion" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "org",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "status": "queued",
  "scheduledFor": "2026-09-15T10:32:00Z",
  "cancelledAt": "2026-09-15T10:32:00Z",
  "executedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}
GET/v1/users/me/data-deletion

Geplante Löschung des eigenen Kontos lesen

Die eingeplante Löschung mit Datum oder null, auf jedem Gerät gleich.

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/users/me/data-deletion" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "pending": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "kind": "org",
    "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "status": "queued",
    "scheduledFor": "2026-09-15T10:32:00Z",
    "cancelledAt": "2026-09-15T10:32:00Z",
    "executedAt": "2026-09-15T10:32:00Z",
    "createdAt": "2026-09-15T10:32:00Z"
  }
}
POST/v1/users/me/data-deletion

Eigenes Konto löschen

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/users/me/data-deletion" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "kind": "org",
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "userId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "status": "queued",
  "scheduledFor": "2026-09-15T10:32:00Z",
  "cancelledAt": "2026-09-15T10:32:00Z",
  "executedAt": "2026-09-15T10:32:00Z",
  "createdAt": "2026-09-15T10:32:00Z"
}
POST/v1/data-deletions/{id}/cancel

Löschung abbrechen

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/data-deletions/{id}/cancel" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)

Öffentlich und Geräte

Öffentliche Endpunkte

Öffentliche Endpunkte ohne Token: Landing-Seiten, Pass-Download, Pitch-Demos.

POST/v1/leads

Demo-Anfrage senden

Kontaktformular der Website. Einwilligung ist Pflicht.

Request-Body (JSON)

  • namestringPflicht

    1–200 Zeichen

  • emailemailPflicht
  • companystringoptional

    0–200 Zeichen

  • planInterest"free" | "growth" | "enterprise"optional
  • messagestringoptional

    0–4000 Zeichen

  • sourcestringoptional

    0–80 Zeichen

  • consentbooleanoptional
  • websitestringoptional
  • captchaTokenstringoptional

    1–4096 Zeichen

Antworten

  • 200OK
  • 400Ungültige Anfrage
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/leads" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "email": "kunde@example.de",
  "company": "text",
  "planInterest": "free",
  "message": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "source": "text",
  "consent": true,
  "website": "text",
  "captchaToken": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx"
}'
Antwort200
{
  "ok": true,
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}
GET/api/public/branding-assets/{orgId}/{file}

Branding-Datei

Pfad-Parameter

  • orgIduuidPflicht
  • filestringPflicht

Antworten

  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/api/public/branding-assets/{orgId}/{file}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
GET/api/public/orgs/{id}/branding

Marke einer Organisation (öffentlich)

Logo, weißes Logo, Farben und Schrift der Organisation, dazu poweredByDoWallet (false nur mit White-Label-Freigabe). Eingefroren oder gelöscht 404.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/api/public/orgs/{id}/branding" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "logoUrl": "https://example.de/hook",
  "logoWhiteUrl": "https://example.de/hook",
  "primaryColor": "#005be7",
  "surfaceColor": "#005be7",
  "textColor": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "mutedColor": "#005be7",
  "fontFamily": "text",
  "fontCssSrc": "https://example.de/hook",
  "appName": "Sommer-Aktion",
  "iconUrl": "https://example.de/hook",
  "name": "Sommer-Aktion",
  "poweredByDoWallet": true
}
GET/api/public/app-brand/{slug}

App-Marke zu einem Kurznamen (öffentlich)

Die geprüfte App-Marke einer Organisation mit White-Label: App-Name, Logos, App-Icon, Akzentfarbe und poweredByDoWallet. Unbekannt, ohne White-Label, nicht von doWallet geprüft, eingefroren, gesperrt oder gelöscht: 404. Nie Support-E-Mail, Texte oder Links.

Pfad-Parameter

  • slugstringPflicht

Antworten

  • 200OK
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/api/public/app-brand/{slug}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "slug": "sommer-aktion",
  "appName": "Sommer-Aktion",
  "logoUrl": "https://example.de/hook",
  "logoWhiteUrl": "https://example.de/hook",
  "iconUrl": "https://example.de/hook",
  "primaryColor": "#005be7",
  "poweredByDoWallet": true
}
GET/api/public/app-brand/by-subdomain/{sub}

App-Marke zu einer Subdomain (öffentlich)

Die geprüfte App-Marke einer Organisation mit White-Label: App-Name, Logos, App-Icon, Akzentfarbe und poweredByDoWallet. Unbekannt, ohne White-Label, nicht von doWallet geprüft, eingefroren, gesperrt oder gelöscht: 404. Nie Support-E-Mail, Texte oder Links. Die Subdomain muss vergeben und aktiv sein.

Pfad-Parameter

  • substringPflicht

Antworten

  • 200OK
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/api/public/app-brand/by-subdomain/{sub}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "slug": "sommer-aktion",
  "appName": "Sommer-Aktion",
  "logoUrl": "https://example.de/hook",
  "logoWhiteUrl": "https://example.de/hook",
  "iconUrl": "https://example.de/hook",
  "primaryColor": "#005be7",
  "poweredByDoWallet": true
}
GET/api/public/branding-assets/workspaces/{workspaceId}/{file}

Logo eines Arbeitsbereichs

Öffentliche Bilddatei des Logos, das POST /v1/workspaces/{id}/branding/logo hochgeladen hat. Unveränderlich, lange zwischenspeicherbar.

Pfad-Parameter

  • workspaceIduuidPflicht
  • filestringPflicht

Antworten

  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/api/public/branding-assets/workspaces/{workspaceId}/{file}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
GET/api/public/branding/by-subdomain/{sub}

Marke zu einer Subdomain (öffentlich)

Löst eine vergebene Subdomain zur Marke der Organisation auf (Logo, weißes Logo, Farben, Schrift, poweredByDoWallet, false nur mit White-Label-Freigabe). Unbekannt, reserviert, eingefroren oder gelöscht 404.

Pfad-Parameter

  • substringPflicht

Antworten

  • 200OK
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/api/public/branding/by-subdomain/{sub}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "orgId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "logoUrl": "https://example.de/hook",
  "logoWhiteUrl": "https://example.de/hook",
  "primaryColor": "#005be7",
  "surfaceColor": "#005be7",
  "textColor": "Heute 20 % auf alles. Nur bis Ladenschluss.",
  "mutedColor": "#005be7",
  "fontFamily": "text",
  "fontCssSrc": "text",
  "poweredByDoWallet": true
}
POST/api/public/claim/{slug}/redeem

Pass über die Landing-Seite ausstellen

Wird von der Landing-Seite aufgerufen und liefert die Wallet-Links für Apple und Google; ein Handy erhält pro Landing-Seite einen Pass. attributes übernimmt nur Felder, die in der Feldliste der Vorlage als über den öffentlichen Link setzbar markiert sind. Kontaktdaten (email, firstName, lastName) speichert doWallet nur mit Einwilligung: consents beantwortet jeden aktiven Zweck des Arbeitsbereichs (GET /p/{slug} nennt sie in landing.consentPurposes), consent: true allein gilt als Zweck service. Fehlt ein Pflicht-Zweck, antwortet die Route 422 consent_required mit fields je Zweck.

Pfad-Parameter

  • slugstringPflicht

Query-Parameter

  • utm_sourcestringoptional
  • utm_mediumstringoptional
  • utm_campaignstringoptional
  • utm_termstringoptional
  • utm_contentstringoptional

Request-Body (JSON)

  • emailemailoptional
  • namestringoptional

    0–120 Zeichen

  • firstNamestringoptional

    1–80 Zeichen

  • lastNamestringoptional

    1–80 Zeichen

  • consentbooleanoptional
  • consentsobject[]optional

    Einwilligung je Zweck, z. B. [{ key: "service", given: true }, { key: "marketing_email", given: false }]. Mit E-Mail und Vorname müssen alle aktiven Pflicht-Zwecke gegeben sein (sonst 422 consent_required). Ohne consents gilt consent: true als service. · 0–20 Einträge

  • keystringPflicht
  • givenbooleanPflicht
  • platform"apple" | "google" | "both"optional
  • attributesobjectoptional

    Nur Felder, die die Feldliste der Vorlage mit fromPublicClaim freigibt. Andere Schlüssel werden verworfen, die Antwort bleibt 200. Werte außerhalb des Feldtyps: 422. Kontaktdaten nur über email, firstName, lastName mit consent: true.

  • utmobjectoptional
  • sourcestringoptional
  • mediumstringoptional
  • campaignstringoptional
  • termstringoptional
  • contentstringoptional
  • attributionKeystringoptional

    8–128 Zeichen

  • handoffbooleanoptional

    Die Landing-Seite hat den Besucher aus einem In-App-Browser an Safari oder Chrome übergeben und löst dort ein. Nur für die Auswertung.

Antworten

  • 200OK
  • 402Default Response
  • 404Nicht gefunden
  • 409Konflikt
  • 410Nicht mehr gültig
  • 422Validierung fehlgeschlagen
  • 423Default Response
  • 429Rate-Limit
  • 503Nicht verfügbar
Anfragecurl
curl -X POST "https://api.dowallet.dev/api/public/claim/{slug}/redeem?utm_source=text&utm_medium=text&utm_campaign=text" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "kunde@example.de",
  "name": "Sommer-Aktion",
  "firstName": "Sommer-Aktion",
  "lastName": "Sommer-Aktion",
  "consent": true,
  "consents": [
    {
      "key": "text",
      "given": true
    }
  ],
  "platform": "both",
  "attributes": {},
  "utm": {
    "source": "text",
    "medium": "text",
    "campaign": "text",
    "term": "text",
    "content": "text"
  },
  "attributionKey": "text",
  "handoff": true
}'
Antwort200
{
  "passId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "serial": "ABC123456",
  "code": "text",
  "platform": "apple",
  "apple": {
    "downloadUrl": "https://example.de/hook"
  },
  "google": {
    "saveUrl": "https://example.de/hook"
  }
}
POST/api/public/passes/{serial}/link-customer

Kontaktdaten mit Einwilligung hinterlegen

Name und E-Mail zu einem Pass, autorisiert über den signierten Link aus dem Pass. Einwilligung je Zweck wie auf der Landing-Seite: consents (jeder aktive Pflicht-Zweck gegeben, sonst 422 consent_required), oder consent: true für den Zweck service.

Pfad-Parameter

  • serialstringPflicht

Query-Parameter

  • tstringPflicht

Request-Body (JSON)

  • emailemailPflicht

    0–240 Zeichen

  • firstNamestringPflicht

    1–80 Zeichen

  • lastNamestringoptional

    0–80 Zeichen

  • consentbooleanoptional
  • consentsobject[]optional

    0–20 Einträge

  • keystringPflicht
  • givenbooleanPflicht
  • locale"de" | "en" | "fr"optional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/api/public/passes/{serial}/link-customer?t=text" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "email": "kunde@example.de",
  "firstName": "Sommer-Aktion",
  "lastName": "Sommer-Aktion",
  "consent": true,
  "consents": [
    {
      "key": "text",
      "given": true
    }
  ],
  "locale": "de"
}'
Antwort200
{
  "ok": true,
  "customerId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
}
POST/api/public/scanner/pair

Handy als Scanner-Gerät koppeln

Löst einen Kopplungscode ein (aus „Scanner-Gerät anlegen“ oder „Neuen Kopplungscode ausgeben“) und liefert einmalig den Geräte-Token dwsd_… samt Name, Arbeitsbereich, Standort und erlaubten Aktionen. Der Token erreicht nur den Scanner (GET …/scan/lookup, POST …/scans), jede andere Route antwortet 403 device_not_allowed. Falscher, abgelaufener oder schon benutzter Code: 404 pair_code_invalid. Ohne Anmeldung; höchstens 30 Versuche je 5 Minuten und IP. Ist der Scanner für die Organisation nicht eingeschaltet (nur doWallet schaltet ihn ein): 403 feature_disabled, der Code bleibt gültig.

Request-Body (JSON)

  • codestringPflicht

    1–32 Zeichen

Antworten

  • 200OK
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
  • 429Rate-Limit
Anfragecurl
curl -X POST "https://api.dowallet.dev/api/public/scanner/pair" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "code": "text"
}'
Antwort200
{
  "token": "dwlt_xxxxxxxxxxxxxxxxxxxxxxxx",
  "device": {
    "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "name": "Sommer-Aktion",
    "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "workspaceName": "Sommer-Aktion",
    "locationId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
    "locationName": "Sommer-Aktion",
    "allowedActions": [
      "redeem"
    ],
    "orgSlug": "sommer-aktion"
  }
}

Weitere

promotions

GET/v1/workspaces/{workspaceId}/promotions

Aktionen eines Workspace

Alle Aktionen des Workspace mit Zustand (draft ohne Start, scheduled Start nach heute, running, ended Ende vor heute, archived), heute in der Zeitzone des Workspace, und Zählern je Art der Teile. passesIssued und activePasses zählen die Pässe, deren aktuelle Vorlage zur Aktion gehört. year filtert auf Aktionen, deren Zeitraum das Jahr berührt (ohne Start: das Jahr der Anlage; ohne Ende: bis heute). years nennt alle Jahre aller Aktionen, absteigend. q sucht im Namen. Neueste zuerst (Start, ohne Start die Anlage). Jede Rolle im Workspace.

Pfad-Parameter

  • workspaceIduuidPflicht

Query-Parameter

  • yearintegeroptional
  • qstringoptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/workspaces/{workspaceId}/promotions?year=2000&q=sommer" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "data": [
    {
      "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
      "name": "Sommer-Aktion",
      "startsOn": "text",
      "endsOn": "text",
      "state": "draft",
      "archivedAt": "text",
      "createdAt": "text",
      "updatedAt": "text",
      "counts": {
        "templates": 1,
        "landingPages": 1,
        "codeLists": 1,
        "campaigns": 1,
        "passesIssued": 1,
        "activePasses": 1
      }
    }
  ],
  "years": [
    1
  ]
}
POST/v1/workspaces/{workspaceId}/promotions

Aktion anlegen

Name (höchstens 120 Zeichen) und optional Zeitraum als Kalendertage; Ende vor Start ist 422 ends_before_start. Ab der Rolle editor.

Pfad-Parameter

  • workspaceIduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–120 Zeichen

  • startsOnstring | nulloptional
  • endsOnstring | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/workspaces/{workspaceId}/promotions" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "startsOn": "text",
  "endsOn": "text"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "startsOn": "text",
  "endsOn": "text",
  "state": "draft",
  "archivedAt": "text",
  "createdAt": "text",
  "updatedAt": "text",
  "counts": {
    "templates": 1,
    "landingPages": 1,
    "codeLists": 1,
    "campaigns": 1,
    "passesIssued": 1,
    "activePasses": 1
  }
}
GET/v1/promotions/{id}

Aktion mit ihren Teilen

Die Aktion wie in der Liste und parts: ihre Pass-Vorlagen, Landing-Seiten, Code-Listen (ohne gelöschte) und Kampagnen. Ohne Zugang zum Workspace 404 promotion_not_found.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X GET "https://api.dowallet.dev/v1/promotions/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "startsOn": "text",
  "endsOn": "text",
  "state": "draft",
  "archivedAt": "text",
  "createdAt": "text",
  "updatedAt": "text",
  "counts": {
    "templates": 1,
    "landingPages": 1,
    "codeLists": 1,
    "campaigns": 1,
    "passesIssued": 1,
    "activePasses": 1
  },
  "parts": {
    "templates": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "name": "Sommer-Aktion",
        "status": "active",
        "archivedAt": "text"
      }
    ],
    "landingPages": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "slug": "sommer-aktion",
        "active": true,
        "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "isTest": true
      }
    ],
    "codeLists": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "name": "Sommer-Aktion",
        "templateId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "totalCount": 1,
        "assignedCount": 1
      }
    ],
    "campaigns": [
      {
        "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
        "name": "Sommer-Aktion",
        "status": "active",
        "scheduleAt": "text"
      }
    ]
  }
}
PATCH/v1/promotions/{id}

Aktion ändern

Name und Zeitraum; null leert ein Datum. Ende vor Start 422 ends_before_start, eine archivierte Aktion 409 promotion_archived. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringoptional

    1–120 Zeichen

  • startsOnstring | nulloptional
  • endsOnstring | nulloptional

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X PATCH "https://api.dowallet.dev/v1/promotions/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "startsOn": "text",
  "endsOn": "text"
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "startsOn": "text",
  "endsOn": "text",
  "state": "draft",
  "archivedAt": "text",
  "createdAt": "text",
  "updatedAt": "text",
  "counts": {
    "templates": 1,
    "landingPages": 1,
    "codeLists": 1,
    "campaigns": 1,
    "passesIssued": 1,
    "activePasses": 1
  }
}
DELETE/v1/promotions/{id}

Aktion löschen

Nur eine Aktion ohne Teile (sonst 409 promotion_not_empty), etwa nach einem Tippfehler; sonst archivieren. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 204Kein Inhalt
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 409Konflikt
Anfragecurl
curl -X DELETE "https://api.dowallet.dev/v1/promotions/{id}" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort204
(kein Inhalt)
POST/v1/promotions/{id}/duplicate

Aktion kopieren (aus Vorjahr)

Legt eine neue Aktion im selben Workspace an, mit Name und optional Zeitraum aus dem Body (ohne Zeitraum ein Entwurf; Ende vor Start 422 ends_before_start). Kopiert werden die nicht archivierten Pass-Vorlagen der Aktion als neuer Entwurf (Version 1 aus dem Stand des Editors, mit Treue- und Einlöse-Regel und Standorten) und ihre Landing-Seiten ohne Test-Seiten (neuer Slug, inaktiv, auf die kopierte Vorlage zeigend, sonst auf dieselbe Vorlage, ohne Code-Liste, Ablauf und Kanäle). Mit templateIds und landingPageIds nur die gewählten (ein Teil, das nicht zur Aktion gehört, 422 part_not_in_promotion, dann entsteht nichts); eine gewählte Seite ohne gewählte Vorlage zeigt weiter auf die alte Vorlage. Nie kopiert: Code-Listen, Kampagnen, Zielgruppen, Treue-Automatik; eine Wertquelle aus Code-Listen wird null. Die Quelle bleibt unverändert, auch eine archivierte. copied nennt, wie viele Vorlagen und Landing-Seiten entstanden. Ab der Rolle editor.

Pfad-Parameter

  • iduuidPflicht

Request-Body (JSON)

  • namestringPflicht

    1–120 Zeichen

  • startsOnstring | nulloptional
  • endsOnstring | nulloptional
  • templateIdsuuid[]optional

    Nur diese Pass-Vorlagen der Aktion kopieren; fehlt = alle nicht archivierten, [] = keine. · 0–500 Einträge

  • landingPageIdsuuid[]optional

    Nur diese Landing-Seiten der Aktion kopieren; fehlt = alle ohne Test-Seiten, [] = keine. · 0–500 Einträge

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
  • 422Validierung fehlgeschlagen
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/promotions/{id}/duplicate" \
  -H "Authorization: Bearer $DOWALLET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Sommer-Aktion",
  "startsOn": "text",
  "endsOn": "text",
  "templateIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ],
  "landingPageIds": [
    "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01"
  ]
}'
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "startsOn": "text",
  "endsOn": "text",
  "state": "draft",
  "archivedAt": "text",
  "createdAt": "text",
  "updatedAt": "text",
  "counts": {
    "templates": 1,
    "landingPages": 1,
    "codeLists": 1,
    "campaigns": 1,
    "passesIssued": 1,
    "activePasses": 1
  },
  "copied": {
    "templates": 1,
    "landingPages": 1
  }
}
POST/v1/promotions/{id}/archive

Aktion archivieren

Archiviert die Aktion: ihre Pässe (aktuelle Vorlage in der Aktion, Test- und Demo-Pässe eingeschlossen) laufen sofort ab, wie beim Archivieren eines Workspace (valid_until = jetzt, Status bleibt active, nichts wird entwertet, Push an Apple und Google). Landing-Seiten der Aktion gehen aus, geplante Kampagnen in den Entwurf, aktive Automatisierungen ihrer Vorlagen auf pausiert. Danach stellen ihre Vorlagen nichts aus (409 promotion_archived), und ihre Teile lassen sich nicht zuordnen oder herausnehmen. expiredPasses zählt die Pässe, die jetzt abgelaufen sind; wiederholt ohne Wirkung (0). Ab org_admin im Workspace, nur mit Browser-Sitzung.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/promotions/{id}/archive" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "startsOn": "text",
  "endsOn": "text",
  "state": "draft",
  "archivedAt": "text",
  "createdAt": "text",
  "updatedAt": "text",
  "counts": {
    "templates": 1,
    "landingPages": 1,
    "codeLists": 1,
    "campaigns": 1,
    "passesIssued": 1,
    "activePasses": 1
  },
  "expiredPasses": 1
}
POST/v1/promotions/{id}/unarchive

Aktion reaktivieren

Öffnet eine archivierte Aktion wieder: ihre Vorlagen stellen wieder aus, ihre Teile lassen sich wieder ändern. Abgelaufene Pässe bleiben abgelaufen, Landing-Seiten bleiben aus, Kampagnen und Automatisierungen bleiben, wie sie sind. Ab org_admin im Workspace, nur mit Browser-Sitzung.

Pfad-Parameter

  • iduuidPflicht

Antworten

  • 200OK
  • 401Nicht angemeldet
  • 403Keine Berechtigung
  • 404Nicht gefunden
Anfragecurl
curl -X POST "https://api.dowallet.dev/v1/promotions/{id}/unarchive" \
  -H "Authorization: Bearer $DOWALLET_TOKEN"
Antwort200
{
  "id": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "workspaceId": "3f2c1b7e-8d4a-4c6e-9b1f-2a7d5e6c9f01",
  "name": "Sommer-Aktion",
  "startsOn": "text",
  "endsOn": "text",
  "state": "draft",
  "archivedAt": "text",
  "createdAt": "text",
  "updatedAt": "text",
  "counts": {
    "templates": 1,
    "landingPages": 1,
    "codeLists": 1,
    "campaigns": 1,
    "passesIssued": 1,
    "activePasses": 1
  }
}