Kunden

Endpoints für die Verwaltung von Kunden — Anlegen, Lesen, Aktualisieren und Löschen — plus alle direkt am Kunden hängenden Unterressourcen (Adressen, Bankverbindungen, Verträge, Schäden, Dokumente …).

Zuletzt geprüft: 12. Mai 2026

Übersicht

Ein Customer ist der zentrale Datensatz für eine Person oder Firma in i-Planner — intern als Kontakt im Bereich „Privatkunden" geführt. Alle weiteren CRM-Objekte (Verträge, Schäden, Aktivitäten, Dokumente, Finanzen …) hängen direkt oder indirekt am Customer.

Das Customer-Schema ist organisationsspezifisch konfigurierbar: Welche Felder dein Tenant für einen Kunden pflegt, definiert die Form-Konfiguration in den Account-Einstellungen. Die API liefert auf Wunsch (with_schema=true) das aktuelle Feld-Schema deiner Organisation mit zurück, damit Integratoren keine Felder hart verdrahten müssen, die ggf. nicht existieren.

Scopes

Jede Ressource-Familie hat ihren eigenen Scope nach dem Schema v3:<resource>:<action>. Der URL-Pfad spielt für die Berechtigung keine Rolle — entscheidend ist, welche Daten angefasst werden.

Customer-Stammdaten (Name, Anrede, Geburtsdatum, Kommentar etc.):

  • v3:customers:read — GET /v3/customers, GET /v3/customers/<id>
  • v3:customers:write — POST /v3/customers, PATCH /v3/customers/<id>, DELETE /v3/customers/<id>

Unterressourcen teilen sich entweder den Customer-Scope (direkt am Customer-Datensatz) oder haben eine eigene Scope-Familie (eigenständige Daten-Domäne):

UnterressourceScopeDomäne
Addressesv3:customers:read · v3:customers:writedirekt am Customer
Contactsv3:customers:read · v3:customers:writedirekt am Customer
Bankingv3:customers:read · v3:customers:writedirekt am Customer
Nummernv3:customers:read · v3:customers:writedirekt am Customer
Identityv3:customers:read · v3:customers:writedirekt am Customer
Jobsv3:customers:read · v3:customers:writedirekt am Customer
Tagsv3:customers:read · v3:customers:writedirekt am Customer
Commentsv3:customers:read · v3:customers:writedirekt am Customer
Followersv3:customers:read · v3:customers:writedirekt am Customer
Contractsv3:contracts:read · v3:contracts:writeeigene Scope-Familie + globally-unique id
Damagesv3:damages:read · v3:damages:writeeigene Scope-Familie + globally-unique id
Financesv3:finances:read · v3:finances:writeeigene Scope-Familie + globally-unique id
Goalsv3:goals:read · v3:goals:writeeigene Scope-Familie + globally-unique id
Documentsv3:documents:read · v3:documents:writeeigene Scope-Familie + globally-unique id

Praxisbeispiel — Geburtstags-Newsletter-Tool braucht:

v3:customers:read     ✓   (Name, Anrede, Geburtsdatum, E-Mail-Adresse)

Mehr nicht. Verträge, Schäden, Finanzen, Dokumente bleiben für dieses Tool unsichtbar — kein versehentlicher Daten-Leak möglich.

Wie die Authentifizierung über Bearer-Token grundsätzlich funktioniert und welche Fehler-Bodies bei fehlendem oder ungültigem Token kommen, siehe Authentication.

Pagination & Limits

Listen-Endpoints sind paginiert. Die Parameter:

  • page — 1-basierter Seitenindex. Default 1.
  • limit — Items pro Seite. Default 50, Hard-Cap 5000.

Verhalten bei ungültigen Werten: Die API klemmt ungültige Pagination-Parameter still auf einen sicheren Wert ab, statt mit 400 zu antworten — das hält Listing-Calls auch bei Tipp- oder Encoding-Fehlern stabil:

  • limit nicht-numerisch (abc), leer, 0, negativ → Default (50)
  • limit > 5000 → auf 5000 geklemmt
  • limit mit Dezimalstellen (1.5) → auf den Integer-Anteil geparst (1)
  • page nicht-numerisch, leer, 0, negativ → 1
  • page jenseits der letzten Seite → 200 mit items: []

Strikt validiert werden hingegen Pfad-Parameter (kid, id) und die meisten Body-Felder — siehe Errors.

Die Antwort enthält immer page, page_size, total und items. Es gibt keine Cursor-Pagination; Clients berechnen Folgeseiten anhand total / page_size.

Beispiel — Seite 2 mit 50 Items pro Seite:

bash
curl 'https://www.api.i-planner.app/v3/customers?page=2&limit=50' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Folgeseiten berechnen:

  • Gesamtseitenzahl: Math.ceil(total / page_size) — im Beispiel: Math.ceil(4217 / 50) = 85
  • Letzte Seite hat oft weniger Items: total - (page - 1) * page_size
  • Wenn items.length < page_size, ist die aktuelle Seite die letzte.

Schema

Die Response-Struktur eines einzelnen Customers (mit allen Unterressourcen-Includes aktiviert). Welche tenant-konfigurierbaren Felder dein Customer-Datensatz im Detail hat, kannst du jederzeit über with_schema=true aus der API selbst lernen — siehe GET /v3/customers unten.

json
{
  // ─── System & Identifikation ─────────────────────────────────
  "id": 838,                          // Row-Primary-Key (Postgres-PK)
  "kid": 1485348238,                  // Customer-ID — Source-of-Truth im URL-Pfad (auch bei allen Sub-Resources)
  "nummer": "1430397724",             // organisations-spezifische Customer-Nummer
  "betreuer": 1485503904,             // User-ID des zuständigen Betreuers (siehe /v3/users)
  "insert_datum": "2017-01-25",       // Erstanlage (Date-only, KEIN Time-Anteil)
  "edit_datum": "2020-07-15",         // letzte Änderung (Date-only)

  // ─── Klassifikation & Anrede ─────────────────────────────────
  "kontakt_art": 0,                   // 0=Kunde, 1=Interessent, 2=Inaktiv, 3=Verstorben, 4=Lead, 5=Empfehlung, 6=Kontakt
  "anrede": "Herr",                   // "Frau" | "Herr" | "Firma" | "Familie"
  "briefanrede": "Sehr geehrter Herr Dr. Leier,",   // serverseitig generierte Brief-Anrede

  // ─── Person / Firma — Stammdaten ─────────────────────────────
  "name": "Leier",                    // Nachname oder Firmenname
  "vorname": "Helmut",                // bei anrede="Firma" typisch leer
  "titel": "Dr.",                     // akademischer Titel
  "nation": "deutsch",                // Nationalität — siehe select_fields.customers.nation

  // ─── Geburts- und Familien-Daten (nur bei natürlichen Personen) ─
  "geb": "1970-01-15",                // Geburtsdatum
  "geb_ort": "München",
  "geb_name": "",                     // Geburtsname (geboren als …)
  "familienstand": "verheiratet",     // siehe select_fields.customers.familienstand
  "datum_heirat": null,
  "datum_scheidung": null,
  "datum_erstkontakt": "2017-01-25",  // Datum des Erstkontakts mit dem Customer

  // ─── Inline-Sub-Resources (opt-in via with_*=true, Default false seit Phase C) ─
  // ⚠ Naming-Asymmetrie: das Inline-Array `banks` korrespondiert mit der
  //   URL `/v3/customers/<kid>/banking`, das Inline-Array `identifications`
  //   mit `/v3/customers/<kid>/identity`. Beide laufen unter `v3:customers:*`
  //   — siehe Note unten.

  "addresses": [
    {
      "id": 840,
      "kid": 1485348238,
      "art": 0,                       // numerisch (siehe select_fields.addresses)
      "bezeichnung": "Geschäftlich",  // Freitext-Label, z. B. "Erstanschrift", "Zweitanschrift"
      "adresszusatz": "Herr Michael Absmeier",
      "strasse": "Bahnhofstraße 20",
      "plz": "94099",
      "ort": "Ruhstorf-Sulzbach (Inn)",
      "bundesland": "Bayern",
      "insert_datum": null,
      "edit_datum": null
    }
  ],

  "contacts": [
    {
      "id": 3338,
      "kid": 1485348238,
      "art": "E-Mail",                // "E-Mail" | "Telefon" — capitalized, nicht snake_case
      "wert": "h.leier@example.com",
      "werbung": 1,                   // 0=Marketing-Opt-out, 1=Opt-in — DSGVO-relevant
      "insert_datum": null,
      "edit_datum": null
    }
  ],

  "banks": [
    {
      "id": 4,
      "kid": 1485348238,
      "typ": "0",                     // "0"=Konto, "1"=Depot (siehe select_fields.banks.bank_typ)
      "inhaber": "Helmut Leier",      // NICHT `kontoinhaber`
      "nummer": "",                   // Legacy-Kontonummer (vor IBAN-Pflicht), typisch leer
      "iban": "DE50750700240505025700",
      "bic": "DEUTDEDB750",
      "institut": "Deutsche Bank Privat und Geschäftskunden, Regensburg",
      "insert_datum": null,
      "edit_datum": null
    }
  ],

  "numbers": [
    {
      "id": 6,
      "kid": 1485348238,
      "art": 1,                       // numerische Nummern-Art
      "wert": "143/188/4024",
      "insert_datum": null,
      "edit_datum": null
    }
  ],

  "identifications": [
    {
      "id": 91,
      "kid": 1485348238,
      "art": "Personalausweis",       // "Personalausweis" | "Reisepass" (select_fields.identifications.ident_art)
      "behoerde": "Stadt München",
      "ausgestellt": "2020-03-15",
      "gueltig": "2030-03-14",
      "insert_datum": null,
      "edit_datum": null
    }
  ],

  "jobs": [
    {
      "id": 43,
      "kid": 1485348238,
      "arbeitgeber": "ACME GmbH",
      "beruf": "Geschäftsführer",
      "berufsstatus": "Geschäftsführer",   // siehe select_fields.jobs.berufsstatus
      "datum_eintritt": "2010-04-01",
      "datum_austritt": null,
      "insert_datum": "2021-04-13 11:00:00", // Sub-Resources: Datetime statt Date-only
      "edit_datum":   "2021-04-13 11:00:09"
    }
  ]
}

Endpoints

Kunden abfragen

Liefert eine paginierte Liste der Kunden deiner Organisation. Unterressourcen sind standardmäßig nicht eingebunden — wer sie braucht, schaltet sie pro Resource über with_*=true ein.

Query-Parameter

  • page — Seitenindex (Default 1).
  • limit — Items pro Seite (Default 50, Max 5000).
  • with_addresses — Adressen inline mitliefern. Default false (opt-in). Auf true oder 1 setzen zum Aktivieren.
  • with_contacts — Kontaktdaten (E-Mail, Telefon …) inline mitliefern. Default false (opt-in).
  • with_jobs — Berufsangaben inline mitliefern. Default false (opt-in).
  • with_banks — Bankverbindungen inline mitliefern. Default false (opt-in).
  • with_numbers — Nummern (Kundennummer, Vermittler-Nr. …) inline mitliefern. Default false (opt-in).
  • with_identifications — Ausweisdaten inline mitliefern. Default false (opt-in).
  • with_schema — Feld-Schema (Labels, Typen, Option-Quellen) im Response unter fields und select_fields mitliefern. Default false (opt-in).
  • flat — Unterressourcen-Arrays in flache Keys ausrollen statt als Array zurückzugeben. Default false. Das erste Element heißt addresses_strasse, das zweite addresses_1_strasse, das dritte addresses_2_strasse. Leere Sub-Resource-Arrays produzieren keine Keys.

Request

bash
curl 'https://www.api.i-planner.app/v3/customers?page=1&limit=50&with_jobs=false' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Response

json
// OK — Pagination-Envelope + `items[]`. Jedes Item ist ein
// vollständiges Customer-Objekt mit Unterressourcen-Arrays — siehe
// „Das Customer-Objekt" oben für die volle Struktur.
{
  "page": 1,
  "page_size": 50,
  "total": 4217,
  "items": [
    {
      "kid": 12345,
      "id": 67890,
      "vorname": "Helmut",
      "name": "Leier",
      // … weitere Felder + addresses[], contacts[], jobs[],
      // banks[], numbers[], identifications[]
    }
  ],
  "fields": {
    "customers": {
      "vorname": { "label": "Vorname", "data_type": "string", "select_fields_name": null }
    }
  },
  "select_fields": { "customers": {} }
}

Kunden anlegen

Legt einen oder mehrere Kunden an. Der Request-Body kann entweder ein einzelnes Customer-Objekt oder ein Array von Customer-Objekten sein (Batch, max. 100 Items).

Body-Schema

Der Body enthält nur die direkten Felder des Customer-Objekts (anrede, vorname, name, geb, …). Welche Felder dein Tenant kennt, siehst du im Schema-Tab oben oder live über GET /v3/customers?with_schema=true.

Verhalten bei unbekannten Feldern: Felder, die nicht zum Schema gehören oder system-intern sind (id, kid, guid, insert_datum, edit_datum, del, alle vm_* / push_* / alert_* / Passwort-Felder), werden stillschweigend verworfen — kein 400-Error. Schickst du ein leeres Objekt oder eines mit ausschließlich verworfenen Feldern, antwortet der Server allerdings mit 400 no_valid_fields.

Sonderfeld betreuer: Numerische kid des zuständigen Mitarbeiters. Fehlt das Feld, setzt die API automatisch die kid des authentifizierten Tokens (= „du bist Betreuer").

Batch-Verhalten: Jedes Item wird einzeln in einer eigenen Transaktion angelegt (INSERT + Search-Index + Log + Document-Ordner). Schlägt ein Item fehl, landet es in failed[], der Rest des Batches läuft normal weiter — keine alle-oder-keiner-Semantik. Bis zu 10 Items werden parallel verarbeitet.

Request

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{

    "anrede": "frau",
    "vorname": "Anna",
    "name": "Müller",
    "geb": "1985-03-12"
  }'

Response

json
// Created — nur bei Single-Item-Request UND erfolgreich.
// Der Body ist direkt das angelegte Customer-Objekt (kein Wrapper),
// inkl. der vom Server vergebenen `kid` und `id` plus
// `insert_datum` / `edit_datum`.
{
  "kid": 12346,
  "id": 67890,
  "vorname": "Anna",
  "name": "Müller",
  "geb": "1985-03-12",
  "insert_datum": "2026-05-12",
  "edit_datum": "2026-05-12",
  "betreuer": 42
}

Kunden abrufen

GET/v3/customers/<kid> Im Playground testen ↗

Liefert einen einzelnen Customer-Datensatz inklusive Unterressourcen. <id> ist die numerische kid.

Query-Parameter — identisch zu GET /v3/customers (with_addresses, with_contacts, with_jobs, with_banks, with_numbers, with_identifications, with_schema, flat). Default für alle: false (opt-in) — Sub-Ressourcen müssen explizit per ?with_addresses=true etc. angefordert werden.

Request

bash
curl 'https://www.api.i-planner.app/v3/customers/12345' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Response

json
// OK — Customer-Datensatz inkl. aller Unterressourcen (sofern
// `with_*=true`). Schema-Hinweise siehe „Das Customer-Objekt" oben.
{
  "kid": 12345,
  "id": 67890,
  "vorname": "Helmut",
  "name": "Leier",
  "addresses": [ /* … */ ],
  "contacts":  [ /* … */ ]
}

Unterscheidung 404-Varianten — endpoint_not_found kommt, wenn <id> nicht numerisch ist (z. B. eine UUID übergeben wurde — die Route existiert für den Pfad nicht). not_found kommt, wenn <id> numerisch und gültig ist, aber kein Kunde mit dieser kid in deiner Organisation existiert oder bereits soft-deleted ist.

Kunden aktualisieren

PATCH/v3/customers/<kid> Im Playground testen ↗

Aktualisiert die im Body gesendeten Felder eines Customers. Felder, die nicht im Body stehen, bleiben unverändert (PATCH-Semantik, kein PUT).

Wie beim POST gilt: Unterressourcen-Arrays werden ignoriert — addresses, contacts, banking etc. im PATCH-Body bewirken nichts. Unterressourcen werden über ihre eigenen Endpoints (PATCH /v3/customers/<kid>/addresses/<id> usw.) aktualisiert. Unbekannte und system-interne Felder werden still verworfen (gleiches Verhalten wie beim Create).

Request

bash
curl -X PATCH 'https://www.api.i-planner.app/v3/customers/12345' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "kommentar": "Aktualisiert per API am 2026-05-12" }'

Response

json
// OK — Update angewendet. Der Body ist kompakt: ein Success-Flag
// und `updated` = Anzahl der tatsächlich geänderten Felder. Der
// volle aktualisierte Datensatz wird NICHT zurückgegeben — wer ihn
// braucht, ruft danach `GET /v3/customers/<id>` auf.
{
  "success": true,
  "updated": 1
}

Kunden löschen

DELETE/v3/customers/<kid> Im Playground testen ↗

Markiert den Customer als gelöscht (del=1), entfernt ihn aber nicht hart aus der Datenbank — analog zum „Papierkorb" im UI. Der Datensatz wird aus Listen-Responses und Suchergebnissen ausgeblendet, bleibt aber für Audit-Zwecke erhalten.

Request

bash
curl -X DELETE 'https://www.api.i-planner.app/v3/customers/12345' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Response

json
// OK — Customer wurde als gelöscht markiert (Soft-Delete via `del=1`).
// Der Datensatz bleibt in der Datenbank für Audit-Zwecke erhalten, ist
// aber aus Listen-Responses und Suchergebnissen ausgeblendet.
{
  "success": true,
  "deleted": true,
  "soft_deleted": true,
  "kid": 12345
}

Duplikat zusammenführen

POST/v3/customers/<kid>/merge

Führt einen Slave-Customer in den Master zusammen. Alle Sub-Ressourcen des Slave werden auf den Master umgehängt, der Slave-Datensatz wird soft-deleted (del=1). Der Vorgang läuft in einer Transaktion — entweder gehen alle Daten über, oder gar keine.

Anwendungsfall: Derselbe Kunde wurde versehentlich doppelt erfasst (z. B. einmal über Posteingang-Import, einmal manuell). Du wählst eine der beiden Karteien als "die Wahrheit" (Master) und schiebst alles aus der anderen (Slave) hinein.

Was wandert auf den Master?

BereichVerhalten
addresses, contacts, banking, numbers, jobs, identitySlave-Zeilen bleiben als zusätzliche Rows am Master bestehen (kid-Rewrite).
contracts, damages, finances, goals, activities, documents (inkl. Ordner-Baum)kid-Rewrite — alle CRM-Objekte des Slave gehören danach dem Master.
comments, tags, followersAnnotationen, die per (section='customers', <row-pk>) auf den Slave zeigen, werden auf die Master-crm_kontakte.id umgeschrieben.
links (crm_relations)Beide Richtungen umgeschrieben; master↔master-Self-Loops, die dabei entstehen, werden direkt gelöscht.
relations (Ehe-/Verwandtschaft)Beide kid-Spalten umgeschrieben; master↔master-Self-Loops werden gelöscht.

Was bleibt am Slave?

  • Die crm_kontakte-Zeile selbst bekommt del=1 und ist über GET /v3/customers/<slave-kid> ab sofort als 404 not_found markiert.
  • Das crm_log (Audit-Trail) des Slave bleibt unangetastet — Bewegungen vor dem Merge sollen historisch nachvollziehbar bleiben.
  • Der Such-Index-Eintrag des Slave wird entfernt (der Master behält seinen eigenen).

Konflikt-Strategie für die Stammdaten — über das mode-Feld steuerbar:

modeVerhalten
master_wins (Default)Master-Stammdaten (Name, Anrede, Geburtsdatum etc.) bleiben unverändert.
enrich_masterLeere Master-Felder werden mit Slave-Werten gefüllt. Felder mit Wert am Master werden nie überschrieben. Betrifft nur crm_kontakte-Skalare (vorname, name, titel, anrede, geb_name, namenszusatz, geb).

Audit-Log: Auf der Master-Seite wird ein CUSTOMERS_MERGE-Eintrag geschrieben, der Master- und Slave-Display-Namen referenziert. Im Activity-Feed erscheint die Zeile "… hat den Kunden <Master> mit <Slave> zusammengeführt."

Body

FeldTypPflichtDefaultBemerkung
slave_kidinteger | numerische string✓—Die kid des Slave-Customers. Muss ≠ <kid> aus dem Pfad sein.
modemaster_wins | enrich_master—master_winsKonflikt-Strategie für crm_kontakte-Skalare.

Request

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/merge' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{
    "slave_kid": 67890,
    "mode": "master_wins"
  }'

Response

json
// OK — Merge erfolgreich. Slave-kid ist soft-deleted, alle Sub-Resources
// hängen am Master.
{
  "success": true,
  "master_kid": 12345,
  "slave_kid": 67890,
  "mode": "master_wins"
}

Unterressourcen

Jede Unterressource hängt über kid an einem Customer und folgt demselben Pagination-Envelope (page, page_size, total, items) wie die Customer-Liste. POST/PATCH/DELETE verhalten sich wie bei den Customer-Endpoints — Unknown- und Protected-Fields werden still verworfen, Fehler-Bodies folgen dem gleichen Muster (empty_body, invalid_id, not_found etc.).

Direkt am Customer — feste Bestandteile des Customer-Schemas. Jede Unterressource hat einen Listen-Endpoint (/v3/customers/<kid>/<sub-resource>), einen Create-Endpoint am gleichen Pfad und einen <id>-Pfad für Retrieve/Update/Delete (/v3/customers/<kid>/<sub-resource>/<id>). Path-kid ist Source-of-Truth — POST/PATCH-Bodies dürfen kid nicht enthalten, sonst antwortet der Server mit 400 body_kid_forbidden.

Addresses

Adressen eines Customers. Pro Customer können mehrere Adressen hinterlegt sein (Erstanschrift, Zweitanschrift, Geschäftlich, …); die Unterscheidung läuft über das Freitext-Feld bezeichnung.

Scopes: v3:customers:read (List + Get) · v3:customers:write (Create + Patch + Delete).

json
{
  "id": 840,                          // numerischer Row-Identifier (Postgres-PK)
  "kid": 1485348238,                  // Customer, an dem die Adresse hängt
  "art": 0,                           // numerischer Adress-Typ — in v3 nur 0 belegt
  "bezeichnung": "Geschäftlich",      // Freitext-Label: "Erstanschrift", "Zweitanschrift", "Geschäftlich", …
  "adresszusatz": "Herr Michael Absmeier",
  "strasse": "Bahnhofstraße 20",
  "plz": "94099",
  "ort": "Ruhstorf-Sulzbach (Inn)",
  "bundesland": "Bayern",
  "insert_datum": null,
  "edit_datum": null
}
GET/v3/customers/<kid>/addresses Im Playground testen ↗
POST/v3/customers/<kid>/addresses Im Playground testen ↗
GET/v3/customers/<kid>/addresses/<id> Im Playground testen ↗
PATCH/v3/customers/<kid>/addresses/<id> Im Playground testen ↗
DELETE/v3/customers/<kid>/addresses/<id> Im Playground testen ↗

Query-Parameter

  • kid (im Pfad, nicht als Query) — Customer-ID des Parents. Bei Sub-Resources steht die ID jetzt im URL-Pfad statt im Query-String.
  • page — Seitenindex (Default 1).
  • limit — Items pro Seite (Default 50, Max 5000).
  • with_schema — Feld-Schema (fields + select_fields) im Response mitliefern. Default false (opt-in).

Beispiel — Adressen eines Kunden abfragen

bash
curl 'https://www.api.i-planner.app/v3/customers/12345/addresses' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Beispiel — neue Adresse anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/addresses' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "bezeichnung": "Erstanschrift",
    "strasse": "Musterweg 1",
    "plz": "80331",
    "ort": "München",
    "bundesland": "Bayern"
  }'

Beispiel — Adresse löschen

bash
curl -X DELETE 'https://www.api.i-planner.app/v3/customers/12345/addresses/78001' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Contacts

Kontaktdaten eines Customers — eine Zeile pro Kanal (E-Mail, Telefon, Fax, Website …). Genaue Felder hängen vom Tenant-Schema ab.

Scopes: v3:customers:read (List + Get) · v3:customers:write (Create + Patch + Delete).

json
{
  "id": 3338,
  "kid": 1485348238,
  "art": "E-Mail",                    // "E-Mail" | "Telefon" — capitalized, kein snake_case
  "wert": "michael@absmeierfv.de",
  "werbung": 0,                       // 0=Marketing-Opt-out, 1=Opt-in (DSGVO-relevant)
  "insert_datum": null,
  "edit_datum": null
}
GET/v3/customers/<kid>/contacts Im Playground testen ↗
POST/v3/customers/<kid>/contacts Im Playground testen ↗
GET/v3/customers/<kid>/contacts/<id> Im Playground testen ↗
PATCH/v3/customers/<kid>/contacts/<id> Im Playground testen ↗
DELETE/v3/customers/<kid>/contacts/<id> Im Playground testen ↗

Query-Parameter

  • kid (im Pfad, nicht als Query) — Customer-ID des Parents. Bei Sub-Resources steht die ID jetzt im URL-Pfad statt im Query-String.
  • page — Seitenindex (Default 1).
  • limit — Items pro Seite (Default 50, Max 5000).
  • with_schema — Feld-Schema im Response mitliefern. Default false (opt-in).

Beispiel — Kontaktdaten eines Kunden abfragen

bash
curl 'https://www.api.i-planner.app/v3/customers/12345/contacts' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Beispiel — E-Mail-Adresse anlegen (mit Marketing-Opt-in)

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/contacts' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "art": "E-Mail",
    "wert": "neu@example.com",
    "werbung": 1
  }'

Beispiel — Kontaktdatensatz löschen

bash
curl -X DELETE 'https://www.api.i-planner.app/v3/customers/12345/contacts/79001' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Banking

Bankverbindungen eines Customers. Genaue Felder hängen vom Tenant-Schema ab.

Scopes: v3:customers:read (List + Get) · v3:customers:write (Create + Patch + Delete).

json
{
  "id": 4,
  "kid": 1485348238,
  "typ": "0",                         // "0"=Konto, "1"=Depot — String (in select_fields auch number)
  "inhaber": "Absmeier, Michael",
  "nummer": "",                       // Legacy-Kontonummer (vor IBAN-Pflicht), typisch leer
  "iban": "DE50750700240505025700",
  "bic": "DEUTDEDB750",
  "institut": "Deutsche Bank Privat und Geschäftskunden, Regensburg",
  "insert_datum": null,
  "edit_datum": null
}
GET/v3/customers/<kid>/banking Im Playground testen ↗
POST/v3/customers/<kid>/banking Im Playground testen ↗
GET/v3/customers/<kid>/banking/<id> Im Playground testen ↗
PATCH/v3/customers/<kid>/banking/<id> Im Playground testen ↗
DELETE/v3/customers/<kid>/banking/<id> Im Playground testen ↗

Query-Parameter

  • kid (im Pfad, nicht als Query) — Customer-ID des Parents. Bei Sub-Resources steht die ID jetzt im URL-Pfad statt im Query-String.
  • page — Seitenindex (Default 1).
  • limit — Items pro Seite (Default 50, Max 5000).
  • with_schema — Feld-Schema im Response mitliefern. Default false (opt-in).

Beispiel — Bankverbindungen abfragen

bash
curl 'https://www.api.i-planner.app/v3/customers/12345/banking' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Beispiel — Bankverbindung anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/banking' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "typ": "0",
    "inhaber": "Helmut Leier",
    "iban": "DE89370400440532013000",
    "bic": "SSKMDEMM",
    "institut": "Sparkasse München"
  }'

Beispiel — Bankverbindung löschen

bash
curl -X DELETE 'https://www.api.i-planner.app/v3/customers/12345/banking/80001' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Nummern

Kunden-, Vermittler-, Steuer- und sonstige Identifizierungsnummern. Genaue Felder hängen vom Tenant-Schema ab.

Scopes: v3:customers:read (List + Get) · v3:customers:write (Create + Patch + Delete).

json
{
  "id": 6,
  "kid": 1485504800,
  "art": 1,                           // numerischer Nummern-Typ — pro Tenant konfiguriert
  "wert": "143/188/4024",
  "insert_datum": null,
  "edit_datum": null
}
GET/v3/customers/<kid>/numbers Im Playground testen ↗
POST/v3/customers/<kid>/numbers Im Playground testen ↗
GET/v3/customers/<kid>/numbers/<id> Im Playground testen ↗
PATCH/v3/customers/<kid>/numbers/<id> Im Playground testen ↗
DELETE/v3/customers/<kid>/numbers/<id> Im Playground testen ↗

Query-Parameter

  • kid (im Pfad, nicht als Query) — Customer-ID des Parents. Bei Sub-Resources steht die ID jetzt im URL-Pfad statt im Query-String.
  • page — Seitenindex (Default 1).
  • limit — Items pro Seite (Default 50, Max 5000).
  • with_schema — Feld-Schema im Response mitliefern. Default false (opt-in).

Beispiel — Nummern abfragen

bash
curl 'https://www.api.i-planner.app/v3/customers/12345/numbers' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Beispiel — neue Nummer anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/numbers' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "art": 1,
    "wert": "K-9876543"
  }'

Beispiel — Nummer löschen

bash
curl -X DELETE 'https://www.api.i-planner.app/v3/customers/12345/numbers/81001' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Identity

Ausweisdaten eines Customers — Personalausweis oder Reisepass.

Scopes: v3:customers:read (List + Get) · v3:customers:write (Create + Patch + Delete).

json
{
  "id": 91,
  "kid": 1485348238,
  "art": "Personalausweis",           // "Personalausweis" | "Reisepass" — capitalized String
  "behoerde": "Stadt München",        // ausstellende Behörde
  "ausgestellt": "2020-03-15",        // Ausstellungsdatum (Date)
  "gueltig": "2030-03-14",            // Ablaufdatum (Date)
  "insert_datum": null,
  "edit_datum": null
}
GET/v3/customers/<kid>/identity Im Playground testen ↗
POST/v3/customers/<kid>/identity Im Playground testen ↗
GET/v3/customers/<kid>/identity/<id> Im Playground testen ↗
PATCH/v3/customers/<kid>/identity/<id> Im Playground testen ↗
DELETE/v3/customers/<kid>/identity/<id> Im Playground testen ↗

Query-Parameter

  • kid (im Pfad, nicht als Query) — Customer-ID des Parents. Bei Sub-Resources steht die ID jetzt im URL-Pfad statt im Query-String.
  • page — Seitenindex (Default 1).
  • limit — Items pro Seite (Default 50, Max 5000).
  • with_schema — Feld-Schema im Response mitliefern. Default false (opt-in).

Beispiel — Ausweisdaten abfragen

bash
curl 'https://www.api.i-planner.app/v3/customers/12345/identity' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Beispiel — Reisepass anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/identity' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "art": "Reisepass",
    "behoerde": "Landratsamt München",
    "ausgestellt": "2022-06-10",
    "gueltig": "2032-06-09"
  }'

Beispiel — Ausweisdaten löschen

bash
curl -X DELETE 'https://www.api.i-planner.app/v3/customers/12345/identity/82001' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Jobs

Beruf, Arbeitgeber und Beschäftigungs-Details eines Customers. Genaue Felder hängen vom Tenant-Schema ab.

Scopes: v3:customers:read (List + Get) · v3:customers:write (Create + Patch + Delete).

json
{
  "id": 43,
  "kid": 1485504800,
  "arbeitgeber": "ACME GmbH",
  "beruf": "Geschäftsführer",
  "berufsstatus": "Geschäftsführer",     // siehe select_fields["berufsstatus"]
  "datum_eintritt": "2010-04-01",
  "datum_austritt": null,                 // null = aktuell beschäftigt
  "insert_datum": "2021-04-13 11:00:00",  // Sub-Resources: Datetime statt Date-only
  "edit_datum":   "2021-04-13 11:00:09"
}
GET/v3/customers/<kid>/jobs Im Playground testen ↗
POST/v3/customers/<kid>/jobs Im Playground testen ↗
GET/v3/customers/<kid>/jobs/<id> Im Playground testen ↗
PATCH/v3/customers/<kid>/jobs/<id> Im Playground testen ↗
DELETE/v3/customers/<kid>/jobs/<id> Im Playground testen ↗

Query-Parameter

  • kid (im Pfad, nicht als Query) — Customer-ID des Parents. Bei Sub-Resources steht die ID jetzt im URL-Pfad statt im Query-String.
  • page — Seitenindex (Default 1).
  • limit — Items pro Seite (Default 50, Max 5000).
  • with_schema — Feld-Schema im Response mitliefern. Default false (opt-in).

Beispiel — Berufsangaben abfragen

bash
curl 'https://www.api.i-planner.app/v3/customers/12345/jobs' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Beispiel — Beruf anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/jobs' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "arbeitgeber": "ACME GmbH",
    "beruf": "Senior Developer",
    "berufsstatus": "Angestellt",
    "datum_eintritt": "2024-01-15"
  }'

Beispiel — Berufseintrag löschen

bash
curl -X DELETE 'https://www.api.i-planner.app/v3/customers/12345/jobs/83001' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Tags

Freie Beschriftungs-Tags am Customer (z. B. „VIP", „Newsletter", „Bestandskunde"). Genaue Felder hängen vom Tenant-Schema ab.

Scopes: v3:customers:read (List) · v3:customers:write (Create + Delete).

json
{
  "id": 84001,
  "kid": 12345,
  "name": "VIP",
  "farbe": "#FFB400",     // Hex- oder Token-Wert (abhängig vom Tenant)
  "insert_datum": "2024-08-14",
  "edit_datum": "2024-08-14"
}
GET/v3/customers/<kid>/tags Im Playground testen ↗
POST/v3/customers/<kid>/tags Im Playground testen ↗
DELETE/v3/customers/<kid>/tags/<id> Im Playground testen ↗

Query-Parameter

  • kid (im Pfad, nicht als Query) — Customer-ID des Parents. Bei Sub-Resources steht die ID jetzt im URL-Pfad statt im Query-String.
  • page — Seitenindex (Default 1).
  • limit — Items pro Seite (Default 50, Max 5000).
  • with_schema — Feld-Schema im Response mitliefern. Default false (opt-in).

Beispiel — Tags eines Kunden abfragen

bash
curl 'https://www.api.i-planner.app/v3/customers/12345/tags' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Beispiel — Tag setzen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/tags' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Bestandskunde",
    "farbe": "#22C55E"
  }'

Beispiel — Tag entfernen

bash
curl -X DELETE 'https://www.api.i-planner.app/v3/customers/12345/tags/84001' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

CRM-Objekte am Customer — eigenständige Datensätze (Verträge, Schäden, Finanzen, Ziele), die im Customer-Kontext angelegt und gelistet werden. Jedes hat deep paths für angehängte Comments / Documents / Followers / Tags (siehe Anhänge an CRM-Objekten unten).

Contracts

Versicherungs-, Finanzierungs- und sonstige Verträge eines Customers. Genaue Felder hängen vom Tenant-Schema ab.

json
{
  "id": 90001,
  "kid": 12345,
  "nummer": "V-2024-00471",          // interne Vertragsnummer
  "gesellschaft": "Allianz",          // Versicherer / Anbieter
  "sparte": "krankenversicherung",    // siehe Schema-Tab
  "tarif": "Vital BestMed",
  "beitrag": 87.50,                   // periodischer Beitrag in EUR
  "intervall": "monatlich",           // monatlich | jaehrlich | einmalig
  "beginn": "2024-01-01",
  "ende": null,                       // null = unbefristet
  "status": "aktiv",                  // aktiv | gekuendigt | ruht
  "insert_datum": "2024-01-15",
  "edit_datum": "2024-06-02"
}

Customer-scoped (Listing + Create only):

GET/v3/customers/<kid>/contracts Im Playground testen ↗
POST/v3/customers/<kid>/contracts Im Playground testen ↗

Read / Update / Delete laufen über die globally-unique Contract-id top-level — siehe Verträge für die vollständige API:

  • GET /v3/contracts/<id> — Vertrag abrufen
  • PATCH /v3/contracts/<id> — Vertrag aktualisieren
  • DELETE /v3/contracts/<id> — Vertrag löschen

Zusätzliche Helper-Endpoints

  • GET /v3/system/sparten — Liste der verfügbaren Sparten als Reference-Daten. Kein kid-Parameter, weil global. Scope v3:system:read (siehe System).
  • /v3/contracts/<id>/persons und /v3/contracts/<id>/tariffs — Sub-Resources versicherte Personen und Tarif-Optionen, top-level über die Contract-id.

Query-Parameter (List)

  • kid (im Pfad, nicht als Query) — Customer-ID des Parents.
  • page, limit, with_schema — wie bei den direkten Unterressourcen.

Beispiel — Verträge eines Kunden abfragen

bash
curl 'https://www.api.i-planner.app/v3/customers/12345/contracts' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Beispiel — Vertrag anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/contracts' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "nummer": "H-2026-00012",
    "gesellschaft": "HUK24",
    "sparte": "haftpflicht",
    "beitrag": 7.90,
    "intervall": "monatlich",
    "beginn": "2026-06-01"
  }'

Beispiel — Vertrag löschen (top-level über die globally-unique id)

bash
curl -X DELETE 'https://www.api.i-planner.app/v3/contracts/90001' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN"

Damages

Schadensfälle / Schadenmeldungen am Customer.

Scopes: v3:damages:read (List + Get) · v3:damages:write (Create + Patch + Delete).

json
{
  "id": 91001,
  "kid": 12345,
  "schadennummer": "S-2026-00018",
  "vertrag_id": 90001,              // optionale Verknüpfung zum Vertrag
  "art": "haftpflicht",
  "datum": "2026-04-21",            // Schadendatum
  "schadenshoehe": 1250.00,
  "status": "in_bearbeitung",       // gemeldet | in_bearbeitung | reguliert | abgelehnt
  "beschreibung": "Wasserschaden in der Küche",
  "insert_datum": "2026-04-22",
  "edit_datum": "2026-04-23"
}

Customer-scoped (Listing + Create only):

GET/v3/customers/<kid>/damages Im Playground testen ↗
POST/v3/customers/<kid>/damages Im Playground testen ↗

Read / Update / Delete laufen über die globally-unique Schaden-id top-level — siehe Schäden für die vollständige API.

Query-Parameter (List) — kid (im Pfad), page, limit, with_schema.

Beispiel — Schaden anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/damages' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "vertrag_id": 90001,
    "art": "haftpflicht",
    "datum": "2026-04-21",
    "schadenshoehe": 1250.00,
    "beschreibung": "Wasserschaden in der Küche"
  }'

Finances

Finanz-Positionen am Customer (Einnahmen, Ausgaben, Vermögen, Schulden).

Scopes: v3:finances:read (List + Get) · v3:finances:write (Create + Patch + Delete).

json
{
  "id": 92001,
  "kid": 12345,
  "art": "einnahme",                  // einnahme | ausgabe | vermoegen | verbindlichkeit
  "kategorie": "gehalt",
  "betrag": 4500.00,
  "intervall": "monatlich",
  "beginn": "2024-01-01",
  "ende": null,
  "beschreibung": "Grundgehalt Festanstellung",
  "insert_datum": "2024-01-15",
  "edit_datum": "2024-01-15"
}

Customer-scoped (Listing + Create only):

GET/v3/customers/<kid>/finances Im Playground testen ↗
POST/v3/customers/<kid>/finances Im Playground testen ↗

Read / Update / Delete laufen über die globally-unique Finanz-id top-level — siehe Finanzen für die vollständige API.

Query-Parameter (List) — kid (im Pfad), page, limit, with_schema.

Beispiel — Finanz-Position anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/finances' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "art": "ausgabe",
    "kategorie": "miete",
    "betrag": 1450.00,
    "intervall": "monatlich"
  }'

Goals

Finanz-/Lebensziele eines Customers (Altersvorsorge, Hauskauf, Studium der Kinder …).

Scopes: v3:goals:read (List + Get) · v3:goals:write (Create + Patch + Delete).

json
{
  "id": 93001,
  "kid": 12345,
  "titel": "Altersvorsorge",
  "kategorie": "altersvorsorge",      // siehe Schema-Tab
  "zielbetrag": 250000.00,
  "zieldatum": "2055-01-01",
  "prioritaet": 1,                    // 1 = hoch, 3 = niedrig
  "status": "in_planung",             // in_planung | aktiv | erreicht | verworfen
  "beschreibung": "Private Rentenversicherung + ETF-Sparplan",
  "insert_datum": "2024-01-15",
  "edit_datum": "2026-03-12"
}

Customer-scoped (Listing + Create only):

GET/v3/customers/<kid>/goals Im Playground testen ↗
POST/v3/customers/<kid>/goals Im Playground testen ↗

Read / Update / Delete laufen über die globally-unique Ziel-id top-level — siehe Ziele für die vollständige API.

Query-Parameter (List) — kid (im Pfad), page, limit, with_schema.

Beispiel — Ziel anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/goals' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "titel": "Hauskauf",
    "kategorie": "immobilie",
    "zielbetrag": 400000.00,
    "zieldatum": "2030-06-01",
    "prioritaet": 1
  }'

Aktivitäten & Kollaboration — generische Anhang-Ressourcen am Customer: Kommentare, Dokumente und Follower.

Comments

Freitext-Kommentare am Customer. Full-CRUD: List, Get, Create, Patch, Delete.

Scopes: v3:customers:read (List + Get) · v3:customers:write (Create + Patch + Delete).

json
{
  "id": 95001,
  "kid": 12345,
  "text": "Kunde hat per E-Mail nach einer Vertragsanpassung gefragt.",
  "autor_kid": 7,                     // ausdrücklich angegebener Berater; 0 = Organisationstoken
  "autor_name": "Anna Berater",
  "insert_datum": "2026-05-12T14:23:00.000Z"
}
GET/v3/customers/<kid>/comments Im Playground testen ↗
POST/v3/customers/<kid>/comments Im Playground testen ↗
GET/v3/customers/<kid>/comments/<id> Im Playground testen ↗
PATCH/v3/customers/<kid>/comments/<id> Im Playground testen ↗
DELETE/v3/customers/<kid>/comments/<id> Im Playground testen ↗

Query-Parameter (List) — kid (Pflicht), page, limit. Comments haben kein konfigurierbares Schema; with_schema wird ignoriert.

Beim POST ist text Pflicht. Optional kann autor_kid die KID eines aktiven Beraters derselben Organisation angeben. Die API prüft die Berater-Mitgliedschaft; eine unbekannte, gelöschte oder inaktive KID wird mit HTTP 400 (invalid_author_kid) abgelehnt. Ohne autor_kid erscheint der Name des Organisationstokens als Kommentarautor (autor_kid: 0). Das Änderungsprotokoll nennt in beiden Fällen den ausführenden Token. PATCH ändert nur den Text und lässt den beim POST bestimmten Autor bestehen.

Beispiel — Kommentar anlegen

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/comments' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Telefonat: Kunde möchte Beratungstermin im Juni.",
    "autor_kid": 7
  }'

Documents

Dokumente am Customer (PDF, Bilder, beliebige Datei-Typen). Werden in einer Ordnerstruktur abgelegt; die Default-Ordner Dokumente wird beim Customer-Create automatisch angelegt.

Scopes: v3:documents:read (List + Get + Folders) · v3:documents:write (Create + Patch + Delete).

json
{
  "id": 96001,
  "kid": 12345,
  "name": "Versicherungsschein-Allianz-2024.pdf",
  "mime_type": "application/pdf",
  "dateigroesse": 142315,             // Bytes
  "ordner_id": 5001,                  // Verweis auf einen Folder, siehe GET .../folders
  "ordner_name": "Verträge",
  "beschreibung": "KV-Police Vital BestMed",
  "insert_datum": "2024-01-16",
  "edit_datum": "2024-01-16"
}

Customer-scoped (Listing + Create only):

GET/v3/customers/<kid>/documents Im Playground testen ↗
POST/v3/customers/<kid>/documents Im Playground testen ↗
GET/v3/customers/<kid>/documents/folders Im Playground testen ↗

Read / Update / Delete laufen über die globally-unique Dokument-id top-level — siehe Dokumente für die vollständige API.

Query-Parameter (List) — kid (im Pfad), page, limit. Optional ordner_id zum Filtern auf einen bestimmten Ordner.

Beispiel — Dokument hochladen (Datei-Inhalt als Base64-String im inhalt-Feld)

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/documents' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Vertragsanlage.pdf",
    "mime_type": "application/pdf",
    "ordner_id": 5001,
    "inhalt": "JVBERi0xLjQKJeLjz9MK…"
  }'

Followers

Mitarbeiter, die einen Customer „abonniert" haben — bekommen Notifications bei Änderungen. Keine eigenen Datensatz-Felder außer der User-Verknüpfung.

Scopes: v3:customers:read (List) · v3:customers:write (Create + Delete).

json
{
  "id": 97001,
  "kid": 12345,                       // beobachteter Customer
  "user_kid": 7,                      // Mitarbeiter, der folgt
  "user_name": "Helmut Leier",
  "insert_datum": "2026-04-20"
}
GET/v3/customers/<kid>/followers Im Playground testen ↗
POST/v3/customers/<kid>/followers Im Playground testen ↗
DELETE/v3/customers/<kid>/followers/<id> Im Playground testen ↗

Query-Parameter (List) — kid (Pflicht), page, limit.

Beispiel — Customer abonnieren

bash
curl -X POST 'https://www.api.i-planner.app/v3/customers/12345/followers' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "user_kid": 7
  }'

Anhänge an CRM-Objekten

Comments, Documents, Followers und Tags lassen sich auch an einem konkreten CRM-Objekt anlegen — z. B. ein Kommentar zu einem Vertrag, ein Dokument an einem Schaden.

Pfad-Pattern für Sub-Domains mit globally-unique id (contracts, damages, finances, goals, contact-persons, portals):

/v3/<section>/<sectionId>/<resource>[/<id>]

Pfad-Pattern für Identity — eine customer-direkte Sub-Resource ohne eigenen Top-Level:

/v3/customers/<kid>/identity/<sectionId>/<resource>[/<id>]
  • <section> — contracts, damages, finances, goals, contact-persons, portals (oder customers/<kid>/identity)
  • <sectionId> — Integer-ID des konkreten Section-Objekts
  • <resource> — comments, documents, followers oder tags

Scopes: je nach <resource> — v3:customers:* für comments / followers / tags an Customer-direkten Subs, v3:documents:* für documents. Ein Parent-Scope wie v3:contracts:read ersetzt niemals den Dokument-Scope. Der Parent-Datensatz selbst bleibt an seine eigene Scope-Familie gebunden.

Felder, Methods und Response-Bodies sind identisch zu den Customer-Level-Pendants oben — der einzige Unterschied: kein kid-Body-Feld, kein kid-Query-Param. Beides ergibt sich aus dem Pfad. POST/PATCH-Bodies mit kid-Feld werden mit 400 body_kid_forbidden abgelehnt.

bash
curl -X POST 'https://www.api.i-planner.app/v3/contracts/90001/comments' \
  -H "Authorization: Bearer $IPLANNER_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "text": "Beitragserhöhung 2026 vorgemerkt." }'