Zum Inhalt springen

Girovo API

Mit Girovo API arbeitet deine App mit Girovo auf demselben Rechner. Sie liest Konten und Umsätze, ändert Kategorien, Notizen, Budgets und Einstellungen und schlägt Überweisungen vor. Jede App fragt vorher den Nutzer.

Für
Girovo Next 7.0, Windows und Linux
Verbindung
nur auf diesem Rechner
Standard
aus
Protokoll
JSON-RPC 2.0, eine Nachricht pro Zeile

Girovo API gehört zu Girovo Next, der Vorabversion von Girovo 7. Methoden und Antworten können sich bis zur Version 7.0 noch ändern.

Das Wichtigste

  • Girovo API ist aus, bis der Nutzer sie einschaltet: Einstellungen › Girovo API › Girovo API zulassen.
  • Es gibt kein Netzwerk und kein HTTP. Unter Windows ist es eine Named Pipe, unter Linux ein Unix Socket. Nur der angemeldete Benutzer kommt daran.
  • Jede App fragt zuerst. Girovo zeigt einen Dialog mit dem Namen der App, ihrem Herausgeber und jedem Recht einzeln.
  • Den Herausgeber liest Girovo aus der Codesignatur deiner App. Was die App über sich selbst sagt, zählt dafür nicht. Unsignierte Apps zeigt Girovo als „Herausgeber unbekannt“.
  • Überweisungen schlägt deine App nur vor. Girovo öffnet sie ausgefüllt, der Nutzer prüft sie und sendet sie selbst, dann folgt die Freigabe der Bank.
  • Der Nutzer kann jedes Recht in Einstellungen › Girovo API wieder entziehen, für jede App einzeln.

Verbinden

Öffne die Pipe oder den Socket und sende JSON-RPC 2.0, eine Nachricht pro Zeile, mit \n am Ende. Antworten und Ereignisse kommen genauso zurück.

Adresse

Windows
\\.\pipe\girovo-api-<SID>Die SID des Benutzers, etwa aus whoami /user.
Linux
$XDG_RUNTIME_DIR/girovo-api.sockOhne XDG_RUNTIME_DIR liegt der Socket in ~/.config/Girovo.

Der erste Aufruf: girovo.hello

Jede Verbindung beginnt mit girovo.hello. Vorher beantwortet Girovo nichts anderes. Du nennst den Namen deiner App, die Rechte, die du brauchst, und einen kurzen Grund für den Nutzer.

{"jsonrpc":"2.0","id":1,"method":"girovo.hello","params":{"app":"Mein Haushaltsbuch","version":"1.0","permissions":["accounts.read","transactions.read"],"reason":"Zeigt deine Kontostände im Haushaltsbuch."}}

Die Antwort kommt, sobald der Nutzer entschieden hat. granted sind alle Rechte, die deine App jetzt hat. Der Nutzer kann einzelne Rechte ausschalten, prüfe also granted.

{"jsonrpc":"2.0","id":1,"result":{"granted":["accounts.read","transactions.read"],"girovo":{"version":"7.0.0","api":1}}}

Was der Dialog zeigt

  • Symbol und Name deiner App, aus der Programmdatei, nicht aus hello.
  • „Herausgeber: <Name>“ mit einem Haken, wenn Windows der Signatur vertraut. Sonst „Herausgeber: unbekannt“ als Warnung, mit dem Pfad der Datei.
  • Jedes Recht als eigener Schalter. Der Nutzer kann einzelne ausschalten.
  • Deinen Grund aus hello, als Worte der App gekennzeichnet.
  • Zulassen und Ablehnen.

Was passieren kann

Zugelassen
Girovo merkt es sich, bis der Nutzer es entzieht. Ein späteres hello fragt nur nach Rechten, die fehlen.
Abgelehnt
refused_by_user. Danach bekommt deine App denied, bis Girovo neu startet.
Keine Antwort
Nach 2 Minuten timeout. Das ist keine Ablehnung, du darfst wieder fragen.
Nicht angemeldet
Der Aufruf wartet. Girovo kommt nach vorn und sagt bei der Anmeldung, welche App fragt. Nach 2 Minuten ohne Anmeldung kommt locked.
Zu viel auf einmal
busy, etwa bei mehr als 4 Verbindungen eines Programms.

Rechte

Frag nur nach dem, was deine App wirklich braucht. Fehlt später ein Recht, bekommst du not_permitted mit data.permission. Ein neues hello mit diesem Recht öffnet den Dialog nur dafür.

accounts.read
Konten, Salden, Verfügbar und den Gesamtsaldo lesen
transactions.read
Umsätze mit Notizen und Kategorien lesen und suchen
insights.read
Zahlen der Analyse, Verträge & Abos, Budgets und Sparziele lesen
ask
Girovo AI fragen (noch keine Methode)
categories.write
Kategorien von Umsätzen, Regeln und eigene Kategorien
notes.write
Notizen an Umsätzen
budgets.write
Monatsbudgets, Sparziele, Erinnerungen und Namen von Verträgen
settings.read
Einstellungen lesen
settings.write
Einstellungen ändern, nur die freigegebenen
bank.refresh
Neue Daten von der Bank holen. Fragt die Bank nach einer Freigabe, gibt der Nutzer sie in Girovo.
transfers.request
Überweisungen und Terminüberweisungen vorschlagen. Der Nutzer prüft und sendet jede in Girovo.

Methoden

Alle Methoden beginnen mit girovo. Beträge sind ganze Cent mit Währung, etwa {"cents":1299,"currency":"EUR"}. Tage sind yyyy-mm-dd, Monate yyyy-mm. Konten, Umsätze und Verträge haben eigene IDs aus den Lese-Methoden.

Lesen

  • girovo.accounts.listRecht accounts.read
    {}

    { accounts[], total[] }: jedes Konto mit id, name, type, iban, bank, balance und available, dazu der Gesamtsaldo je Währung.

  • girovo.transactions.listRecht transactions.read
    { account?, from?, to?, query?, category?, limit?, cursor? }

    { transactions[], next? }: Umsätze, neueste zuerst. limit 1 bis 500, Standard 100. next ist der cursor für die nächste Seite.

  • girovo.insights.monthRecht insights.read
    { month? }

    Einnahmen, Ausgaben, Saldo und beide nach Kategorie für einen Monat, Standard dieser Monat. coverage sagt, ob der Monat ganz geladen ist.

  • girovo.contracts.listRecht insights.read
    {}

    { contracts[] }: Verträge & Abos mit Betrag pro Monat und Jahr, letztem und nächstem Tag.

  • girovo.budgets.listRecht insights.read
    { month? }

    { month, coverage, budgets[] }: jedes Monatsbudget mit Ausgaben, Rest und state (left, exact, over, unknown).

  • girovo.goals.listRecht insights.read
    {}

    { goals[] }: Sparziele mit Ziel, Stand und was noch fehlt.

Ändern

  • girovo.categories.setRecht categories.write
    { booking, category | null }

    { booking, category }. null setzt den Umsatz zurück auf die Regel oder den Vorschlag.

  • girovo.rules.addRecht categories.write
    { booking, category } | { payee, category }

    { applied, payees[], … }. Hat der Nutzer den Empfänger von Hand eingeordnet, bleibt es dabei: applied false, reason filed_by_hand.

  • girovo.categories.createRecht categories.write
    { name, direction?: "out" | "in" }

    { category: { id, name }, direction }

  • girovo.notes.setRecht notes.write
    { booking, text | null }

    { booking, note }. Eine Zeile. null oder leer löscht die Notiz.

  • girovo.budgets.setRecht budgets.write
    { category, cents | null }

    { category, cents }. Nur für Ausgabenkategorien. null löscht das Budget.

  • girovo.goals.setRecht budgets.write
    { account, name, target | null, by? }

    { account, goal }. Nur für Sparkonten, by als yyyy-mm. Wo Sparziele Girovo Plus brauchen, kommt not_permitted.

  • girovo.reminders.setRecht budgets.write
    { contract, by | null, lead?: 7 | 14 | 30 }

    { contract, reminder }. Eine Erinnerung an einen Vertrag, lead Tage vorher.

  • girovo.contracts.renameRecht budgets.write
    { contract, name | null }

    { contract, name, own }. null stellt den erkannten Namen wieder her.

Einstellungen

  • girovo.settings.getRecht settings.read
    {}

    { settings, onlyOn[], onlyOff[] }: die Einstellungen, die deine App lesen und ändern kann. onlyOn und onlyOff nennen die, die nur in eine Richtung gehen.

  • girovo.settings.setRecht settings.write
    { key, value }

    { key, value, changed }. Andere Schlüssel geben invalid.

Freigegebene Schlüssel: language, theme, blackBackground, idleMinutes (5, 10, 15, 30), balancesAtLogin, bookingsAtLogin, keepBalances und keepBookings (nur an), companyLogos (nur aus), ai, aiTone, aiLength, aiUseName, aiNames, singleKeyShortcuts, accountOrder, accountGrouping (type, bank, none), hiddenAccounts.

Bank und Überweisungen

  • girovo.bank.refreshRecht bank.refresh
    { account? }

    { accounts: [{ account, state, newBookings?, balance? }], newBookings }. Holt neue Daten wie Girovo selbst. Eine Freigabe gibt der Nutzer in Girovo. Kann bis 10 Minuten dauern.

  • girovo.transfers.requestRecht transfers.request
    { iban, name, cents, purpose?, executeOn?, account? }

    { request, state: "pending" }. Girovo öffnet die Überweisung ausgefüllt, mit „Angefragt von <App>“. Mit executeOn wird es eine Terminüberweisung, wenn das Konto sie anbietet.

  • girovo.transfers.statusRecht transfers.request
    { request }

    { request, state, text?, changed? }. Nur für eigene Anfragen.

state ist pending, bis der Nutzer handelt. Dann sent (die Bank hat sie angenommen), refused (ohne Senden geschlossen), failed (die Bank hat abgelehnt, ihre Worte in text) oder unclear (noch offen, ob sie durchging). changed: true heißt, der Nutzer hat andere Werte gesendet. Welche, sagt Girovo nicht. Das Ergebnis kommt auch als Ereignis girovo.transfer.updated auf der Verbindung, die gefragt hat.

Ereignisse

  • girovo.events.subscribeRecht je Art
    { kinds[] }

    { subscribed[] }

  • girovo.events.unsubscribeRecht keins
    { kinds[]? }

    { subscribed[] }. Ohne kinds enden alle Abos dieser Verbindung.

Fehler

Ein Fehler ist ein JSON-RPC-Fehler. error.data.reason ist der Code aus dieser Liste, dazu kommen Felder wie permission, param oder text. Die message ist für dein Log gedacht, nicht für deine Oberfläche.

{"jsonrpc":"2.0","id":2,"error":{"code":-32003,"message":"This app does not have the permission for this method.","data":{"reason":"not_permitted","permission":"insights.read"}}}
  • locked-32001Girovo ist gesperrt oder niemand ist angemeldet. Versuch es später wieder.
  • denied-32002Der Nutzer hat deine App abgelehnt. Bis Girovo neu startet, gilt das für alles.
  • not_permitted-32003Deiner App fehlt ein Recht, data.permission nennt es. Ohne data.permission sagt message den Grund, etwa zu viele offene Überweisungen.
  • refused_by_user-32004Der Nutzer hat im Dialog oder bei der Freigabe abgelehnt.
  • bank_error-32005Die Bank hat einen Fehler gemeldet, ihre Worte in data.text.
  • timeout-32006Keine Antwort rechtzeitig, etwa auf den Dialog. Du darfst wieder fragen.
  • rate_limited-32007Zu viele Aufrufe in kurzer Zeit.
  • too_large-32008Die Nachricht ist größer als 1 MB.
  • busy-32009Zu viele Verbindungen oder wartende Aufrufe.
  • invalid-32602Ein Parameter passt nicht, data.param nennt ihn. Auch jeder Aufruf vor hello.
  • method_not_found-32601Diese Methode gibt es nicht.
  • internal-32603Girovo konnte den Aufruf nicht beantworten.

Ereignisse

Mit girovo.events.subscribe hört deine Verbindung auf Ereignisse. Sie kommen als JSON-RPC-Benachrichtigung ohne id, mit der Methode girovo.<Art>. Jede Art braucht ein Recht. Entzieht der Nutzer es, enden ihre Ereignisse sofort. Ein Abo gilt nur für diese Verbindung.

→ {"jsonrpc":"2.0","id":3,"method":"girovo.events.subscribe","params":{"kinds":["bookings.new","balances.changed"]}}
← {"jsonrpc":"2.0","id":3,"result":{"subscribed":["bookings.new","balances.changed"]}}
← {"jsonrpc":"2.0","method":"girovo.balances.changed","params":{"account":"a_…","balance":{…},"available":{…}}}
  • bookings.newRecht transactions.read
    { account, count, bookings[] }

    Neue Umsätze auf einem Konto, das schon geladen war.

  • balances.changedRecht accounts.read
    { account, balance, available }

    Ein Saldo hat sich geändert.

  • transfer.updatedRecht transfers.request
    { request, state, text?, changed? }

    Eine Überweisungsanfrage deiner App ist entschieden.

Beispiel in Node.js

Verbinden, hello, Konten lesen. Kein Paket nötig, Node 18 oder neuer reicht. Girovo muss laufen und Girovo API muss an sein.

// girovo-client.mjs: node girovo-client.mjs
import net from 'node:net'
import { execFileSync } from 'node:child_process'

function address() {
  if (process.platform === 'win32') {
    // "PC\\name","S-1-5-21-…"
    const line = execFileSync('whoami', ['/user', '/fo', 'csv', '/nh'], { encoding: 'utf8' })
    const sid = line.trim().split(',').pop().replaceAll('"', '')
    return '\\\\.\\pipe\\girovo-api-' + sid
  }
  return process.env.XDG_RUNTIME_DIR + '/girovo-api.sock'
}

const socket = net.connect(address())
socket.setEncoding('utf8')
const waiting = new Map()
let nextId = 1
let buffer = ''

function call(method, params = {}) {
  const id = nextId++
  socket.write(JSON.stringify({ jsonrpc: '2.0', id, method, params }) + '\n')
  return new Promise((resolve, reject) => waiting.set(id, { resolve, reject }))
}

socket.on('data', (chunk) => {
  buffer += chunk
  let at
  while ((at = buffer.indexOf('\n')) >= 0) {
    const line = buffer.slice(0, at)
    buffer = buffer.slice(at + 1)
    if (!line.trim()) continue
    const message = JSON.parse(line)
    if (!('id' in message)) continue // an event
    const { resolve, reject } = waiting.get(message.id)
    waiting.delete(message.id)
    if (message.error) reject(message.error)
    else resolve(message.result)
  }
})

socket.on('connect', async () => {
  try {
    const hello = await call('girovo.hello', {
      app: 'Mein Haushaltsbuch',
      version: '1.0',
      permissions: ['accounts.read'],
      reason: 'Zeigt deine Kontostände im Haushaltsbuch.',
    })
    console.log('Erlaubt:', hello.granted)
    const { accounts } = await call('girovo.accounts.list')
    for (const a of accounts) console.log(a.name, a.balance?.cents, a.balance?.currency)
  } catch (error) {
    console.error(error.data?.reason, error.message)
  } finally {
    socket.end()
  }
})

Girovo MCP

Girovo MCP verbindet KI-Assistenten wie Claude Desktop oder Codex mit Girovo. Es ist ein MCP-Server über stdio, der Girovo API nutzt. Der Assistent bekommt dieselben Dialoge und Rechte wie jede andere App.

Wo es liegt

Windows
%LOCALAPPDATA%\Programs\Girovo\girovo-mcp.exe
Linux (deb)
/usr/bin/girovo-mcp
Linux (AppImage)
~/.config/Girovo/girovo-mcp

Claude Desktop

Trag Girovo MCP in claude_desktop_config.json ein. Unter Windows liegt die Datei in %APPDATA%\Claude. Schreib den vollen Pfad aus und verdopple in JSON jeden Backslash.

{
  "mcpServers": {
    "girovo": {
      "command": "C:\\Users\\DEIN-NAME\\AppData\\Local\\Programs\\Girovo\\girovo-mcp.exe"
    }
  }
}

Unter Linux ist command der volle Pfad, etwa "/usr/bin/girovo-mcp". Starte den Assistenten danach neu.

Andere MCP-Clients

Für Codex und andere Clients gilt dasselbe: Der Befehl ist der Pfad zu girovo-mcp, ohne Argumente.

So verhält es sich

  • Beim ersten Werkzeug fragt Girovo MCP nach accounts.read, transactions.read und insights.read, dazu nach dem Recht dieses Werkzeugs. Ein Dialog deckt so den Anfang ab.
  • Braucht ein späteres Werkzeug ein weiteres Recht, öffnet Girovo den Dialog nur dafür.
  • Unter Windows zeigt der Dialog den Assistenten, etwa „Claude (Anthropic PBC) über Girovo MCP“. Unter Linux zeigt er Girovo MCP mit seinem Pfad.
  • Ist Girovo zu oder Girovo API aus, sagt das Werkzeug das. Der nächste Aufruf verbindet neu.

Die 19 Werkzeuge

  • list_accountsaccounts.listaccounts.read
  • search_transactionstransactions.listtransactions.read
  • month_summaryinsights.monthinsights.read
  • list_contractscontracts.listinsights.read
  • list_budgetsbudgets.listinsights.read
  • list_savings_goalsgoals.listinsights.read
  • set_booking_categorycategories.setcategories.write
  • add_category_rulerules.addcategories.write
  • create_categorycategories.createcategories.write
  • set_notenotes.setnotes.write
  • set_budgetbudgets.setbudgets.write
  • set_savings_goalgoals.setbudgets.write
  • set_reminderreminders.setbudgets.write
  • rename_contractcontracts.renamebudgets.write
  • get_settingssettings.getsettings.read
  • set_settingsettings.setsettings.write
  • refresh_from_bankbank.refreshbank.refresh
  • request_transfertransfers.requesttransfers.request
  • transfer_statustransfers.statustransfers.request

Läuft dein Assistent in der Cloud, geht alles, was er aus Girovo liest, an seinen Anbieter.

Grenzen

Was Girovo zulässt

Verbindungen pro Programm
4 (16 insgesamt)
Erster Aufruf nach dem Verbinden
innerhalb von 30 s
Aufrufe pro Sekunde
20, kurz bis 40
Offene Aufrufe pro Verbindung
32
Größe einer Nachricht
1 MB
Antwort auf einen Aufruf
bis 150 s
girovo.bank.refresh
bis 10 Minuten
Warten auf die Anmeldung
2 Minuten, höchstens 64 Aufrufe
Offene Überweisungen
3 pro App, 10 insgesamt

Was keine App kann

  • PIN, Windows Hello und Sicherheitsschlüssel
  • „Weitere Banken mit anmelden“ und das Gerät vergessen
  • Gespeicherte Daten löschen oder zurücksetzen, ein Backup wiederherstellen
  • Girovo API selbst: den Schalter und die Rechte, auch nicht die eigenen
  • Update-Kanal und Updates
  • Nutzungsdaten, „Neue Umsätze melden“ und die Synchronisierung
  • Eine Überweisung senden: das tut immer der Nutzer in Girovo

Girovo ist source available unter der PolyForm Perimeter License 1.0.1. Den Quellcode findest du auf GitHub.