{
  "info": {
    "name": "epago Public API v1",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
    "description": "Erzeugt aus openapi.json, Version 1.2.0.\nNicht von Hand bearbeiten: die Sammlung entsteht aus der Spezifikation (apps/frontend/database/scripts/generate-postman.mjs).\nVor dem ersten Aufruf die Umgebung \"epago Public API (Produktion)\" importieren und dort `apiKey` mit einem eigenen Schluessel belegen (App: Mein Konto, API-Schluessel).\n\nVersionierte Public API von epago (GoBD-konforme Doppik fuer KMU). Ein duenner, validierter Mantel um die bestehende Service-Schicht: externe Schreibzugriffe durchlaufen EXAKT dieselbe Validierung wie die Oberflaeche (Soll=Haben, Steuerautomatik, Periodensperre, Storno statt Loeschen). Authentifizierung per API-Schluessel mit Scopes (read/write) und Rate-Limit.\n\n## Authentifizierung\n\nDer Schluessel geht als `Authorization: Bearer epago_…` oder im Header `x-api-key`. Er gehoert zu genau einem Mandanten, und der Mandant kommt immer aus dem Schluessel, nie aus dem Anfragekoerper. Zwei Scopes: `read` liest, `write` schreibt und liest mit. Jede Operation nennt ihren Scope in `x-scope`.\n\n## Grenzen\n\nJe Schluessel gelten 60 Anfragen pro Minute in einem Schiebefenster (am Schluessel einstellbar), davor zusaetzlich 600 Anfragen pro Minute je IP. Das Limit gilt ueber alle Instanzen hinweg. Jede Antwort traegt den Zustand des Fensters in den Headern X-RateLimit-Limit, X-RateLimit-Remaining und X-RateLimit-Reset (Unix-Zeit in Sekunden); eine Absage mit 429 zusaetzlich Retry-After (Sekunden bis zum Fensterende). Wird das Limit ueberschritten, antwortet die API mit 429 und dem Code `rate_limit_exceeded`.\n\n## Fehlerformat\n\nJeder Fehler hat denselben Koerper und traegt keinen Stacktrace:\n\n```json\n{ \"error\": { \"code\": \"insufficient_scope\", \"message\": \"…\" } }\n```\n\n`code` ist maschinenlesbar, `message` ist deutscher Text fuer Menschen. Einzelne Absagen tragen NEBEN `code` und `message` weitere Felder, wenn die Antwort ohne sie eine Sackgasse waere: eine Zahlung, die einen Rest offen laesst, liefert Vorschlag, Restbetrag und Optionen mit. Solche Felder sind additiv, ein Client, der nur `code` und `message` liest, bleibt gueltig.\n\n## Versionierung\n\nDie Version steht im Pfad (`/api/v1`). Innerhalb von v1 wird nur additiv geaendert: neue Endpunkte, neue optionale Felder, neue Fehlerfelder. Ein bestehendes Feld verschwindet nicht und wechselt nicht die Bedeutung. `info.version` folgt SemVer, eine neue Minor-Nummer ist eine additive Erweiterung. Eine nicht additive Aenderung bekaeme `/api/v2`. Der Aenderungsverlauf steht auf https://epago.de/entwickler.\n\nContact Support:\n Name: epago"
  },
  "auth": {
    "type": "bearer",
    "bearer": [
      {
        "key": "token",
        "value": "{{apiKey}}",
        "type": "string"
      }
    ]
  },
  "variable": [
    {
      "key": "baseUrl",
      "value": "https://app.epago.de",
      "type": "string"
    }
  ],
  "item": [
    {
      "name": "Allgemein",
      "description": {
        "content": "Verbindungstest & Key-Info",
        "type": "text/plain"
      },
      "item": [
        {
          "name": "Verbindungstest & Mandanten-Info",
          "request": {
            "name": "Verbindungstest & Mandanten-Info",
            "description": {
              "content": "Smoke-Test-Endpoint. Liefert Key-Scopes und Mandanten-Stammdaten. Scope: read. Liefert auch die Umgebung des Schlüssels (live oder sandbox).",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "api",
                "v1",
                "me"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": [],
              "raw": "{{baseUrl}}/api/v1/me"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    },
    {
      "name": "Konten",
      "description": {
        "content": "Kontenplan, Salden, Kontenblatt",
        "type": "text/plain"
      },
      "item": [
        {
          "name": "Kontenplan abrufen",
          "request": {
            "name": "Kontenplan abrufen",
            "description": {
              "content": "Liefert den Kontenplan des Mandanten. Mit withBalances=1 zusaetzlich aktuelle Salden. Scope: read.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "api",
                "v1",
                "accounts"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [
                {
                  "disabled": true,
                  "key": "withBalances",
                  "value": "<string>",
                  "description": "Salden mitliefern"
                },
                {
                  "disabled": true,
                  "key": "from",
                  "value": "<date>",
                  "description": "Saldenzeitraum von (nur mit withBalances)"
                },
                {
                  "disabled": true,
                  "key": "to",
                  "value": "<date>",
                  "description": "Saldenzeitraum bis (nur mit withBalances)"
                }
              ],
              "variable": [],
              "raw": "{{baseUrl}}/api/v1/accounts?withBalances=<string>&from=<date>&to=<date>"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "name": "Kontenblatt abrufen",
          "request": {
            "name": "Kontenblatt abrufen",
            "description": {
              "content": "Buchungszeilen eines Kontos mit laufendem Saldo. Scope: read.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "api",
                "v1",
                "accounts",
                ":number",
                "ledger"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [
                {
                  "disabled": true,
                  "key": "from",
                  "value": "<date>"
                },
                {
                  "disabled": true,
                  "key": "to",
                  "value": "<date>"
                }
              ],
              "variable": [
                {
                  "disabled": false,
                  "type": "any",
                  "value": "<string>",
                  "key": "number",
                  "description": "(Required) Kontonummer, z.B. 1200"
                }
              ],
              "raw": "{{baseUrl}}/api/v1/accounts/:number/ledger?from=<date>&to=<date>"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    },
    {
      "name": "Buchungen",
      "description": {
        "content": "Buchungen lesen, anlegen, stornieren",
        "type": "text/plain"
      },
      "item": [
        {
          "name": "Buchungen lesen",
          "request": {
            "name": "Buchungen lesen",
            "description": {
              "content": "Buchungen des Mandanten, optional gefiltert nach Datum und Status. Scope: read.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "api",
                "v1",
                "journal-entries"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [
                {
                  "disabled": true,
                  "key": "from",
                  "value": "<date>",
                  "description": "Buchungsdatum von (inkl.)"
                },
                {
                  "disabled": true,
                  "key": "to",
                  "value": "<date>",
                  "description": "Buchungsdatum bis (inkl.)"
                },
                {
                  "disabled": true,
                  "key": "status",
                  "value": "<string>"
                }
              ],
              "variable": [],
              "raw": "{{baseUrl}}/api/v1/journal-entries?from=<date>&to=<date>&status=<string>"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "name": "Buchung anlegen",
          "request": {
            "name": "Buchung anlegen",
            "description": {
              "content": "Legt eine Buchung an. Laeuft durch DIESELBE Validierung wie die Oberflaeche: Soll=Haben (Toleranz 0,01 EUR), Steuerautomatik-Konsistenz (Steuerschluessel 1/2/3/8/9), Kontoexistenz, Periodensperre (festgeschriebene Perioden -> 409). Vermerkt source='api' im Audit-Trail. Scope: write.\n\nDer Body kommt in GENAU EINER von zwei Formen: mit fertigen Buchungszeilen (lines[]) oder vereinfacht (betrag, bruttoKonto, sachKonto). Beide zusammen ergeben 400.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "api",
                "v1",
                "journal-entries"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": [],
              "raw": "{{baseUrl}}/api/v1/journal-entries"
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"date\": \"<date>\",\n  \"description\": \"<string>\",\n  \"lines\": [\n    {\n      \"accountNumber\": \"<string>\",\n      \"accountName\": \"<string>\",\n      \"debit\": 0,\n      \"credit\": 0,\n      \"taxCode\": \"<string,null>\",\n      \"costCenterId\": \"<string,null>\",\n      \"description\": \"<string,null>\"\n    },\n    {\n      \"accountNumber\": \"<string>\",\n      \"accountName\": \"<string>\",\n      \"debit\": 0,\n      \"credit\": 0,\n      \"taxCode\": \"<string,null>\",\n      \"costCenterId\": \"<string,null>\",\n      \"description\": \"<string,null>\"\n    }\n  ],\n  \"reference\": \"<string,null>\",\n  \"status\": \"draft\",\n  \"costCenterId\": \"<string,null>\",\n  \"tags\": [\n    \"<string>\",\n    \"<string>\"\n  ]\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "name": "Buchung stornieren",
          "request": {
            "name": "Buchung stornieren",
            "description": {
              "content": "GoBD-konformes Storno: erzeugt eine Gegenbuchung mit aktuellem Datum und markiert das Original als 'reversed'. Loeschen ist nicht moeglich. Scope: write.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "api",
                "v1",
                "journal-entries",
                ":id",
                "reverse"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": [
                {
                  "disabled": false,
                  "type": "any",
                  "value": "<string>",
                  "key": "id",
                  "description": "(Required) "
                }
              ],
              "raw": "{{baseUrl}}/api/v1/journal-entries/:id/reverse"
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"reason\": \"<string>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    },
    {
      "name": "Rechnungen",
      "description": {
        "content": "Ein-/Ausgangsrechnungen lesen",
        "type": "text/plain"
      },
      "item": [
        {
          "name": "Rechnungen lesen",
          "request": {
            "name": "Rechnungen lesen",
            "description": {},
            "url": {
              "path": [
                "api",
                "v1",
                "invoices"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [
                {
                  "disabled": true,
                  "key": "documentType",
                  "value": "<string>"
                },
                {
                  "disabled": true,
                  "key": "status",
                  "value": "<string>"
                },
                {
                  "disabled": true,
                  "key": "paymentStatus",
                  "value": "<string>"
                },
                {
                  "disabled": true,
                  "key": "from",
                  "value": "<date>"
                },
                {
                  "disabled": true,
                  "key": "to",
                  "value": "<date>"
                }
              ],
              "variable": [],
              "raw": "{{baseUrl}}/api/v1/invoices?documentType=<string>&status=<string>&paymentStatus=<string>&from=<date>&to=<date>"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "name": "Einzelne Rechnung lesen",
          "request": {
            "name": "Einzelne Rechnung lesen",
            "description": {},
            "url": {
              "path": [
                "api",
                "v1",
                "invoices",
                ":id"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": [
                {
                  "disabled": false,
                  "type": "any",
                  "value": "<string>",
                  "key": "id",
                  "description": "(Required) "
                }
              ],
              "raw": "{{baseUrl}}/api/v1/invoices/:id"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "name": "Zahlungen eines Belegs lesen",
          "request": {
            "name": "Zahlungen eines Belegs lesen",
            "description": {
              "content": "Alle erfassten Zahlungen des Belegs, aelteste zuerst. Fremde oder unbekannte ID: 404. Scope: read.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "api",
                "v1",
                "invoices",
                ":id",
                "payments"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": [
                {
                  "disabled": false,
                  "type": "any",
                  "value": "<string>",
                  "key": "id",
                  "description": "(Required) "
                }
              ],
              "raw": "{{baseUrl}}/api/v1/invoices/:id/payments"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "name": "Zahlung an einem Beleg erfassen",
          "request": {
            "name": "Zahlung an einem Beleg erfassen",
            "description": {
              "content": "Erfasst eine Zahlung und laeuft dabei durch dieselbe Schreibschicht wie die Oberflaeche: Belegstatus-Gate (auf einen Entwurf oder einen stornierten Beleg geht keine Zahlung ein, 409), Ueberzahlungsschutz, Zahlungsbuchung, Umsatzsteuer-Umbuchung bei Ist-Versteuerung (Paragraf 20 UStG) und die Fortschreibung des Zahlungsstands am Beleg.\n\nBleibt nach der Zahlung ein Rest offen, ist zahlungsart PFLICHT. Fehlt sie, antwortet die API mit 400 zahlungsart_erforderlich und liefert restBetrag, vorschlag und die ausfuehrbaren optionen mit; der zweite Aufruf setzt dann die gewaehlte zahlungsart. Grund: eine Teilzahlung, ein Skontoabzug und ein Forderungsausfall sehen in den Daten gleich aus, haben aber verschiedene Folgen fuer die Umsatzsteuer (Paragraf 17 UStG kennt keine Bagatellgrenze).\n\nGoBD: Skonto und Forderungsausfall erzeugen eine EIGENE Buchung mit dem Zahlungsdatum (Paragraf 17 Abs. 1 Satz 7 UStG: Zeitraum der Aenderung). Die Rechnung und ihre Buchung bleiben unveraendert. Scope: write.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "api",
                "v1",
                "invoices",
                ":id",
                "payments"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": [
                {
                  "disabled": false,
                  "type": "any",
                  "value": "<string>",
                  "key": "id",
                  "description": "(Required) "
                }
              ],
              "raw": "{{baseUrl}}/api/v1/invoices/:id/payments"
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"amount\": \"<number>\",\n  \"paymentDate\": \"<date>\",\n  \"paymentMethod\": \"<string>\",\n  \"reference\": \"<string>\",\n  \"zahlungsart\": \"<string>\",\n  \"zahlungsartBegruendung\": \"<string>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    },
    {
      "name": "Belege",
      "description": {
        "content": "Belege hochladen",
        "type": "text/plain"
      },
      "item": [
        {
          "name": "Beleg hochladen",
          "request": {
            "name": "Beleg hochladen",
            "description": {
              "content": "Laedt einen Beleg als Base64 hoch (max. 10 MB; PDF, Bilder, Excel, CSV). SHA256-Hash fuer GoBD-Integritaet wird serverseitig gebildet. Scope: write.",
              "type": "text/plain"
            },
            "url": {
              "path": [
                "api",
                "v1",
                "documents"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [],
              "variable": [],
              "raw": "{{baseUrl}}/api/v1/documents"
            },
            "header": [
              {
                "key": "Content-Type",
                "value": "application/json"
              },
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "POST",
            "body": {
              "mode": "raw",
              "raw": "{\n  \"fileName\": \"<string>\",\n  \"originalName\": \"<string>\",\n  \"mimeType\": \"<string>\",\n  \"data\": \"<string>\",\n  \"size\": \"<integer>\",\n  \"category\": \"<string>\",\n  \"description\": \"<string>\",\n  \"documentDate\": \"<date>\",\n  \"reference\": \"<string>\"\n}",
              "options": {
                "raw": {
                  "language": "json"
                }
              }
            }
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    },
    {
      "name": "Berichte",
      "description": {
        "content": "BWA, UStVA, Saldenliste",
        "type": "text/plain"
      },
      "item": [
        {
          "name": "BWA (Betriebswirtschaftliche Auswertung)",
          "request": {
            "name": "BWA (Betriebswirtschaftliche Auswertung)",
            "description": {},
            "url": {
              "path": [
                "api",
                "v1",
                "reports",
                "bwa"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [
                {
                  "disabled": true,
                  "key": "from",
                  "value": "<date>"
                },
                {
                  "disabled": true,
                  "key": "to",
                  "value": "<date>"
                }
              ],
              "variable": [],
              "raw": "{{baseUrl}}/api/v1/reports/bwa?from=<date>&to=<date>"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "name": "UStVA (Umsatzsteuer-Voranmeldung)",
          "request": {
            "name": "UStVA (Umsatzsteuer-Voranmeldung)",
            "description": {},
            "url": {
              "path": [
                "api",
                "v1",
                "reports",
                "vat"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [
                {
                  "disabled": true,
                  "key": "from",
                  "value": "<date>"
                },
                {
                  "disabled": true,
                  "key": "to",
                  "value": "<date>"
                }
              ],
              "variable": [],
              "raw": "{{baseUrl}}/api/v1/reports/vat?from=<date>&to=<date>"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        },
        {
          "name": "Saldenliste",
          "request": {
            "name": "Saldenliste",
            "description": {},
            "url": {
              "path": [
                "api",
                "v1",
                "reports",
                "account-balances"
              ],
              "host": [
                "{{baseUrl}}"
              ],
              "query": [
                {
                  "disabled": true,
                  "key": "from",
                  "value": "<date>"
                },
                {
                  "disabled": true,
                  "key": "to",
                  "value": "<date>"
                }
              ],
              "variable": [],
              "raw": "{{baseUrl}}/api/v1/reports/account-balances?from=<date>&to=<date>"
            },
            "header": [
              {
                "key": "Accept",
                "value": "application/json"
              }
            ],
            "method": "GET"
          },
          "event": [],
          "protocolProfileBehavior": {
            "disableBodyPruning": true
          }
        }
      ],
      "event": []
    }
  ]
}
