{
  "openapi": "3.0.3",
  "info": {
    "title": "Mailpro™ SMS API",
    "version": "2",
    "description": "Die Mailpro™ SMS-API ermöglicht Ihnen die programmatische Verwaltung von Telefonkontaktlisten,\nRufnummern sowie den Versand von Massen- oder einzelnen SMS-Nachrichten.\n\n## Authentifizierung\n\nJeder Endpunkt akzeptiert **drei Authentifizierungsmethoden**. Wählen Sie diejenige, die zu Ihrem\nTechnologie-Stack passt.\n\n- **OAuth 2.0** — scope-basierte, widerrufbare Token für Drittanbieter-Apps und\n  Integrationsplattformen (Zapier, Make, n8n). **OAuth-Token werden pro Endpunkt\n  durch Scopes eingeschränkt** (siehe unten).\n- **Bearer JWT** (Legacy) — ein HMAC-Token von `POST /token`, ohne Scopes.\n- **id_client + api_key** (Legacy) — Kunden-ID + API-Schlüssel.\n\n> Legacy-Bearer-JWT sowie id_client+api_key funktionieren unverändert weiter und unterliegen\n> **keiner** Scope-Einschränkung. Lediglich OAuth-2.0-Access-Token sind den\n> endpunktspezifischen Scope-Prüfungen unterworfen, die bei jeder Operation unten aufgeführt sind.\n\n### Methode 1 — OAuth 2.0 (empfohlen für Integrationen)\n\nMailpro betreibt **einen einzigen** OAuth-2.0-Autorisierungsserver für sämtliche APIs unter einer\neinheitlichen, versionsneutralen Adresse: **`https://api.mailpro.com/oauth/`**. Es gibt\nkeinen versionsspezifischen OAuth-Endpunkt — Sie erhalten ein Token über `/oauth/token`, und\n**dasselbe** Token funktioniert auf dieser SMS-API, auf der CRM v3 und auf der Email v2. Welche\nEndpunkte es ansprechen darf, wird durch die **Scopes** des Tokens bestimmt, nicht durch die\nAPI-Basis-URL. Aussteller (`iss`-Claim): `https://api.mailpro.com/oauth/`.\n\n| Endpunkt | URL |\n|----------|-----|\n| Authorize | `GET https://api.mailpro.com/oauth/authorize` |\n| Token / Refresh | `POST https://api.mailpro.com/oauth/token` |\n| JWKS | `GET https://api.mailpro.com/oauth/.well-known/jwks` |\n| Discovery | `GET https://api.mailpro.com/oauth/.well-known/openid-configuration` |\n\nGrant-Typen: `authorization_code` **+ PKCE (S256, verpflichtend)**, `client_credentials`,\n`refresh_token` (Rotation). Lebensdauer des Access-Tokens **20 Min.**; Refresh-Token **30 Tage**\n(gleitend, Einmalverwendung); Authorization Code **60 Sek.**.\n\n**Schnellstart — Token abrufen und diese API aufrufen** (Platzhalter ersetzen; ein echtes Secret\nniemals committen):\n\n```bash\ncurl -X POST https://api.mailpro.com/oauth/token \\\n  -H \"Content-Type: application/x-www-form-urlencoded\" \\\n  -d \"grant_type=client_credentials\" \\\n  -d \"client_id=YOUR_CLIENT_ID\" \\\n  -d \"client_secret=YOUR_CLIENT_SECRET\" \\\n  -d \"scope=sms:send sms:read\"\n```\n\nRufen Sie diese API anschließend mit `Authorization: Bearer ACCESS_TOKEN` auf. Dasselbe Token\nfunktioniert auf den APIs CRM v3 und Email v2. Ein Token, dem der für einen Endpunkt erforderliche\nScope fehlt, erhält **403 `insufficient_scope`**. Die vollständige Flow-Beschreibung und der\nScope-Katalog sind in den **CRM v3**-API-Dokumenten unter \"Authentifizierung\" zu finden. Für die\nSMS-API relevante Scopes: `sms:send`, `sms:read`, `sms:contacts:read`, `sms:contacts:write`,\n`account:read`.\n\n### Methode 2 — Bearer JWT (Legacy)\n\n```\nAuthorization: Bearer <access_token>\n```\n\nToken über `POST /token` abrufen (formularkodiert, OAuth2 Password Grant):\n\n```\nPOST https://api.mailpro.com/sms/token\nContent-Type: application/x-www-form-urlencoded\n\ngrant_type=password&username=YOUR_USERNAME&password=YOUR_API_KEY\n```\n\nDasselbe Token ist auch auf der CRM-API v3 sowie auf der Email v2 API gültig —\neinmalige Authentifizierung, beliebiger API-Aufruf. Token sind standardmäßig **30 Tage** gültig;\nverwenden Sie `grant_type=refresh_token`, um sie ohne erneute Authentifizierung zu verlängern. Ohne\nScopes — für installierbare Integrationen wird OAuth 2.0 bevorzugt.\n\n### Methode 3 — id_client + api_key\n\nZwei Anmeldedaten:\n\n| Parameter   | Typ     | Beschreibung |\n|-------------|---------|-------------|\n| `id_client` | integer | Ihre numerische Mailpro-Kunden-ID, zu finden unter **Einstellungen → API-Zugang** |\n| `api_key`   | string  | Ihr API-Schlüssel (GUID-Format), zu finden unter **Einstellungen → API-Zugang** |\n\nÜbermitteln Sie diese an einer der folgenden Stellen — wählen Sie eine:\n\n1. **HTTP-Header (empfohlen)** — `id_client: 12345` und `api_key: a1b2c3d4-…`.\n   URLs werden von Webservern, CDNs und Proxys protokolliert, sodass ein Schlüssel in der\n   Query-Zeichenkette in Zugriffsprotokolle gelangen kann. Header werden nicht protokolliert.\n2. **Query-String (Legacy, weiterhin funktionsfähig)** — `?id_client=12345&api_key=…`.\n   Zur Abwärtskompatibilität mit bestehenden Integrationen erhalten. Wechseln Sie so bald wie\n   möglich zu Headern.\n3. **JSON-/Formular-Body (nur POST)** — dieselben Feldnamen innerhalb des Request-Bodys.\n\nWerden Anmeldedaten an mehr als einer Stelle übermittelt, **gewinnt der Header**.\n\n### OAuth-Scope-Durchsetzung pro Endpunkt (SMS)\n\nFür OAuth-ausgestellte Token erfordert jede Endpunktgruppe einen Scope (Legacy-Authentifizierung\nist davon ausgenommen). Jede Operation listet ihren Scope unter **Authorization** auf. Übersicht:\n\n| Endpunkte | Erforderlicher Scope |\n|-----------|----------------|\n| `/send/*` (Massenversand, Einzelversand, Planung) | `sms:send` |\n| `/history/list`, `/credit/get` | `sms:read` |\n| `/phone/list`, `/list/list` | `sms:contacts:read` |\n| `/phone/{add,edit,del}`, `/list/{edit,del}`, `/import/upload` | `sms:contacts:write` |\n| `/account/limits` | `account:read` |\n\n> `POST /list/add` (Anlegen einer Liste) ist derzeit mit jedem gültigen Token erreichbar —\n> der Endpunkt wird noch nicht durch Scopes geschützt. Eine Scope-Ablehnung auf den geschützten\n> Endpunkten gibt **403** zurück mit\n> `{ \"error\": \"insufficient_scope\", \"required_scope\": \"…\" }`.\n\n## Antwortformat\n\nAlle Endpunkte unterstützen `json` (Standard) und `xml`. Geben Sie das Format in der URL an:\n- `/credit/get.json`\n- `/credit/get.xml`\n\nFeldnamen in Antworten sind **PascalCase** (`TotalCredits`, `FirstName`, …),\nwährend Anfrageparameter **snake_case** sind (`id_client`, `address_book_id`, …).\nListen-Endpunkte verpacken ihre Zeilen in einem `Items`-Array.\n\n## Paginierung\n\n**Gleiche Regel für die drei Mailpro-APIs** (Email v2, CRM v3, SMS): **5.000 Einträge pro Seite,\nstandardmäßig und maximal.**\n- `NumberOfRecords` — Einträge pro Seite. Fehlend, `0` oder über 5.000 = 5.000.\n- `PageNumber` — Seitennummer ab 1 (Standard 1).\n- Beide werden als Query-Parameter **oder** als HTTP-Header akzeptiert.\n- Eine volle Seite bedeutet, dass es weitere geben kann: Fordern Sie die nächste Seite an, bis\n  eine unvollständige Seite zurückkommt.\n\n**Unbekannte Parameter** werden ignoriert, nie abgelehnt. Enthält eine Anfrage einen Parameter, den die API\nnicht kennt, enthält die Antwort `X-Ignored-Parameters` (die Namen) und `X-Documentation` (einen Link zu\ndieser Seite), damit ein Tippfehler nicht unbemerkt bleibt.\n\n## SMS-Guthabenkosten\n\nEine SMS kostet **Länder-Guthaben × Anzahl der Teile**.\n\n**Länder-Guthaben** — jedes Zielland hat einen Preis von 1, 2 oder 3 Guthaben,\nbasierend auf der internationalen Vorwahl der Nummer. Der Versand an eine Nummer,\nderen Vorwahl wir nicht bepreisen, wird mit `400` abgelehnt.\n\n**Anzahl der Teile** — eine Nachricht, die länger als eine SMS ist, wird vom\nBetreiber aufgeteilt und jeder Teil wird berechnet. Das Limit hängt von den\nverwendeten Zeichen ab:\n\n| Alphabet | Einzelne Nachricht | Pro Teil bei Aufteilung |\n|----------|--------------------|--------------------------|\n| GSM-7 (Standard-Latein) | 160 Zeichen | 153 Zeichen |\n| Unicode (Akzente außerhalb GSM-7, Kyrillisch, Emoji, …) | 70 Zeichen | 67 Zeichen |\n\nEin **einziges** Zeichen außerhalb von GSM-7 stellt die **gesamte** Nachricht auf\nUnicode um; so kann ein Emoji eine 160-Zeichen-Nachricht von 1 auf 3 Teile\nbringen. Die Zeichen `^ { } [ ] ~ | \\` und `€` zählen jeweils als **zwei**,\nobwohl sie GSM-7 sind.\n\n*Beispiel:* eine 300-Zeichen-Nachricht in Standard-Latein = 2 Teile; an ein Land\nmit 2 Guthaben gesendet, kostet sie 2 × 2 = **4 Guthaben** pro Empfänger.\n\n## Rufnummernformat\n\nRufnummern werden automatisch normalisiert. Sie können sie in vielen Formaten übermitteln —\nLeerzeichen, Bindestriche, Punkte, Schrägstriche, Klammern, Unterstriche und geschützte Leerzeichen\nwerden vor der Validierung entfernt. Jedes andere Zeichen (Buchstaben, Apostrophe,\n`=`, `;` usw.) macht die Nummer ungültig.\n\n| Gültig                                          | Ungültig                                            |\n|------------------------------------------------|----------------------------------------------------|\n| `+41794849980` — E.164 international           | `0612345678` — nationales Format (führende `0`)    |\n| `0041 79 484 99 80` — 00-Präfix + Leerzeichen  | `41'794'849'80` — Apostrophe (werden nicht entfernt) |\n| `+33 6-12-34-56-78` — + mit Bindestrichen      | `tel=0041794849980` — überflüssige Zeichen          |\n| `41794849980` — reine Ziffern                  | `1234567` — zu kurz (< 8 Ziffern)                  |\n\n**Regeln:**\n- Akzeptierte Präfixe: `+`, `00` oder kein Präfix\n- Länge nach Normalisierung: **8 bis 15 Ziffern** (E.164-Maximum)\n- Die erste Ziffer nach Entfernung des Präfixes muss **1–9** sein (nicht `0`)\n- Entfernte Trennzeichen: Leerzeichen, Tabulator, Bindestrich `-`, Punkt `.`, Schrägstrich `/`, Klammern `( )`, Unterstrich `_`, geschütztes Leerzeichen\n- Alles andere (Buchstaben, Apostrophe, `=`, `;`, `+` innerhalb der Nummer usw.) → wird abgelehnt\n- Speicherform in unserer Datenbank: reine Ziffern, kein Präfix (z. B. `41794849980`)\n\n## Fehlercodes\n\n| HTTP | Code | Bedeutung |\n|------|------|---------|\n| 400  | 103  | Fehlerhafte Eingabe — fehlender oder ungültiger erforderlicher Parameter |\n| 202  | 202  | Unzureichende SMS-Guthaben |\n| 401  |      | Ungültige(r) `id_client` / `api_key` |\n| 500  | 500  | Interner Fehler |\n\n## Webhooks\n\nMailpro™ kann Ihren Server in Echtzeit benachrichtigen, sobald SMS-Ereignisse auf Ihrem\nKonto eintreten (eine SMS wurde zugestellt, eine SMS ist fehlgeschlagen, Ihr Guthaben ist niedrig\nusw.). Im Stripe-Stil — Ihre URL erhält einen mit HMAC-SHA256 signierten POST, sobald das\nEreignis ausgelöst wird.\n\nJedes an Ihren Webhook gesendete Ereignis zählt als 1 Anfrage in Ihrem Kontingent an API-Anfragen.\n\n### Funktionsweise\n\n1. **Abonnieren** Sie einen oder mehrere Ereignistypen über `POST /webhooks`. Die Antwort\n   enthält ein `secret`, das **nur einmal** angezeigt wird (Stil von Stripe / GitHub) — speichern Sie es.\n2. **Mailpro sendet einen POST** mit signiertem JSON-Payload an Ihre URL, sobald ein Ereignis übereinstimmt.\n3. **Verifizieren Sie die Signatur** serverseitig mit Ihrem `secret` (Codebeispiele unten).\n4. **Antworten Sie mit 200–299** innerhalb von 10 Sekunden. Andernfalls führen wir Wiederholungen mit\n   exponentiellem Backoff durch (10 Sek. → 1 Min. → 5 Min. → 30 Min. → 2 Std. → 6 Std. → 24 Std., danach Abbruch).\n\n> **⏱ Aktivierungsverzögerung** — nach dem Erstellen, Aktualisieren oder Löschen eines Webhooks\n> dauert die Verbreitung der Änderung über die Mailpro-API-Server bis zu **10 Minuten**. Während\n> dieses Zeitfensters stimmen Ereignisse unter Umständen noch nicht mit Ihrem neuen Abonnement\n> überein (oder treffen weiterhin auf ein gerade entferntes zu). Diese Zeit wird benötigt, um den\n> In-Memory-Cache der Abonnements auf jeder API-Instanz zu aktualisieren.\n\n### Payload-Hülle\n\nAlle Ereignisse teilen sich eine gemeinsame Hülle:\n\n```json\n{\n  \"id\":         \"evt_8f3a9b2c4d1e5f6789abcdef01234567\",\n  \"type\":       \"sms.queued\",\n  \"created\":    1748194800,\n  \"apiVersion\": \"sms\",\n  \"account\":    { \"id\": 12345, \"name\": \"ACME Corp\" },\n  \"data\":       {\n    \"messageId\":   12345,\n    \"to\":          \"41791234567\",\n    \"queuedAt\":    \"2026-05-27T14:32:12.0123456Z\",\n    \"scheduledAt\": \"2026-05-27T14:32:12.0123456Z\",\n    \"parts\":       1\n  }\n}\n```\n\n| Feld | Format | Beschreibung |\n|-------|--------|-------------|\n| `id` | `evt_` + 32 Hexzeichen | Eindeutige Ereignis-ID — nutzen Sie sie als Idempotenzschlüssel auf Ihrer Seite. |\n| `type` | `<domain>.<verb>` | Kanonischer Ereignistyp. |\n| `created` | Unix-Sekunden UTC | In die HMAC-Signatur einbezogen. |\n| `apiVersion` | `\"sms\"` für Ereignisse, die von `POST /sms/send/add_single` ausgelöst werden; `\"v3\"` für Ereignisse, die von `POST /v3/Sms/SingleSMS` ausgelöst werden; `\"watcher\"` für DLR-basierte Ereignisse, die vom Worker ausgelöst werden. | Welche Mailpro-Komponente das Ereignis veröffentlicht hat. |\n| `account.id` | int | Ihre Mailpro-Kunden-ID (= `id_client`). |\n| `account.name` | string | Ihr Kontoname (praktisch fürs clientseitige Debugging). |\n| `data` | object | Ereignis-Payload — die Struktur hängt von `type` ab (siehe Katalog unten). |\n\n### Ereigniskatalog\n\nEs werden ausschließlich die unten aufgeführten Ereignisse tatsächlich ausgelöst. Die Strukturen\nentsprechen exakt dem JSON, das die Plattform sendet — verwenden Sie diese Feldnamen beim Parsen genau so.\n\n| Ereignis | Auslöser | `data`-Struktur |\n|-------|---------|--------------|\n| `ping` | Test über `POST /webhooks/{id}/test` | `{ message }` |\n| `sms.queued` | `POST /sms/send/add_single` oder `POST /v3/Sms/SingleSMS` in die Mailpro-Sendewarteschlange aufgenommen | `{ messageId: int, to: string, queuedAt: ISO-8601, scheduledAt: ISO-8601, parts: int }` |\n| `sms.delivered` | DLR mit Carrier-Code `004` oder `008` (Erfolgscodes) | `{ messageId: int, phone: string, stateCode: string, dlrDate: datetime }` |\n| `sms.failed` | DLR mit jedem anderen Carrier-Code (Timeout, nicht zugestellt, abgelehnt, gesperrt, …) | `{ messageId: int, phone: string, stateCode: string, dlrDate: datetime }` |\n| `credits.sms.low` | SMS-Guthaben ist unter Ihre Warnschwelle gefallen (Worker `CreditsLowWatcher`) | `{ remaining: int, threshold: int, alertedAt: ISO-8601 }` |\n\n> **Hinweis** — es gibt kein `sms.sent`-Ereignis. Der Carrier-DLR ist die einzige Rückmeldung, die\n> die Plattform zwischen \"queued\" und \"delivered/failed\" erhält, sodass das nächste Ereignis nach\n> `sms.queued` entweder `sms.delivered` (Erfolg) oder `sms.failed` (Fehler) ist. Die meisten\n> Nachrichten erreichen den Carrier innerhalb von Sekunden und einen DLR innerhalb von Minuten;\n> die Bedingungen des Mobilfunknetzes können dies gelegentlich auf Stunden ausdehnen.\n\n> **Feldbenennung** — `sms.queued` verwendet `to` (das Ziel, wie es vom API-Aufrufer übermittelt\n> wurde, nach Normalisierung). `sms.delivered` / `sms.failed` verwenden `phone` (das Ziel, wie es\n> vom Carrier im DLR zurückgegeben wird). In der Praxis sind die Ziffern identisch, die Namen\n> unterscheiden sich jedoch, da die Ereignisse aus unterschiedlichen Code-Pfaden stammen.\n\nAbonnieren Sie alle Ereignisse dieser API, indem Sie `[\"*\"]` im `events`-Array übergeben.\n\n### HMAC-Signatur\n\nJeder POST trägt einen `X-Mailpro-Signature`-Header:\n\n```\nX-Mailpro-Signature: t=1748194800,v1=7f9ac2b6e4d1c8a3...\nX-Mailpro-Event-Id:  evt_8f3a9b2c4d1e5f6789abcdef01234567\nX-Mailpro-Event-Type: sms.delivered\nX-Mailpro-Attempt:   1\n```\n\nSo verifizieren Sie:\n1. Extrahieren Sie `t` und `v1` aus dem Header.\n2. **Ablehnen**, wenn `|now - t| > 300` (5-Minuten-Replay-Schutzfenster).\n3. Berechnen Sie `expected = hex(HMAC_SHA256(secret, t + \".\" + raw_body))`.\n4. **Zeitkonstanter Vergleich** von `v1` mit `expected` (`crypto.timingSafeEqual`,\n   `hash_equals`, `CryptographicOperations.FixedTimeEquals`) — niemals `==`.\n\n#### Node.js\n\n```js\nconst crypto = require('crypto');\n\nfunction verifyMailproSignature(rawBody, header, secret) {\n  const parts = Object.fromEntries(header.split(',').map(p => p.split('=')));\n  if (Math.abs(Date.now() / 1000 - parseInt(parts.t)) > 300) return false;\n  const expected = crypto\n    .createHmac('sha256', secret)\n    .update(parts.t + '.' + rawBody)\n    .digest('hex');\n  return crypto.timingSafeEqual(\n    Buffer.from(parts.v1, 'hex'),\n    Buffer.from(expected, 'hex'));\n}\n```\n\n#### PHP\n\n```php\nfunction verifyMailproSignature(string $rawBody, string $header, string $secret): bool {\n    parse_str(str_replace(',', '&', $header), $p);\n    if (abs(time() - (int)$p['t']) > 300) return false;\n    $expected = hash_hmac('sha256', $p['t'] . '.' . $rawBody, $secret);\n    return hash_equals($expected, $p['v1']);\n}\n```\n\n#### Python\n\n```python\nimport hmac, hashlib, time\n\ndef verify_mailpro_signature(raw_body: bytes, header: str, secret: str) -> bool:\n    parts = dict(p.split('=') for p in header.split(','))\n    t = int(parts['t'])\n    if abs(time.time() - t) > 300:\n        return False\n    expected = hmac.new(\n        secret.encode(),\n        f\"{t}.\".encode() + raw_body,\n        hashlib.sha256\n    ).hexdigest()\n    return hmac.compare_digest(expected, parts['v1'])\n```\n\n#### C#\n\n```csharp\nusing System.Security.Cryptography;\nusing System.Text;\n\nstatic bool VerifyMailproSignature(string rawBody, string header, string secret) {\n    var parts = header.Split(',')\n        .Select(p => p.Split('='))\n        .ToDictionary(a => a[0], a => a[1]);\n    var t = long.Parse(parts[\"t\"]);\n    if (Math.Abs(DateTimeOffset.UtcNow.ToUnixTimeSeconds() - t) > 300) return false;\n    using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(secret));\n    var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes($\"{t}.{rawBody}\"));\n    var expected = Convert.ToHexString(hash).ToLowerInvariant();\n    return CryptographicOperations.FixedTimeEquals(\n        Encoding.UTF8.GetBytes(expected),\n        Encoding.UTF8.GetBytes(parts[\"v1\"]));\n}\n```\n\n### Wiederholungsversuche und automatische Deaktivierung\n\n| Versuch | Wartezeit vor dem nächsten Versuch |\n|---------|----------------------|\n| 1 → 2 | 10 Sekunden |\n| 2 → 3 | 1 Minute |\n| 3 → 4 | 5 Minuten |\n| 4 → 5 | 30 Minuten |\n| 5 → 6 | 2 Stunden |\n| 6 → 7 | 6 Stunden |\n| 7 | abgebrochen (Zustellung als `failed` markiert) |\n\nNach **10 aufeinanderfolgenden Fehlversuchen** auf demselben Webhook wird dieser **automatisch\ndeaktiviert** (`isActive: false`) und Sie erhalten eine Benachrichtigungs-E-Mail. Reaktivieren Sie\nihn mit `PUT /webhooks/{id}`, sobald Ihr Endpunkt korrigiert ist.\n\n### Erfolg = HTTP 2xx\n\nWir werten Ihren Webhook nur dann als erfolgreich, wenn Sie einen Statuscode im Bereich `200–299`\nzurückgeben. Jeder 3xx-/4xx-/5xx-Code oder ein Timeout (> 10 Sek.) zählt als Fehlschlag und löst\nWiederholungsversuche aus. Wenn Ihr Endpunkt dauerhaft nicht erreichbar ist, geben Sie explizit\n`410 Gone` zurück — Wiederholungsversuche finden dennoch statt, der Fehlergrund wird in Ihrem\nZustellprotokoll jedoch deutlicher.\n\n### Limits\n\n| Limit | Wert |\n|-------|-------|\n| Webhooks pro Konto | 20 |\n| Abonnierte Ereignisse pro Webhook | 50 |\n| Maximale Payload-Größe | 256 KB |\n| HTTP-Timeout pro Versuch | 10 Sekunden |\n| Aufbewahrung des Zustellverlaufs | 30 Tage |"
  },
  "servers": [
    {
      "url": "https://api.mailpro.com/sms",
      "description": "Produktion"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "IdClientHeader": [],
      "ApiKeyHeader": []
    },
    {
      "IdClientQuery": [],
      "ApiKeyQuery": []
    }
  ],
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT",
        "description": "Bearer-JWT-Token, das über `POST /sms/token` (form-kodiert, password\ngrant) bezogen wird. Derselbe Token ist auch für die CRM API v3 und\ndie Email v2 API gültig — einmal authentifizieren, jede API aufrufen.\nÜbergeben Sie ihn als: `Authorization: Bearer <token>`\n"
      },
      "OAuth2": {
        "type": "oauth2",
        "description": "Mailpro OAuth 2.0 — der moderne Weg für Drittanbieter-Apps und Integrationsplattformen\n(Zapier, Make, n8n), um im Namen eines Mailpro-Benutzers mit\nscoped, widerrufbaren Access-Tokens zu agieren.\n\n- **authorizationCode + PKCE** (S256, verpflichtend für öffentliche Clients) — der\n  „Mailpro verbinden\"-Einwilligungsflow. Stellt einen Access-Token + einen rotierenden\n  Refresh-Token aus.\n- **clientCredentials** — Maschine-zu-Maschine, ohne Benutzerbeteiligung.\n\nEin Autorisierungsserver für alle APIs, an der versionsneutralen Schnittstelle\n`https://api.mailpro.com/oauth/` (Issuer / `iss`-Claim\n`https://api.mailpro.com/oauth/`). Access-Tokens sind RS256-JWTs\n(verifizieren Sie diese gegen den JWKS unter `https://api.mailpro.com/oauth/.well-known/jwks`);\nTTL **20 Minuten**. Refresh-Tokens sind **30 Tage** gültig (gleitend) und\n**einmalig verwendbar** (bei jedem Refresh rotiert). Autorisierungscodes leben\n**60 Sekunden**.\n\nDerselbe OAuth-Access-Token wird von allen drei Mailpro-APIs\n(CRM v3, Email v2, SMS) akzeptiert — einmal authentifizieren, jede API aufrufen; der Zugriff wird\ndurch die Scopes des Tokens geregelt, nicht durch die API-Basis-URL. Die Legacy-Authentifizierung\n(Bearer JWT / IdClient+ApiKey) funktioniert unverändert weiter und ist NICHT\nscope-gesteuert.\n",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://api.mailpro.com/oauth/authorize",
            "tokenUrl": "https://api.mailpro.com/oauth/token",
            "refreshUrl": "https://api.mailpro.com/oauth/token",
            "scopes": {
              "contacts:read": "View your contacts, lists, tags, segments and custom fields.",
              "contacts:write": "Create, edit and delete your contacts, lists, tags and custom fields.",
              "email:send": "Send transactional and campaign emails on your behalf.",
              "email:read": "View delivery stats, opens, clicks and bounce history.",
              "email:templates:read": "View your email templates (subject, HTML, plain-text body).",
              "email:templates:write": "Create, edit and delete your email templates.",
              "sms:send": "Send transactional and campaign SMS messages on your behalf.",
              "sms:read": "View SMS credit balance and message history.",
              "sms:contacts:read": "View your SMS phone book.",
              "sms:contacts:write": "Create, edit and delete entries in your SMS phone book.",
              "webhooks:manage": "Subscribe to, edit and remove webhook endpoints for your account.",
              "account:read": "View your account credits, limits and subscription status."
            }
          },
          "clientCredentials": {
            "tokenUrl": "https://api.mailpro.com/oauth/token",
            "scopes": {
              "contacts:read": "View your contacts, lists, tags, segments and custom fields.",
              "contacts:write": "Create, edit and delete your contacts, lists, tags and custom fields.",
              "email:send": "Send transactional and campaign emails on your behalf.",
              "email:read": "View delivery stats, opens, clicks and bounce history.",
              "email:templates:read": "View your email templates (subject, HTML, plain-text body).",
              "email:templates:write": "Create, edit and delete your email templates.",
              "sms:send": "Send transactional and campaign SMS messages on your behalf.",
              "sms:read": "View SMS credit balance and message history.",
              "sms:contacts:read": "View your SMS phone book.",
              "sms:contacts:write": "Create, edit and delete entries in your SMS phone book.",
              "webhooks:manage": "Subscribe to, edit and remove webhook endpoints for your account.",
              "account:read": "View your account credits, limits and subscription status."
            }
          }
        }
      },
      "IdClientHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "id_client",
        "description": "Ihre numerische Mailpro-Client-ID — **bevorzugter** Transport (HTTP-Header).\nURLs werden von Webservern, Cloudflare und Proxys protokolliert, daher können\nQuery-String-Anmeldedaten in Zugriffsprotokolle gelangen. Header werden nicht protokolliert.\n"
      },
      "ApiKeyHeader": {
        "type": "apiKey",
        "in": "header",
        "name": "api_key",
        "description": "Ihr API-Schlüssel (GUID) — **bevorzugter** Transport (HTTP-Header).\n"
      },
      "IdClientQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "id_client",
        "description": "Ihre numerische Mailpro-Client-ID — **veraltet**, aus Gründen der Abwärtskompatibilität beibehalten.\nWechseln Sie nach Möglichkeit zum `id_client`-Header.\n"
      },
      "ApiKeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "api_key",
        "description": "Ihr API-Schlüssel (GUID) — **veraltet**, aus Gründen der Abwärtskompatibilität beibehalten.\n"
      }
    },
    "parameters": {
      "format": {
        "name": "format",
        "in": "path",
        "required": true,
        "description": "Antwortformat",
        "schema": {
          "type": "string",
          "enum": [
            "json",
            "xml"
          ],
          "default": "json"
        },
        "example": "json"
      },
      "numberOfRecords": {
        "name": "NumberOfRecords",
        "in": "header",
        "required": false,
        "description": "Einträge pro Seite — standardmäßig und maximal 5.000 (siehe Paginierung). HTTP-Header oder Query-Parameter.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 5000,
          "default": 5000
        },
        "example": 100
      },
      "pageNumber": {
        "name": "PageNumber",
        "in": "header",
        "required": false,
        "description": "1-basierte Seitenzahl für paginierte Antworten. Wird als HTTP-Header gesendet.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        },
        "example": 1
      },
      "sortByName": {
        "name": "SortByName",
        "in": "header",
        "required": false,
        "description": "Auf `true` setzen, um Ergebnisse alphabetisch nach Namen zu sortieren.",
        "schema": {
          "type": "boolean",
          "default": false
        }
      }
    },
    "schemas": {
      "TokenResponse": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string",
            "description": "JWT-Access-Token — verwenden Sie ihn als `Authorization: Bearer <token>` in nachfolgenden Anfragen."
          },
          "token_type": {
            "type": "string",
            "example": "bearer"
          },
          "expires_in": {
            "type": "integer",
            "description": "Token-Lebensdauer in Sekunden",
            "example": 31535999
          },
          "userName": {
            "type": "string",
            "description": "Client-ID des authentifizierten Benutzers",
            "example": "12345"
          },
          "refresh_token": {
            "type": "string",
            "description": "Token, um einen neuen Access-Token ohne erneute Authentifizierung zu erhalten"
          },
          "application": {
            "type": "string",
            "description": "Integrationsname (nur für Drittanbieter-Grants)",
            "nullable": true
          }
        }
      },
      "PhoneList": {
        "type": "object",
        "properties": {
          "AddressBookId": {
            "type": "integer",
            "description": "Unique identifier of the phone list",
            "example": 42
          },
          "Name": {
            "type": "string",
            "description": "Anzeigename der Telefonliste",
            "example": "Newsletter subscribers"
          },
          "TotalNumberPhones": {
            "type": "integer",
            "description": "Number of phone numbers in this list",
            "example": 1547
          }
        }
      },
      "PhoneNumber": {
        "type": "object",
        "properties": {
          "Id": {
            "type": "integer",
            "description": "Eindeutige Kennung des Telefonnummerneintrags",
            "example": 1001
          },
          "Number": {
            "type": "string",
            "description": "Telefonnummer im reinen internationalen Format (Speicherform — siehe „Phone number format\" in der API-Beschreibung für die akzeptierten Eingabeformate)",
            "example": "41791234567"
          },
          "FirstName": {
            "type": "string",
            "description": "Vorname des Kontakts",
            "example": "Alice"
          },
          "LastName": {
            "type": "string",
            "description": "Nachname des Kontakts",
            "example": "Dupont"
          }
        }
      },
      "SingleSend": {
        "type": "object",
        "properties": {
          "Id": {
            "type": "integer",
            "description": "Eindeutige Kennung des erstellten Versands",
            "example": 5001
          },
          "Message": {
            "type": "string",
            "description": "Der SMS-Nachrichtentext",
            "example": "Your verification code is 8472"
          },
          "ScheduledTime": {
            "type": "string",
            "format": "date-time",
            "description": "Wann die SMS versendet wird (oder wurde)",
            "example": "2026-04-15T09:00:00"
          },
          "To": {
            "type": "string",
            "description": "Empfänger-Telefonnummer",
            "example": "0041791234567"
          },
          "Charge": {
            "type": "string",
            "description": "Tatsächlich berechnete Credits für diesen Versand = **Länder-Credits × Anzahl der Teile**.\nZ. B. eine 1-Teil-SMS nach Panama (+507, 3 Credits/SMS) → `\"3\"`; eine 2-Teil-SMS → `\"6\"`.\n",
            "example": "3"
          },
          "Parts": {
            "type": "integer",
            "description": "Anzahl der SMS-Segmente (GSM-03.38-Teile), in die die Nachricht aufgeteilt wurde.",
            "example": 1
          }
        }
      },
      "BulkSend": {
        "type": "object",
        "properties": {
          "Id": {
            "type": "integer",
            "description": "Eindeutige Kennung des erstellten Massenversands",
            "example": 6001
          },
          "Message": {
            "type": "string",
            "description": "Der SMS-Nachrichtentext",
            "example": "Spring sale — 20% off all products this weekend!"
          },
          "ScheduledTime": {
            "type": "string",
            "format": "date-time",
            "description": "Wann die SMS-Kampagne versendet wird (oder wurde)",
            "example": "2026-04-20T10:00:00"
          },
          "To": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Liste der Listen-IDs, die von diesem Versand angesprochen werden",
            "example": [
              "42"
            ]
          },
          "Charge": {
            "type": "string",
            "description": "Insgesamt berechnete Credits für den gesamten Versand = **Σ (Länder-Credits × Teile)**\nüber alle Nummern der Liste.\n",
            "example": "150"
          },
          "Parts": {
            "type": "integer",
            "description": "Anzahl der SMS-Segmente (GSM-03.38-Teile) pro Nachricht.",
            "example": 1
          }
        }
      },
      "CreditBalance": {
        "type": "object",
        "properties": {
          "TotalCredits": {
            "type": "number",
            "description": "Verbleibendes SMS-Guthaben (Tarif-Guthaben + monatliches Guthaben).\n\nDies ist eine Guthabenzahl, keine Nachrichtenanzahl: eine SMS kostet\n`Länder-Guthaben × Anzahl der Teile` — siehe „SMS-Guthabenkosten“ in der\nAPI-Beschreibung.\n",
            "example": 5000
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "Error": {
            "type": "string",
            "description": "Menschenlesbare Fehlermeldung",
            "example": "Malformed Input"
          },
          "Code": {
            "type": "integer",
            "description": "Mailpro-spezifischer Fehlercode",
            "example": 103
          }
        }
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64",
            "example": 42
          },
          "url": {
            "type": "string",
            "format": "uri",
            "example": "https://example.com/hooks/mailpro"
          },
          "description": {
            "type": "string",
            "nullable": true,
            "example": "Slack integration"
          },
          "is_active": {
            "type": "boolean",
            "description": "Wenn `false`, wird kein Ereignis zugestellt. Wird nach 10 aufeinanderfolgenden Fehlversuchen automatisch deaktiviert.",
            "example": true
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-07-01T21:09:52.43"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "example": "2026-07-21T18:56:08.02"
          },
          "last_delivery_at": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Wann der letzte Zustellversuch erfolgte",
            "example": "2026-07-21T18:56:07.653"
          },
          "last_delivery_status": {
            "type": "integer",
            "nullable": true,
            "description": "HTTP-Status, den Ihr Endpunkt bei der letzten Zustellung zurückgegeben hat",
            "example": 200
          },
          "consecutive_failures": {
            "type": "integer",
            "description": "Beim ersten Erfolg auf 0 zurückgesetzt; bei 10 wird der Webhook automatisch deaktiviert",
            "example": 0
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Abonnierte Ereignistypen. Ein leeres Array bedeutet jedes Ereignis dieser API.",
            "example": [
              "sms.delivered",
              "sms.failed"
            ]
          }
        }
      },
      "WebhookList": {
        "type": "object",
        "description": "Umschlag, der von `GET /webhooks` zurückgegeben wird.",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          },
          "total": {
            "type": "integer",
            "description": "Gesamtzahl der Webhooks im Konto",
            "example": 2
          }
        }
      },
      "WebhookCreate": {
        "type": "object",
        "required": [
          "url",
          "events"
        ],
        "properties": {
          "url": {
            "type": "string",
            "format": "uri",
            "description": "HTTPS-Endpoint (HTTP wird in der Produktion abgelehnt)",
            "example": "https://example.com/hooks/mailpro"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 50,
            "description": "Liste der Ereignistypen, die abonniert werden sollen (siehe Katalog oben). Verwenden Sie `[\"*\"]`, um alle Ereignisse dieser API zu abonnieren.",
            "example": [
              "sms.delivered",
              "sms.failed"
            ]
          },
          "description": {
            "type": "string",
            "maxLength": 500,
            "example": "Slack integration"
          }
        }
      },
      "WebhookCreateResponse": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "properties": {
              "secret": {
                "type": "string",
                "description": "HMAC-Geheimnis. **Wird hier einmal angezeigt, danach nie wieder.** Speichern Sie es serverseitig.",
                "example": "whsec_AbcD1234EfgH5678IjkL9012MnoP3456QrsT"
              }
            }
          }
        ]
      },
      "WebhookUpdate": {
        "type": "object",
        "description": "Teilaktualisierung — jedes Feld ist optional.",
        "properties": {
          "url": {
            "type": "string",
            "format": "uri"
          },
          "events": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "maxItems": 50
          },
          "description": {
            "type": "string",
            "maxLength": 500
          },
          "isActive": {
            "type": "boolean",
            "description": "Auf `true` setzen, um einen automatisch deaktivierten Webhook wieder zu aktivieren, sobald Ihr Endpoint repariert ist."
          }
        }
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "type": "integer",
            "format": "int64"
          },
          "eventId": {
            "type": "string",
            "example": "evt_8f3a9b2c4d1e5f6789abcdef01234567"
          },
          "eventType": {
            "type": "string",
            "example": "sms.delivered"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "success",
              "retrying",
              "failed"
            ]
          },
          "statusCode": {
            "type": "integer",
            "nullable": true,
            "example": 200
          },
          "responseTimeMs": {
            "type": "integer",
            "nullable": true,
            "example": 142
          },
          "attemptCount": {
            "type": "integer"
          },
          "lastError": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "lastAttemptAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "nextAttemptAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          }
        }
      }
    }
  },
  "tags": [
    {
      "name": "Authentication",
      "description": "Beziehen Sie einen Bearer-JWT-Token zur Authentifizierung aller anderen API-Aufrufe. Der SMS-\n`/token`-Endpoint ist eine 307-Weiterleitung zum kanonischen `/v3/token`-Issuer —\nIhr HTTP-Client folgt der Weiterleitung transparent (POST-Methode und\nBody werden beibehalten).\n"
    },
    {
      "name": "Account",
      "description": "Überprüfen Sie Ihr SMS-Credit-Guthaben, Ihr monatliches API-Kontingent und den Kontostatus."
    },
    {
      "name": "Send SMS",
      "description": "Versenden Sie SMS-Nachrichten — entweder eine **einzelne transaktionale SMS** an einen Empfänger\noder eine **Massenkampagne** an eine ganze Kontaktliste.\n"
    },
    {
      "name": "Lists",
      "description": "Verwalten Sie SMS-Kontaktlisten. Eine Kontaktliste gruppiert Telefonnummern für den Massenversand.\nSie können bis zu 1.000 Listen pro Konto erstellen (gleiche Grenze für die drei Mailpro-APIs und in der App).\n"
    },
    {
      "name": "Phone Numbers",
      "description": "Verwalten Sie einzelne Telefonnummern innerhalb einer Kontaktliste — Einträge hinzufügen, aktualisieren und entfernen."
    },
    {
      "name": "Credit",
      "description": "Überprüfen Sie das verbleibende SMS-Credit-Guthaben für Ihr Konto (getrennt vom monatlichen API-Anfragekontingent — siehe `/account/limits`)."
    },
    {
      "name": "History",
      "description": "Durchsuchen Sie das vollständige Protokoll vergangener SMS-Kampagnen."
    },
    {
      "name": "Import",
      "description": "Laden Sie eine CSV- oder XLSX-Datei hoch, um Telefonnummern stapelweise in eine Kontaktliste zu importieren.\nDie Datei wird zur asynchronen Verarbeitung in die Warteschlange gestellt — verfolgen Sie den Abschluss über\ndie zurückgegebene `ImportJobId` oder über den optionalen `webhook_url`-Callback.\n"
    },
    {
      "name": "Webhooks",
      "description": "Abonnieren Sie auf Ihrem Server Echtzeitbenachrichtigungen zu SMS-Ereignissen. Mailpro sendet\neinen HMAC-signierten JSON-Payload an Ihre URL, sobald das abonnierte Ereignis\neintritt. Im Abschnitt „Webhooks\" der Einleitung finden Sie den vollständigen\nEreigniskatalog, das Payload-Envelope, Snippets zur Signaturverifizierung und die Retry-Richtlinie.\n"
    }
  ],
  "paths": {
    "/token": {
      "post": {
        "tags": [
          "Authentication"
        ],
        "operationId": "getSmsAccessToken",
        "summary": "Access-Token abrufen (307-Weiterleitung an /v3/token)",
        "security": [],
        "description": "Bezieht einen Bearer-JWT-Token mit Mailpro-Client-Anmeldedaten.\nÜbergeben Sie den zurückgegebenen `access_token` als `Authorization: Bearer <token>` in allen\nnachfolgenden Anfragen. Derselbe Token ist auch für die CRM API v3 und\ndie Email v2 API gültig.\n\n> **⚙ Implementierungsdetail** — `POST /sms/token` ist eine **307 Temporary\n> Redirect** an `POST /v3/token` (konfiguriert in der IIS-`web.config`-\n> Rewrite-Schicht). HTTP 307 bewahrt sowohl die **Methode** (`POST`) als\n> auch den **Anfrage-Body**, sodass jeder standardkonforme HTTP-Client\n> der Weiterleitung transparent folgt — Sie senden weiterhin Anfragen an\n> `/sms/token` und erhalten ein gültiges JWT zurück. Es gibt keine duplizierte\n> Token-Ausstellungslogik; die SMS API stellt selbst nie Tokens aus.\n\n### Unterstützte Grant-Typen\n| Grant-Typ | Anwendungsfall |\n|-----------|----------------|\n| `password` | Standardintegration — Benutzername + API-Schlüssel |\n| `refresh_token` | Erneuerung eines ablaufenden Access-Tokens ohne erneute Authentifizierung |\n| `client_credentials` | Server-zu-Server nur mit Client-ID |\n\n### Token-Lebensdauer\n- Access-Token: **30 Tage**\n- Refresh-Token: **90 Tage**\n\nVerwenden Sie `grant_type=refresh_token`, um den Access-Token ohne\nerneute Authentifizierung zu erneuern. Speichern Sie Tokens serverseitig (Vault, Umgebungsvariablen); betten Sie sie niemals\nin Browser-JS oder mobile App-Binärdateien ein. Vollständige Sicherheitshinweise finden Sie in der CRM API v3\n`/token`-Dokumentation.\n",
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "grant_type"
                ],
                "properties": {
                  "grant_type": {
                    "type": "string",
                    "enum": [
                      "password",
                      "refresh_token",
                      "client_credentials"
                    ],
                    "example": "password"
                  },
                  "username": {
                    "type": "string",
                    "description": "Ihr Mailpro-Benutzername (E-Mail). Erforderlich für `password`-Grant.",
                    "example": "user@yourcompany.com"
                  },
                  "password": {
                    "type": "string",
                    "description": "Ihr Mailpro-API-Schlüssel (GUID-Format). Erforderlich für `password`-Grant.",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "refresh_token": {
                    "type": "string",
                    "description": "Vorheriger Refresh-Token. Erforderlich für `refresh_token`-Grant."
                  },
                  "client_id": {
                    "type": "string",
                    "description": "Ihre Mailpro-Client-ID (Ganzzahl). Erforderlich für `client_credentials`-Grant.",
                    "example": "12345"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Token erfolgreich ausgestellt. Wird von `POST /v3/token` nach dem\ntransparenten 307-Follow zurückgegeben — Ihr HTTP-Client sieht einen normalen 200 mit\nderselben Body-Struktur, die er direkt vom v3-Token-Endpoint erhalten\nwürde.\n",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TokenResponse"
                },
                "example": {
                  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
                  "token_type": "bearer",
                  "expires_in": 31535999,
                  "userName": "12345",
                  "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
                  "application": null
                }
              }
            }
          },
          "307": {
            "description": "Temporary Redirect an `POST /v3/token`, ausgegeben durch die IIS-Rewrite-\nRegel in `web.config`. Standardkonforme HTTP-Clients folgen dieser\nautomatisch und bewahren die ursprüngliche POST-Methode und den Form-Body.\nNur für Clients sichtbar, die das Folgen von Weiterleitungen explizit deaktivieren\n(z. B. `curl --max-redirs 0`).\n",
            "headers": {
              "Location": {
                "schema": {
                  "type": "string"
                },
                "example": "https://api.mailpro.com/v3/token"
              }
            }
          },
          "400": {
            "description": "Ungültige Anmeldedaten oder nicht unterstützter Grant-Typ",
            "content": {
              "application/json": {
                "examples": {
                  "invalid_grant": {
                    "summary": "Falsche Anmeldedaten",
                    "value": {
                      "error": "invalid_grant",
                      "error_description": "The username or password is incorrect."
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/credit/get.{format}": {
      "get": {
        "tags": [
          "Credit"
        ],
        "operationId": "getSmsCredits",
        "security": [
          {
            "OAuth2": [
              "sms:read"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "SMS-Credit-Guthaben abrufen",
        "description": "Gibt das aktuelle SMS-Credit-Guthaben für Ihr Konto zurück.\nSMS-Credits werden zum Versandzeitpunkt verbraucht. Eine Standard-SMS (≤160 GSM-7-Zeichen)\nkostet 1 Credit. Längere Nachrichten oder Nachrichten mit Sonderzeichen können mehr kosten.\n\n> Hinweis: Dies gibt Ihr **SMS-Versand-Credit-Guthaben** zurück, nicht Ihr API-Anfragekontingent.\n> Für das API-Kontingent siehe `GET /account/limits.{format}`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "responses": {
          "200": {
            "description": "Credit-Guthaben erfolgreich zurückgegeben",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreditBalance"
                },
                "example": {
                  "TotalCredits": 5000
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/account/limits.{format}": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getSmsAccountLimits",
        "security": [
          {
            "OAuth2": [
              "account:read"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Monatliches API-Kontingent abrufen",
        "description": "Gibt das monatliche API-Anfragekontingent für den authentifizierten Client zurück.\n\n**Kontingentberechnung:** Das Limit wird aus den E-Mail-\nAbonnement-Credits kalibriert (typischerweise `subscription_credits × 5`). Für\neinen 10.000-E-Mails/Monat-Plan ergibt dies ein monatliches Budget von 50.000\nAnfragen. Zurückgesetzt am **Jahrestag des Abonnements** (nicht am\n1. des Kalendermonats).\n\n**Was Credits verbraucht:**\n- Jede authentifizierte API-Anfrage an `v2`-, `v3`- oder `sms`-Endpoints.\n- Jedes Webhook-Ereignis, das an einen abonnierten Endpoint gesendet wird.\n\n**Was KOSTENLOS ist (verbraucht keine Credits):**\n- `/health`-Endpoints.\n- Anfragen, die mit `401`, `403` oder `429` fehlschlagen.\n- Webhook-Ereignisse für Clients ohne passendes Abonnement.\n\nDas Kontingent wird **über alle 3 Mailpro-APIs hinweg geteilt** (`v2`, `v3`, `sms`)\n— ein Client = ein monatliches Budget für die gesamte Plattform. SMS-\nVersand verbraucht zusätzlich das dedizierte SMS-Credit-Guthaben\n(`GET /credit/get.{format}`).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "responses": {
          "200": {
            "description": "Kontingent-Snapshot",
            "content": {
              "application/json": {
                "example": {
                  "monthlyLimit": 50000,
                  "remaining": 32847,
                  "used": 17153,
                  "isFree": false,
                  "remainedSendsForFree": null
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          },
          "404": {
            "description": "Kein Kontingentdatensatz gefunden (neu erstelltes Konto; die Zeile wird bei der ersten authentifizierten Anfrage angelegt)."
          }
        }
      }
    },
    "/history/list.{format}": {
      "get": {
        "tags": [
          "History"
        ],
        "operationId": "listSmsHistory",
        "security": [
          {
            "OAuth2": [
              "sms:read"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "SMS-Versandhistorie auflisten",
        "description": "Gibt ein paginiertes Protokoll aller von diesem Konto versendeten SMS-Kampagnen zurück.\nDie Ergebnisse sind absteigend nach Datum sortiert (neueste zuerst).\nPaginierung: `NumberOfRecords` und `PageNumber` (Header oder Query, standardmäßig 5.000 pro Seite).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "responses": {
          "200": {
            "description": "Historienliste erfolgreich zurückgegeben",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "Items": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "Id": {
                            "type": "integer",
                            "description": "Kennung des Versands, zu dem diese Zeile gehört",
                            "example": 583294
                          },
                          "DateSent": {
                            "type": "string",
                            "format": "date-time",
                            "description": "Vom Betreiber gemeldeter Zustellzeitstempel",
                            "example": "2026-07-17T18:56:39.813"
                          },
                          "Message": {
                            "type": "string",
                            "example": "Your verification code is 8472"
                          },
                          "Charge": {
                            "type": "number",
                            "description": "Für diese Zeile berechnete Credits = **Länder-Credits × Anzahl der Teile**\n(z. B. 3 für eine 1-Teil-SMS nach Panama). Zuvor immer `1`.\n",
                            "example": 3
                          },
                          "Parts": {
                            "type": "integer",
                            "description": "Anzahl der SMS-Segmente (GSM-03.38-Teile), in die die Nachricht aufgeteilt wurde.",
                            "example": 1
                          }
                        }
                      }
                    }
                  }
                },
                "example": {
                  "Items": [
                    {
                      "Id": 583294,
                      "DateSent": "2026-07-17T18:56:39.813",
                      "Message": "Your verification code is 8472",
                      "Charge": 3,
                      "Parts": 1
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/list/list.{format}": {
      "get": {
        "tags": [
          "Lists"
        ],
        "operationId": "listSmsLists",
        "security": [
          {
            "OAuth2": [
              "sms:contacts:read"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Telefon-Kontaktlisten auflisten",
        "description": "Gibt alle SMS-Kontaktlisten für das Konto zurück.\nVerwenden Sie die zurückgegebenen `Id`-Werte beim Versenden von Massen-SMS-Kampagnen oder beim Hinzufügen von Telefonnummern.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "responses": {
          "200": {
            "description": "Telefonlisten erfolgreich zurückgegeben",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "Items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PhoneList"
                      }
                    }
                  }
                },
                "example": {
                  "Items": [
                    {
                      "AddressBookId": 42,
                      "Name": "Newsletter subscribers",
                      "TotalNumberPhones": 1547
                    },
                    {
                      "AddressBookId": 43,
                      "Name": "Loyalty program",
                      "TotalNumberPhones": 823
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/list/add.{format}": {
      "post": {
        "tags": [
          "Lists"
        ],
        "operationId": "addSmsList",
        "summary": "Eine Kontaktliste erstellen",
        "description": "Erstellt eine neue SMS-Kontaktliste mit dem angegebenen Namen.\nDie Liste beginnt leer — fügen Sie Telefonnummern mit `POST /phone/add` hinzu.\nMaximal 1.000 Listen pro Konto (gleiche Grenze für die drei Mailpro-APIs und in der App). Gibt HTTP 422 zurück, wenn das Limit erreicht ist.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key",
                  "name"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "description": "Ihre Mailpro-Client-ID",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Ihr API-Schlüssel (GUID)",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "name": {
                    "type": "string",
                    "description": "Anzeigename für die neue Kontaktliste",
                    "example": "Spring campaign 2026"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Kontaktliste erfolgreich erstellt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneList"
                },
                "example": {
                  "Id": 44,
                  "Name": "Spring campaign 2026",
                  "NumberPhones": 0
                }
              }
            }
          },
          "400": {
            "description": "Pflichtfeld fehlt (name)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "Error": "Malformed Input",
                  "Code": 103
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/list/edit.{format}": {
      "post": {
        "tags": [
          "Lists"
        ],
        "operationId": "editSmsList",
        "security": [
          {
            "OAuth2": [
              "sms:contacts:write"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Eine Kontaktliste umbenennen",
        "description": "Aktualisiert den Anzeigenamen einer bestehenden SMS-Kontaktliste.\nDie Telefonnummern in der Liste bleiben davon unberührt.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key",
                  "address_book_id",
                  "name"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "description": "Ihre Mailpro-Client-ID",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Ihr API-Schlüssel (GUID)",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "address_book_id": {
                    "type": "integer",
                    "description": "ID der umzubenennenden Kontaktliste (aus `/list/list`)",
                    "example": 42
                  },
                  "name": {
                    "type": "string",
                    "description": "Neuer Anzeigename für die Kontaktliste",
                    "example": "Spring campaign 2026 — updated"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Kontaktliste erfolgreich umbenannt"
          },
          "400": {
            "description": "Pflichtfeld fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/list/del.{format}": {
      "post": {
        "tags": [
          "Lists"
        ],
        "operationId": "deleteSmsList",
        "security": [
          {
            "OAuth2": [
              "sms:contacts:write"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Eine Kontaktliste löschen",
        "description": "Löscht eine SMS-Kontaktliste **und alle darin enthaltenen Telefonnummern** dauerhaft.\nDiese Aktion kann nicht rückgängig gemacht werden.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key",
                  "address_book_id"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "description": "Ihre Mailpro-Client-ID",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Ihr API-Schlüssel (GUID)",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "address_book_id": {
                    "type": "integer",
                    "description": "ID der zu löschenden Kontaktliste",
                    "example": 42
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Kontaktliste erfolgreich gelöscht"
          },
          "400": {
            "description": "address_book_id fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/phone/list.{format}": {
      "get": {
        "tags": [
          "Phone Numbers"
        ],
        "operationId": "listPhones",
        "security": [
          {
            "OAuth2": [
              "sms:contacts:read"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Telefonnummern in einer Kontaktliste auflisten",
        "description": "Gibt eine paginierte Liste der Telefonnummern in einer bestimmten Kontaktliste zurück.\nVerwenden Sie `address_book_id`, um anzugeben, welche Liste abgerufen werden soll.\nPaginierung: `NumberOfRecords` und `PageNumber` (standardmäßig 5.000 pro Seite, Seite 1).\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          },
          {
            "name": "address_book_id",
            "in": "query",
            "required": true,
            "description": "ID der Kontaktliste, aus der Telefonnummern abgerufen werden sollen",
            "schema": {
              "type": "integer"
            },
            "example": 42
          },
          {
            "$ref": "#/components/parameters/numberOfRecords"
          },
          {
            "$ref": "#/components/parameters/pageNumber"
          },
          {
            "$ref": "#/components/parameters/sortByName"
          }
        ],
        "responses": {
          "200": {
            "description": "Telefonnummern erfolgreich zurückgegeben",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "Items": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/PhoneNumber"
                      }
                    }
                  }
                },
                "example": {
                  "Items": [
                    {
                      "Id": 1001,
                      "Number": "41791234567",
                      "FirstName": "Alice",
                      "LastName": "Dupont"
                    },
                    {
                      "Id": 1002,
                      "Number": "33612345678",
                      "FirstName": "Bob",
                      "LastName": "Martin"
                    }
                  ]
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/phone/add.{format}": {
      "post": {
        "tags": [
          "Phone Numbers"
        ],
        "operationId": "addPhone",
        "security": [
          {
            "OAuth2": [
              "sms:contacts:write"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Telefonnummer(n) zu einer Liste hinzufügen",
        "description": "Fügt einer Kontaktliste eine oder mehrere Telefonnummern hinzu.\n\n**Einzelne Nummer:** verwenden Sie das Feld `number`.\n\n**Massenimport:** verwenden Sie das Feld `phone_list` mit durch Semikola getrennten Nummern:\n`+41791234567;+33612345678;0049301234567`\n\nTelefonnummern akzeptieren `+`, `00` oder das reine Format — siehe **Phone number format**\nin der API-Beschreibung für die vollständige Liste der akzeptierten / abgelehnten Eingaben.\nDoppelte Nummern werden stillschweigend übersprungen, sofern nicht `force=1` gesetzt ist.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key",
                  "address_book_id"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "description": "Ihre Mailpro-Client-ID",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Ihr API-Schlüssel (GUID)",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "address_book_id": {
                    "type": "integer",
                    "description": "ID der Kontaktliste, der die Nummer(n) hinzugefügt werden sollen",
                    "example": 42
                  },
                  "number": {
                    "type": "string",
                    "description": "Einzelne Telefonnummer. Akzeptiert `+41…`, `0041…` oder `41…` mit oder ohne\nTrennzeichen (Leerzeichen, Bindestriche, Punkte, Schrägstriche, Klammern). Siehe\n**Phone number format** in der API-Beschreibung.\nVerwenden Sie dies **ODER** `phone_list` — nicht beides.\n",
                    "example": "+41791234567"
                  },
                  "phone_list": {
                    "type": "string",
                    "description": "Durch Semikola getrennte Liste von Telefonnummern für den Massenimport.\nVerwenden Sie dies **ODER** `number` — nicht beides.\nBeispiel: `0041791234567;0033612345678`\n",
                    "example": "0041791234567;0033612345678;0049301234567"
                  },
                  "firstname": {
                    "type": "string",
                    "description": "Vorname des Kontakts (optional, nur bei einzelner Nummer)",
                    "example": "Alice"
                  },
                  "lastname": {
                    "type": "string",
                    "description": "Nachname des Kontakts (optional, nur bei einzelner Nummer)",
                    "example": "Dupont"
                  },
                  "force": {
                    "type": "integer",
                    "description": "Auf `1` setzen, um eine Nummer auch dann hinzuzufügen, wenn sie zuvor abgemeldet wurde oder bereits existiert.\nStandard: `0` (Duplikate werden übersprungen).\n",
                    "enum": [
                      0,
                      1
                    ],
                    "default": 0,
                    "example": 0
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Telefonnummer(n) erfolgreich hinzugefügt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PhoneNumber"
                },
                "example": {
                  "Id": 1003,
                  "Number": "0041791234567",
                  "FirstName": "Alice",
                  "LastName": "Dupont"
                }
              }
            }
          },
          "400": {
            "description": "Pflichtfeld fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/phone/edit.{format}": {
      "post": {
        "tags": [
          "Phone Numbers"
        ],
        "operationId": "editPhone",
        "security": [
          {
            "OAuth2": [
              "sms:contacts:write"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Telefonnummerneintrag aktualisieren",
        "description": "Aktualisiert die Telefonnummer und/oder die Kontaktdaten eines bestehenden Eintrags.\nVerwenden Sie `number_id` (aus `/phone/list`), um den zu aktualisierenden Eintrag zu identifizieren.\nNur die in der Anfrage angegebenen Felder werden aktualisiert.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key",
                  "number_id"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "description": "Ihre Mailpro-Client-ID",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Ihr API-Schlüssel (GUID)",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "number_id": {
                    "type": "integer",
                    "description": "ID des zu aktualisierenden Telefonnummerneintrags (aus `/phone/list`)",
                    "example": 1001
                  },
                  "number": {
                    "type": "string",
                    "description": "Neue Telefonnummer. Akzeptiert `+41…`, `0041…` oder `41…` mit oder ohne Trennzeichen. Siehe **Phone number format** in der API-Beschreibung.",
                    "example": "+41791234568"
                  },
                  "firstname": {
                    "type": "string",
                    "description": "Neuer Vorname des Kontakts",
                    "example": "Alice"
                  },
                  "lastname": {
                    "type": "string",
                    "description": "Neuer Nachname des Kontakts",
                    "example": "Dupont-Martin"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Telefonnummerneintrag erfolgreich aktualisiert"
          },
          "400": {
            "description": "number_id fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/phone/del.{format}": {
      "post": {
        "tags": [
          "Phone Numbers"
        ],
        "operationId": "deletePhone",
        "security": [
          {
            "OAuth2": [
              "sms:contacts:write"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Eine Telefonnummer aus einer Liste entfernen",
        "description": "Entfernt einen bestimmten Telefonnummerneintrag dauerhaft aus seiner Kontaktliste.\nVerwenden Sie `number_id` (aus `/phone/list`), um den Eintrag zu identifizieren.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key",
                  "number_id"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "description": "Ihre Mailpro-Client-ID",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Ihr API-Schlüssel (GUID)",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "number_id": {
                    "type": "integer",
                    "description": "ID des zu löschenden Telefonnummerneintrags (aus `/phone/list`)",
                    "example": 1001
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Telefonnummer erfolgreich entfernt"
          },
          "400": {
            "description": "number_id fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/send/add.{format}": {
      "post": {
        "tags": [
          "Send SMS"
        ],
        "operationId": "sendBulkSms",
        "security": [
          {
            "OAuth2": [
              "sms:send"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Massen-SMS an eine Kontaktliste senden",
        "description": "Sendet eine SMS-Nachricht an **alle Telefonnummern** in einer Kontaktliste.\nUnterstützt Terminierung: Setzen Sie `scheduled_time` auf ein zukünftiges Datum, um später zu senden,\noder lassen Sie es weg, um sofort zu senden.\n\n**Credit-Verbrauch:** Credits werden zum Versandzeitpunkt abgezogen.\nLange Nachrichten (>160 GSM-7-Zeichen) werden in mehrere Teile aufgeteilt,\nvon denen jeder zusätzliche Credits kostet.\n\nDie Antwort gibt `{ \"Error\": \"Insufficient Credit\", \"Code\": 202 }` zurück, wenn\ndas Konto über unzureichende Credits verfügt.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key",
                  "message",
                  "to"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "description": "Ihre Mailpro-Client-ID",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Ihr API-Schlüssel (GUID)",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "message": {
                    "type": "string",
                    "description": "SMS-Nachrichtentext. Bleiben Sie unter 160 Zeichen für eine einteilige SMS.\nZeichen außerhalb des GSM-7-Alphabets (z. B. Chinesisch, Arabisch, Emoji)\nschalten die Kodierung auf Unicode um und reduzieren das Limit auf 70 Zeichen pro Teil.\n",
                    "example": "Flash sale today only — 30% off all orders. Shop now at mailpro.com/shop"
                  },
                  "to": {
                    "type": "integer",
                    "description": "ID der Kontaktliste, an die gesendet werden soll (aus `/list/list`)",
                    "example": 42
                  },
                  "scheduled_time": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Den Versand für ein zukünftiges Datum/eine zukünftige Uhrzeit (ISO 8601) terminieren.\nWeglassen oder leer lassen, um sofort zu senden.\n",
                    "example": "2026-04-20T10:00:00"
                  },
                  "shorten_urls": {
                    "type": "boolean",
                    "default": false,
                    "description": "Auf `true` setzen, um jeden Link der Nachricht durch einen Kurzlink `https://mailp.ro/m/...` zu ersetzen: weniger Zeichen, daher manchmal weniger berechnete SMS-Teile. Ein Link, der nicht gekürzt werden kann, bleibt unverändert."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Massen-SMS-Versand erfolgreich erstellt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkSend"
                },
                "example": {
                  "Id": 6001,
                  "Message": "Flash sale today only — 30% off all orders. Shop now at mailpro.com/shop",
                  "ScheduledTime": "2026-04-20T10:00:00",
                  "To": [
                    "42"
                  ]
                }
              }
            }
          },
          "202": {
            "description": "Unzureichende SMS-Credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "Error": "Insufficient Credit",
                  "Code": 202
                }
              }
            }
          },
          "400": {
            "description": "Pflichtfeld fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "Error": "Malformed Input",
                  "Code": 103
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/send/add_single.{format}": {
      "get": {
        "tags": [
          "Send SMS"
        ],
        "operationId": "sendSingleSmsGet",
        "security": [
          {
            "OAuth2": [
              "sms:send"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Eine einzelne SMS senden (GET)",
        "description": "Sendet eine einzelne SMS an einen Empfänger über eine GET-Anfrage.\nNützlich für einfache Integrationen, bei denen POST nicht verfügbar ist.\nAnmeldedaten und Nachricht werden als Query-Parameter übergeben.\n\n**Hinweis:** Vermeiden Sie GET für sensible Nachrichten — Query-Parameter erscheinen in den Server-Logs.\nBevorzugen Sie stattdessen `POST /send/add_single`.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          },
          {
            "name": "to",
            "in": "query",
            "required": true,
            "description": "Empfänger-Telefonnummer. Akzeptiert `+41…`, `0041…` oder `41…` mit oder ohne Trennzeichen. Siehe **Phone number format** in der API-Beschreibung.",
            "schema": {
              "type": "string"
            },
            "example": "+41791234567"
          },
          {
            "name": "message",
            "in": "query",
            "required": true,
            "description": "SMS-Nachrichtentext (max. 160 Zeichen bei Standardkodierung)",
            "schema": {
              "type": "string"
            },
            "example": "Your appointment is confirmed for tomorrow at 10:00."
          },
          {
            "name": "scheduled_time",
            "in": "query",
            "description": "Den Versand terminieren (ISO 8601). Weglassen, um sofort zu senden.",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "shorten_urls",
            "in": "query",
            "description": "Auf `true` setzen, um jeden Link der Nachricht durch einen Kurzlink `https://mailp.ro/m/...` zu ersetzen: weniger Zeichen, daher manchmal weniger berechnete SMS-Teile. Ein Link, der nicht gekürzt werden kann, bleibt unverändert.",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "SMS erfolgreich gesendet (oder terminiert)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SingleSend"
                },
                "example": {
                  "Id": 5001,
                  "Message": "Your appointment is confirmed for tomorrow at 10:00.",
                  "ScheduledTime": "2026-04-15T09:00:00",
                  "To": "0041791234567",
                  "Charge": "1"
                }
              }
            }
          },
          "202": {
            "description": "Unzureichende SMS-Credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "description": "Erforderlicher Parameter fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      },
      "post": {
        "tags": [
          "Send SMS"
        ],
        "operationId": "sendSingleSms",
        "security": [
          {
            "OAuth2": [
              "sms:send"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Eine einzelne SMS senden",
        "description": "Sendet eine einzelne SMS-Nachricht an eine Empfänger-Telefonnummer.\nUnterstützt Terminierung über `scheduled_time`.\n\n**Credit-Verbrauch:** Credits werden zum Versandzeitpunkt abgezogen.\nDas Feld `Charge` in der Antwort zeigt, wie viele Credits verbraucht wurden.\n\nDie Antwort gibt `{ \"Error\": \"Insufficient Credit\", \"Code\": 202 }` zurück, wenn\ndas Konto über unzureichende Credits verfügt.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key",
                  "message",
                  "to"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "description": "Ihre Mailpro-Client-ID",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Ihr API-Schlüssel (GUID)",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "message": {
                    "type": "string",
                    "description": "SMS-Nachrichtentext",
                    "example": "Your verification code is 8472. Valid for 10 minutes."
                  },
                  "to": {
                    "type": "string",
                    "description": "Empfänger-Telefonnummer. Akzeptiert `+41…`, `0041…` oder `41…` mit oder ohne Trennzeichen. Siehe **Phone number format** in der API-Beschreibung.",
                    "example": "+41791234567"
                  },
                  "scheduled_time": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Den Versand für einen zukünftigen Zeitpunkt terminieren. Weglassen, um sofort zu senden.",
                    "example": "2026-04-15T14:30:00"
                  },
                  "shorten_urls": {
                    "type": "boolean",
                    "default": false,
                    "description": "Auf `true` setzen, um jeden Link der Nachricht durch einen Kurzlink `https://mailp.ro/m/...` zu ersetzen: weniger Zeichen, daher manchmal weniger berechnete SMS-Teile. Ein Link, der nicht gekürzt werden kann, bleibt unverändert."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SMS erfolgreich gesendet (oder terminiert)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SingleSend"
                },
                "example": {
                  "Id": 5001,
                  "Message": "Your verification code is 8472. Valid for 10 minutes.",
                  "ScheduledTime": "2026-04-15T14:30:00",
                  "To": "0041791234567",
                  "Charge": "1"
                }
              }
            }
          },
          "202": {
            "description": "Unzureichende SMS-Credits",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "Error": "Insufficient Credit",
                  "Code": 202
                }
              }
            }
          },
          "400": {
            "description": "Pflichtfeld fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "Error": "Malformed Input",
                  "Code": 103
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/send/list.{format}": {
      "get": {
        "tags": [
          "Send SMS"
        ],
        "operationId": "listSmsSends",
        "security": [
          {
            "OAuth2": [
              "sms:send"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "SMS-Kampagnen auflisten",
        "description": "Gibt die Liste der SMS-Kampagnen (Massenversände) für das Konto zurück.\nPaginierung über die Header `NumberOfRecords` und `PageNumber`.\n\nVerwenden Sie `type_to`, um nach Versandtyp zu filtern:\n- `0` (Standard) — Massenversände an Listen\n- `1` — einzelne Einzelversände\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          },
          {
            "name": "type_to",
            "in": "query",
            "description": "Versandtyp-Filter:\n- `0` (Standard) — Massenversände an eine Kontaktliste\n- `1` — Einzelversände an eine einzelne Nummer\n",
            "schema": {
              "type": "integer",
              "enum": [
                0,
                1
              ],
              "default": 0
            },
            "example": 0
          }
        ],
        "responses": {
          "200": {
            "description": "SMS-Kampagnenliste erfolgreich zurückgegeben",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/SingleSend"
                  }
                },
                "example": [
                  {
                    "Id": 5001,
                    "Message": "Your verification code is 8472",
                    "ScheduledTime": "2026-04-15T09:00:00",
                    "To": "41791234567"
                  }
                ]
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/send/del.{format}": {
      "post": {
        "tags": [
          "Send SMS"
        ],
        "operationId": "deleteSmsSend",
        "security": [
          {
            "OAuth2": [
              "sms:send"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Einen SMS-Versand stornieren oder löschen",
        "description": "Storniert einen **anstehenden terminierten** SMS-Versand oder löscht einen **abgeschlossenen** aus der Historie.\nNur in der Zukunft terminierte Versände können storniert werden. Laufende Versände können nicht gestoppt werden.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key",
                  "id_send"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "description": "Ihre Mailpro-Client-ID",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "description": "Ihr API-Schlüssel (GUID)",
                    "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
                  },
                  "id_send": {
                    "type": "integer",
                    "description": "ID des zu stornierenden oder zu löschenden SMS-Versands (aus `/send/list`)",
                    "example": 6001
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "SMS-Versand erfolgreich storniert oder gelöscht",
            "content": {
              "application/json": {
                "example": {
                  "Result": "OK"
                }
              }
            }
          },
          "400": {
            "description": "id_send fehlt",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          },
          "500": {
            "description": "Löschen fehlgeschlagen (Versand nicht gefunden oder bereits verarbeitet)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                },
                "example": {
                  "Error": "Delete failed",
                  "Code": 500
                }
              }
            }
          }
        }
      }
    },
    "/send/scheduled.{format}": {
      "get": {
        "tags": [
          "Send SMS"
        ],
        "operationId": "listScheduledSms",
        "security": [
          {
            "OAuth2": [
              "sms:send"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Meine terminierten SMS-Versände auflisten",
        "description": "Gibt die SMS-Versände (Einzel oder Kampagne) zurück, die für ein zukünftiges Datum terminiert sind und\nnoch nicht versendet wurden. Nützlich vor dem Aufruf von `/cancel` oder `/reschedule`.\n\nDatensätze sind aufsteigend nach `scheduled_time` sortiert.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          },
          {
            "name": "id_client",
            "in": "query",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 12345
          },
          {
            "name": "api_key",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "example": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
          },
          {
            "$ref": "#/components/parameters/numberOfRecords"
          },
          {
            "$ref": "#/components/parameters/pageNumber"
          }
        ],
        "responses": {
          "200": {
            "description": "Liste der terminierten SMS-Versände",
            "content": {
              "application/json": {
                "example": [
                  {
                    "Id": 9001,
                    "Message": "Black Friday: 30% off until midnight.",
                    "ScheduledTime": "2026-11-27T12:00:00",
                    "To": "+33671234567"
                  }
                ]
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/send/{id_send}/cancel.{format}": {
      "post": {
        "tags": [
          "Send SMS"
        ],
        "operationId": "cancelScheduledSms",
        "security": [
          {
            "OAuth2": [
              "sms:send"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Einen terminierten SMS-Versand stornieren",
        "description": "Storniert eine terminierte SMS, die noch nicht versendet wurde. Wenn der Versand\nbereits verarbeitet wurde (oder nicht existiert / einem anderen Client gehört),\nwird **409 Conflict** zurückgegeben.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          },
          {
            "name": "id_send",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 9001
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key"
                ],
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "example": "a1b2c3d4-..."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Versand storniert",
            "content": {
              "application/json": {
                "example": {
                  "Result": "OK",
                  "Cancelled": 9001
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          },
          "409": {
            "description": "Bereits versendet oder nicht gefunden",
            "content": {
              "application/json": {
                "example": {
                  "error": "conflict",
                  "message": "Send not found, not owned by client, or already dispatched."
                }
              }
            }
          }
        }
      }
    },
    "/send/{id_send}/reschedule.{format}": {
      "patch": {
        "tags": [
          "Send SMS"
        ],
        "operationId": "rescheduleSms",
        "security": [
          {
            "OAuth2": [
              "sms:send"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Einen terminierten SMS-Versand umterminieren",
        "description": "Aktualisiert das geplante Datum einer terminierten SMS, die noch nicht versendet wurde.\nDas neue Datum muss **in der Zukunft** und **innerhalb von 90 Tagen** liegen.\n\n**Name des Datumsfelds:** Die API akzeptiert `scheduled_time` (primär) sowie\ndie Legacy-Aliase `PlanDate`, `date_planned` und `DatePlanned`. Geben Sie\neines davon an — das erste Nicht-Null-Feld wird verwendet.\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          },
          {
            "name": "id_send",
            "in": "path",
            "required": true,
            "schema": {
              "type": "integer"
            },
            "example": 9001
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "type": "object",
                "required": [
                  "id_client",
                  "api_key"
                ],
                "description": "Geben Sie eines von `scheduled_time`, `PlanDate`, `date_planned` oder `DatePlanned` an.",
                "properties": {
                  "id_client": {
                    "type": "integer",
                    "example": 12345
                  },
                  "api_key": {
                    "type": "string",
                    "example": "a1b2c3d4-..."
                  },
                  "scheduled_time": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Primärer Feldname.",
                    "example": "2026-12-31T14:30:00"
                  },
                  "PlanDate": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Legacy-Alias, aus Gründen der Abwärtskompatibilität akzeptiert."
                  },
                  "date_planned": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Legacy-Alias, aus Gründen der Abwärtskompatibilität akzeptiert."
                  },
                  "DatePlanned": {
                    "type": "string",
                    "format": "date-time",
                    "description": "Legacy-Alias, aus Gründen der Abwärtskompatibilität akzeptiert."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Versand umterminiert",
            "content": {
              "application/json": {
                "example": {
                  "Result": "OK",
                  "Id": 9001,
                  "NewScheduledTime": "2026-12-31T14:30:00"
                }
              }
            }
          },
          "400": {
            "description": "scheduled_time fehlt oder ist ungültig"
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          },
          "409": {
            "description": "Bereits versendet, nicht gefunden oder neues Datum außerhalb des Bereichs",
            "content": {
              "application/json": {
                "example": {
                  "error": "conflict",
                  "message": "Reschedule failed — send not found, already dispatched, or new date out of range."
                }
              }
            }
          }
        }
      }
    },
    "/import/upload.{format}": {
      "post": {
        "tags": [
          "Import"
        ],
        "operationId": "uploadImportFile",
        "security": [
          {
            "OAuth2": [
              "sms:contacts:write"
            ]
          },
          {
            "bearerAuth": []
          },
          {
            "IdClientHeader": [],
            "ApiKeyHeader": []
          },
          {
            "IdClientQuery": [],
            "ApiKeyQuery": []
          }
        ],
        "summary": "Datei mit Telefonnummern (CSV / XLSX) für den Massenimport hochladen",
        "description": "Laden Sie eine CSV- oder XLSX-Datei hoch, um Telefonnummern in eine Kontaktliste zu importieren.\nDie Datei wird gespeichert und für die asynchrone Verarbeitung in die Warteschlange gestellt — der Endpoint\ngibt sofort eine `ImportJobId` zurück.\n\n**Anfragetyp:** `multipart/form-data`\n\n**Erforderliche Formularfelder:**\n- `id_client` (Ganzzahl) — Ihre Mailpro-Client-ID\n- `api_key` (Zeichenkette) — Ihr API-Schlüssel\n- `id_list` (Ganzzahl) — ID der Ziel-Kontaktliste\n- `file` (binär) — die hochzuladende CSV- oder XLSX-Datei\n\n**Optional:**\n- `webhook_url` (Zeichenkette) — HTTPS-URL, die nach Abschluss der Verarbeitung aufgerufen wird.\n  Empfängt einen JSON-Payload mit dem Endstatus (success / failed) und\n  der Anzahl importierter / übersprungener / ungültiger Zeilen.\n\n**Dateiformat:**\n- `UTF-8`-kodiert\n- Erste Zeile = Überschriften (eine davon muss `Phone` oder `PhoneNumber` sein — Groß-/Kleinschreibung wird ignoriert)\n- Nummern im internationalen Format (E.164), z. B. `+41791234567`\n- Maximale Dateigröße: 50 MB\n",
        "parameters": [
          {
            "$ref": "#/components/parameters/format"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "multipart/form-data": {
              "schema": {
                "type": "object",
                "required": [
                  "id_list",
                  "file"
                ],
                "properties": {
                  "id_list": {
                    "type": "integer",
                    "format": "int64",
                    "description": "ID der Ziel-Kontaktliste",
                    "example": 11088
                  },
                  "file": {
                    "type": "string",
                    "format": "binary",
                    "description": "CSV- oder XLSX-Datei (`UTF-8`, max. 50 MB)"
                  },
                  "webhook_url": {
                    "type": "string",
                    "format": "uri",
                    "description": "Callback-URL, die nach Abschluss der Verarbeitung aufgerufen wird",
                    "example": "https://example.com/hooks/mailpro-import"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Datei akzeptiert und in die Warteschlange gestellt",
            "content": {
              "application/json": {
                "example": {
                  "Result": "OK",
                  "ImportJobId": 15,
                  "InternalName": "230575-20260420142616-phones.csv"
                }
              }
            }
          },
          "400": {
            "description": "Keine Datei hochgeladen oder id_list fehlt"
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          },
          "500": {
            "description": "Server- oder Speicherfehler"
          }
        }
      }
    },
    "/webhooks": {
      "servers": [
        {
          "url": "https://webhook.mailpro.com/api/sms",
          "description": "Webhook-Verwaltungsdienst (getrennt vom Haupt-API-Host)"
        }
      ],
      "get": {
        "summary": "Webhooks auflisten",
        "description": "Gibt jeden auf dem authentifizierten Konto konfigurierten Webhook zurück.",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Array von Webhooks",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookList"
                },
                "example": {
                  "items": [
                    {
                      "id": 14,
                      "url": "https://example.com/hooks/mailpro",
                      "description": "Slack-Integration",
                      "is_active": true,
                      "created_at": "2026-07-01T21:09:52.43",
                      "updated_at": "2026-07-21T18:56:08.02",
                      "last_delivery_at": "2026-07-21T18:56:07.653",
                      "last_delivery_status": 200,
                      "consecutive_failures": 0,
                      "events": [
                        "sms.delivered",
                        "sms.failed"
                      ]
                    }
                  ],
                  "total": 1
                }
              }
            }
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      },
      "post": {
        "summary": "Einen Webhook erstellen",
        "description": "Erstellt ein neues Webhook-Abonnement. Die Antwort enthält ein `secret`, das\n**nur einmal angezeigt wird** — speichern Sie es sofort serverseitig. Verwenden Sie es, um\ndie HMAC-Signatur jedes eingehenden Payloads zu verifizieren.\n\n**Limits**: max. 20 Webhooks pro Konto, max. 50 Ereignisse pro Webhook.\n",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              },
              "example": {
                "url": "https://example.com/hooks/mailpro",
                "events": [
                  "sms.delivered",
                  "sms.failed"
                ],
                "description": "Slack-Integration"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Webhook erstellt — `secret` wird nur hier zurückgegeben",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreateResponse"
                },
                "example": {
                  "id": 42,
                  "url": "https://example.com/hooks/mailpro",
                  "events": [
                    "sms.delivered",
                    "sms.failed"
                  ],
                  "description": "Slack-Integration",
                  "isActive": true,
                  "consecutiveFailures": 0,
                  "autoDisabledAt": null,
                  "autoDisabledReason": null,
                  "createdAt": "2026-05-25T10:00:00Z",
                  "updatedAt": "2026-05-25T10:00:00Z",
                  "secret": "whsec_AbcD1234EfgH5678IjkL9012MnoP3456QrsT"
                }
              }
            }
          },
          "400": {
            "description": "Ungültige URL, Ereignisliste oder Limit überschritten"
          },
          "401": {
            "description": "Ungültige Anmeldedaten"
          }
        }
      }
    },
    "/webhooks/{id}": {
      "servers": [
        {
          "url": "https://webhook.mailpro.com/api/sms",
          "description": "Webhook-Verwaltungsdienst"
        }
      ],
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "integer",
            "format": "int64"
          }
        }
      ],
      "get": {
        "summary": "Einen Webhook abrufen",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Der Webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "404": {
            "description": "Webhook nicht gefunden"
          }
        }
      },
      "put": {
        "summary": "Einen Webhook aktualisieren",
        "description": "Teilaktualisierung — nur die gesendeten Felder werden geändert.",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Aktualisierter Webhook",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "description": "Ungültiger Payload"
          },
          "404": {
            "description": "Webhook nicht gefunden"
          }
        }
      },
      "delete": {
        "summary": "Einen Webhook löschen",
        "description": "Löscht den Webhook und seine vollständige Zustellhistorie dauerhaft.",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "204": {
            "description": "Gelöscht"
          },
          "404": {
            "description": "Webhook nicht gefunden"
          }
        }
      }
    },
    "/webhooks/{id}/test": {
      "servers": [
        {
          "url": "https://webhook.mailpro.com/api/sms",
          "description": "Webhook-Verwaltungsdienst"
        }
      ],
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "integer",
            "format": "int64"
          }
        }
      ],
      "post": {
        "summary": "Ein Testereignis senden",
        "description": "Stellt ein sofortiges `ping`-Ereignis (oder einen anderen Ereignistyp über das\n`eventType`-Body-Feld) für Ihren Endpoint in die Warteschlange. Nützlich, um Erreichbarkeit\nund Signaturverifizierung zu überprüfen, bevor Sie sich auf echte Ereignisse verlassen.\n",
        "tags": [
          "Webhooks"
        ],
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "eventType": {
                    "type": "string",
                    "default": "ping"
                  }
                }
              },
              "example": {
                "eventType": "ping"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "Ereignis zur Zustellung in die Warteschlange gestellt",
            "content": {
              "application/json": {
                "example": {
                  "deliveryId": 1234,
                  "eventId": "evt_8f3a9b2c4d1e5f6789abcdef01234567",
                  "eventType": "ping"
                }
              }
            }
          },
          "404": {
            "description": "Webhook nicht gefunden"
          }
        }
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "servers": [
        {
          "url": "https://webhook.mailpro.com/api/sms",
          "description": "Webhook-Verwaltungsdienst"
        }
      ],
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "integer",
            "format": "int64"
          }
        }
      ],
      "post": {
        "summary": "HMAC-Geheimnis rotieren",
        "description": "Generiert ein neues HMAC-Geheimnis und macht das alte sofort ungültig.\nDas neue Geheimnis wird **einmal** in der Antwort zurückgegeben — speichern Sie es. Jede\nZustellung ab diesem Zeitpunkt wird mit dem neuen Geheimnis signiert.\n\nVerwenden Sie dies, wenn Sie vermuten, dass Ihr Geheimnis kompromittiert wurde.\n",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Neues Geheimnis (einmal sichtbar)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "secret": {
                      "type": "string"
                    }
                  }
                },
                "example": {
                  "secret": "whsec_XyzA9876BcdE5432FghI1098JklM7654NopQ"
                }
              }
            }
          },
          "404": {
            "description": "Webhook nicht gefunden"
          }
        }
      }
    },
    "/webhooks/{id}/deliveries": {
      "servers": [
        {
          "url": "https://webhook.mailpro.com/api/sms",
          "description": "Webhook-Verwaltungsdienst"
        }
      ],
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "integer",
            "format": "int64"
          }
        },
        {
          "in": "query",
          "name": "limit",
          "schema": {
            "type": "integer",
            "default": 50,
            "maximum": 200
          }
        },
        {
          "in": "query",
          "name": "cursor",
          "schema": {
            "type": "integer",
            "format": "int64"
          },
          "description": "Paginierungs-Cursor (= zuletzt gesehene Delivery-ID). Gibt Zustellungen mit `id < cursor` zurück."
        }
      ],
      "get": {
        "summary": "Zustellversuche auflisten",
        "description": "Gibt die Historie der Zustellversuche für diesen Webhook zurück (30 Tage Aufbewahrung).\nNützlich zum Debugging — welche Ereignisse wurden gesendet, welche Statuscodes wurden empfangen,\nAnzahl der Wiederholungen, Fehlermeldungen.\n",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "200": {
            "description": "Array von Zustellversuchen (neueste zuerst)",
            "content": {
              "application/json": {
                "schema": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/WebhookDelivery"
                  }
                }
              }
            }
          },
          "404": {
            "description": "Webhook nicht gefunden"
          }
        }
      }
    },
    "/webhooks/{id}/deliveries/{deliveryId}/replay": {
      "servers": [
        {
          "url": "https://webhook.mailpro.com/api/sms",
          "description": "Webhook-Verwaltungsdienst"
        }
      ],
      "parameters": [
        {
          "in": "path",
          "name": "id",
          "required": true,
          "schema": {
            "type": "integer",
            "format": "int64"
          }
        },
        {
          "in": "path",
          "name": "deliveryId",
          "required": true,
          "schema": {
            "type": "integer",
            "format": "int64"
          }
        }
      ],
      "post": {
        "summary": "Eine Zustellung erneut abspielen",
        "description": "Stellt einen neuen Zustellversuch mit demselben Payload wie dem Original in die Warteschlange.\nNützlich, um eine fehlgeschlagene Zustellung erneut auszulösen, nachdem Sie Ihren Endpoint repariert haben.\nEine NEUE `Webhook_Delivery`-Zeile wird erstellt (das Original wird zu\nAuditzwecken aufbewahrt). Der Replay durchläuft die Standard-Retry-Richtlinie\n(gleicher Backoff-Zeitplan, gleiche Auto-Deaktivierungsregel nach 10 Fehlschlägen).\n",
        "tags": [
          "Webhooks"
        ],
        "responses": {
          "202": {
            "description": "Replay in die Warteschlange gestellt",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "new_delivery_id": {
                      "type": "integer",
                      "format": "int64",
                      "example": 12999
                    }
                  }
                }
              }
            }
          },
          "404": {
            "description": "Webhook oder Zustellung nicht gefunden"
          }
        }
      }
    }
  }
}