> ## Documentation Index
> Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt
> Use this file to discover all available pages before exploring further.

# Account-API

> REST-Schnittstelle zum Anlegen, Aktualisieren und Anmelden einzelner Kundenkonten über signierte JSON-WebTokens, mit Konnektor-Konfiguration und Berechtigungen.

Mit der Account-API legen Sie einzelne Kundenkonten an und aktualisieren sie, unabhängig von einem ERP- oder Warenwirtschaftssystem. Zusätzlich lässt sich ein Kunde über diese Schnittstelle im Shop anmelden. Welche Bereiche der Kundendaten ein Zugang lesen und schreiben darf, konfigurieren Sie pro Konnektor.

| Eigenschaft | Wert |
| - | - |
| Info | Einzelne Felder der Kundendaten bei Neuanlage vorbelegen oder aktualisieren |
| Übertragungsrichtung | Externes System → WEBSALE Shop (Data-to-Shop) |
| Übertragungsart | REST |
| Dateiformate | JSON |

> [!WARNING]
>
> Die Account-API ersetzt nicht den regulären Kundendatenimport. Wenn Sie komplette Kundendatensätze in den Shop importieren wollen, verwenden Sie [WS-SFTP-Kunden-Pro](https://dokumentation.websale.de/v8s/schnittstellen/kundendaten/ws-sftp-kunden-pro.md).

Jeder Datensatz, der über die Account-API eingeht, wird vom Shop so behandelt, als hätte der Kunde die Änderung selbst vorgenommen. Der Datensatz wird deshalb als geändert markiert und taucht beim Abruf der [Adressdatenänderungen](https://dokumentation.websale.de/v8s/schnittstellen/kundendaten/ws-adressdatenaenderungen.md) per SOAP auf.

## Technische Grundlagen

Die Schnittstelle hat einen einzigen Zugangspunkt. Die Daten werden als Payload in einem JSON-WebToken per POST übergeben.

Der Aufruf ist nur per SSL möglich. Eine Authentifizierung über ein Berechtigungstoken gibt es nicht, stattdessen validiert der Shop die Signatur des JSON-WebTokens. Dafür ist pro Konnektor ein eigenes SharedSecret hinterlegt. Die Berechtigungen des Konnektors konfiguriert WEBSALE. Jeder Aufruf muss mit der zugehörigen Shop-Domain erfolgen, denn über die Domain ermittelt der Shop den Subshop, dessen Konfiguration für die Prüfung der Adressdaten gilt.

Die Freischaltung der Account-API erfolgt auf Antrag des Shopbetreibers durch die WEBSALE AG. Dabei wird festgelegt, wie viele Konnektoren verwendet werden dürfen. Diese Anzahl lässt sich später per Antrag erhöhen oder senken. Die Konfiguration der einzelnen Konnektoren nehmen Sie selbst vor. Die Nutzung der Account-API erhöht den Leistungsverbrauch des Shops.

## Verhalten der Schnittstelle

Werden Adressdaten oder Kundenkontodaten übergeben, prüft der Shop zuerst, ob der Konnektor für jedes einzelne Feld die nötige Berechtigung hat. Fehlt sie auch nur für ein Feld, führt der Shop keine Aktion aus und gibt einen Fehler zurück. Teilweise Updates gibt es nicht.

Ein Kundenkonto lässt sich auf zwei Arten adressieren.

**Über die E-Mail-Adresse.** Existiert bereits ein Konto mit dieser Adresse, führt der Shop die gespeicherten Daten mit den übergebenen zusammen, wobei die übergebenen Werte die bestehenden überschreiben. Anschließend validiert er die Adressdaten gegen die im Shop konfigurierten Prüfungen. Nur wenn diese Prüfung bestanden ist, werden die Daten in der Kundendatenbank aktualisiert. Existiert noch kein Konto, legt der Shop nach erfolgreicher Prüfung ein neues an und kann dabei die in der Konnektor-Konfiguration hinterlegten Werte vorbelegen, beispielsweise einen eigenen Rabattsatz pro Konnektor.

**Über den UserIndex.** Hier ist nur die Aktualisierung oder Prüfung eines bestehenden Kontos möglich, ansonsten gilt dasselbe wie bei der Adressierung über die E-Mail-Adresse.

Mehrfachkonten, also mehrere Konten zu einer E-Mail-Adresse, lassen sich über die Account-API nicht anlegen. Update und Login sind für Mehrfachkonten nur über den UserIndex möglich.

Grundsätzlich gilt: Nach dem Zusammenführen der übergebenen und der vorbelegten Daten mit den vorhandenen Daten muss ein gültiger Datensatz entstehen. Ist das nicht der Fall, übernimmt der Shop keine Daten, legt keinen neuen Datensatz an und gibt einen Fehlercode zurück. Das betrifft auch die Vorbelegung: Soll bei einer Neuanlage eine Adresse vorbelegt werden, muss aus der Kombination von übergebenen und vorbelegten Werten eine gültige Adresse entstehen.

## Berechtigungen

Die Berechtigungen werden pro Konnektor festgelegt und müssen immer explizit gesetzt werden. Sie decken drei Bereiche ab.

**Neuanlage und Update eines Accounts.** Dazu gehören die Liste der zulässigen Domains für die E-Mail-Adresse des Kontos (die auch für Updates per UserIndex gilt), kundenabhängige Rabattsätze, Subshop-Berechtigungen und Hauptsubshop, die Kundennummer, Zahlungsarten, die SuperUserID, die Nutzung des Bestellgenerators, das Setzen eines neuen Passworts und die Änderung der E-Mail-Adresse.

**Rechnungsadressdaten**, mit Ausnahme von E-Mail-Adresse und Kundennummer. Hier gibt es eine generelle Berechtigung, Adressdaten überhaupt zu übergeben, und darunter eine Berechtigung auf Feldebene, entweder für einzeln benannte Felder oder für alle Felder über eine Wildcard.

**Datenabfrage.** Der Konnektor darf einen Login-Deeplink abfragen, über den ein Kunde mit automatischer Anmeldung in den Shop weitergeleitet wird.

Unabhängig von diesen Berechtigungen lassen sich Datenfelder festlegen, die bei Neuanlage oder Update automatisch gesetzt werden: der kundenabhängige Rabattsatz, Subshop-Berechtigungen und Hauptsubshop, Zahlungsarten, die Nutzung des Bestellgenerators sowie beliebige Werte pro Adressdatenfeld.

## Konfiguration

Die Konnektoren werden in der globalen Konfigurationsdatei `account-api-access.config.json` angelegt. Die Datei enthält ein JSON-Array, in dem jeder Zugang durch ein Zugangsobjekt beschrieben wird.

### Zugangsobjekt

| Feld | Wert | Pflicht | Beschreibung |
| - | - | - | - |
| `connectorid` | alphanumerischer String | x | Beliebige, aber eindeutige technische ID des Konnektors |
| `secret` | String | x | SharedSecret für das JWT |
| `description` | String | | Beschreibung des Konnektors |
| `permissions` | Berechtigungsobjekt | x | Berechtigungen und Einschränkungen des Konnektors |
| `data` | Datenaktualisierungsobjekt | | Regelsatz zum automatischen Setzen oder Aktualisieren von Kundendaten bei Aufrufen über diesen Konnektor |

### Berechtigungsobjekt

| Feld | Wert | Pflicht | Beschreibung |
| - | - | - | - |
| `accountrestrictions` | Objekt | x | Zugangsbeschränkungen |
| `accountrestrictions/createaccount` | Boolean | | Konnektor darf neue Accounts anlegen |
| `accountrestrictions/updateaccount` | Boolean | | Konnektor darf bestehende Accounts aktualisieren |
| `accountrestrictions/alloweddomains` | String-Array | x | Liste der erlaubten Domains der Account-E-Mail-Adresse, siehe unten |
| `accountdata` | Objekt | | Berechtigungen, welche Daten des Kundenkontos der Konnektor setzen darf |
| `accountdata/surchargelimit` | Boolean | | Kundenindividuelle Bemessungsgrenze für den Mindermengenzuschlag setzen |
| `accountdata/surcharge` | Boolean | | Kundenindividuellen Betrag des Mindermengenzuschlags setzen |
| `accountdata/userdiscount` | Boolean | | Kundenindividuellen Rabattsatz oder eine Rabattliste setzen |
| `accountdata/mainsubshop` | Boolean | | Hauptsubshop setzen |
| `accountdata/subshoplist` | Boolean | | Subshop-Zugangsberechtigungen setzen |
| `accountdata/customernumber` | Boolean | | Kundennummer setzen |
| `accountdata/allowedpayments` | Boolean | | Liste der erlaubten Zahlungsarten setzen |
| `accountdata/superuserid` | Boolean | | SuperUserID setzen |
| `accountdata/superuseridlist` | Boolean | | SuperUserIDList setzen |
| `accountdata/superuserrestricted` | Boolean | | Eingeschränkten SuperUser setzen |
| `accountdata/subvention` | Boolean | | Zuschussbetrag setzen |
| `accountdata/usergroup` | Boolean | | Kundengruppen setzen |
| `accountdata/ordergenerator` | Boolean | | Bestellgenerator erlauben |
| `accountdata/setpassword` | Boolean | | Neues Passwort setzen, verbunden mit der Zwangsänderung beim nächsten Login |
| `accountdata/changeemail` | Boolean | | E-Mail-Adresse ändern |
| `addressdata` | Objekt | | Berechtigungen, welche Felder der Rechnungsadresse der Konnektor setzen darf |
| `addressdata/transfer` | Boolean | | Konnektor darf generell Rechnungsadressdaten übergeben |
| `addressdata/ignorechecksoncreate` | Boolean | | Ignoriert alle Adresseingabeprüfungen, wenn ein neuer Account mit Rechnungsadressdaten angelegt wird |
| `addressdata/ignorechecksonupdate` | Boolean | | Ignoriert alle Adresseingabeprüfungen, wenn ein bestehender Account mit Rechnungsadressdaten aktualisiert wird |
| `addressdata/fields` | Objekt | | Berechtigung pro Feld oder Feldgruppe |
| `addressdata/fields/<id>` | Boolean | | Berechtigung auf Feldebene, siehe unten |
| `return` | Objekt | | Berechtigung, welche Daten der Konnektor abfragen darf |
| `return/loginlink` | Boolean | | Konnektor darf einen Deeplink mit automatischem Login zurückbekommen |
| `return/loginlinkvalidforseconds` | Integer | | Gültigkeit des Login-Links in Sekunden. Standard 300, Maximum 3600. |

> [!WARNING]
>
> Mit `ignorechecksoncreate` und `ignorechecksonupdate` können inkonsistente Datensätze entstehen, weil sämtliche Adressprüfungen übergangen werden. Setzen Sie die beiden Schalter nur, wenn Ihr vorgelagertes System die Adressen selbst zuverlässig prüft.

**Wildcards in `alloweddomains`.** Jeder durch einen Punkt getrennte Teil der Domain kann durch einen Stern ersetzt werden.

| Eintrag | Berechtigt für | Nicht berechtigt für |
| - | - | - |
| `domain.de` | `@domain.de` | `@sub.domain.de` |
| `*.domain.de` | `@domain.de`, `@sub.domain.de`, `@sub2.domain.de` | `@sub2.sub.domain.de` |
| `domain.*` | `@domain.de`, `@domain.at`, `@domain.xyz` | `@domain.domain2.de`, `@domain.co.uk` |
| `*` | alle Accounts | |

**Wildcards in `fields`.** Am Ende einer Feld-ID kann ein Stern stehen. `FirstName` berechtigt für den Vornamen, `Suffix*` für alle Suffixfelder und `*` für alle Felder. Der letzte Fall schließt auch kritische Felder mit ein.

### Datenaktualisierungsobjekt

Das Objekt `data` hat zwei gleich aufgebaute Zweige. `preset` belegt Daten bei der Neuanlage eines Kundenkontos vor, `overwrite` aktualisiert Daten bei Update oder Abfrage eines bestehenden Kontos. Beide enthalten jeweils ein `accountdata`- und ein `addressdata`-Objekt.

| Feld | Wert | Beschreibung |
| - | - | - |
| `accountdata/surchargelimit` | String | Kundenindividuelle Bemessungsgrenze für den Mindermengenzuschlag |
| `accountdata/surcharge` | String | Kundenindividueller Betrag des Mindermengenzuschlags |
| `accountdata/userdiscount` | String | Kundenindividueller Rabatt in Prozent |
| `accountdata/userdiscountlist` | String | Liste kundenindividueller und produktabhängiger Rabattsätze, aufgebaut wie in den Importdaten |
| `accountdata/mainsubshop` | String | HauptsubshopID des Kunden |
| `accountdata/subshoplist` | String | Kommaseparierte Liste der Subshop-Berechtigungen |
| `accountdata/allowedpayments` | String | Kommaseparierte Liste der zugewiesenen Zahlungsartencodes |
| `accountdata/ordergenerator` | Boolean | Berechtigung, den Bestellgenerator zu verwenden |
| `accountdata/usergroup` | String | Kommaseparierte Liste der Kundengruppenindizes |
| `addressdata/fields/<id>` | String | Wert des jeweiligen Adressdatenfelds |

Im `accountdata`-Objekt wird hier nur ein Teil der Felder unterstützt, die der Payload kennt. Die Adressdatenfelder entsprechen denen der Payload.

### Beispiel

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
[
  {
    "connectorid": "connectorA",
    "secret": "sharedSecret",
    "description": "Beispielkonnektor A: volle Berechtigung",
    "permissions": {
      "accountrestrictions": {
        "createaccount": true,
        "updateaccount": true,
        "alloweddomains": [ "*", "testshop.de", "testshop.*" ]
      },
      "accountdata": {
        "userdiscount": false,
        "mainsubshop": false,
        "subshoplist": false,
        "customernumber": false,
        "allowedpayments": false,
        "superuserid": false,
        "ordergenerator": false,
        "setpassword": false,
        "changeemail": false
      },
      "addressdata": {
        "transfer": true,
        "fields": {
          "id": true,
          "suffix*": true
        }
      },
      "return": {
        "loginlink": true
      }
    },
    "data": {
      "preset": {
        "accountdata": {
          "userdiscount": "5",
          "mainsubshop": "deutsch",
          "subshoplist": "deutsch,englisch",
          "allowedpayments": "5,6,7",
          "ordergenerator": true
        },
        "addressdata": {
          "fields": {
            "suffix11": "asdf",
            "suffix12": "wert"
          }
        }
      },
      "overwrite": {
        "accountdata": {
          "userdiscount": "5",
          "mainsubshop": "deutsch",
          "subshoplist": "deutsch,englisch",
          "allowedpayments": "5,6,7",
          "ordergenerator": true
        },
        "addressdata": {
          "fields": {
            "suffix12": "wert"
          }
        }
      }
    }
  },
  {
    "connectorid": "connectorB",
    "secret": "sharedSecret2",
    "description": "Beispielkonnektor B: nur Login bestehender Kunden von xyz.de, 3 Prozent Rabatt",
    "permissions": {
      "accountrestrictions": {
        "alloweddomains": [ "xyz.de" ]
      },
      "return": {
        "loginlink": true
      }
    },
    "data": {
      "overwrite": {
        "accountdata": {
          "userdiscount": "3"
        }
      }
    }
  }
]
```

## Der Aufruf

### Endpunkt und JSON-WebToken

Die REST-API wird mit einer POST-Anfrage an den Endpunkt `/_api/shop/Account` aufgerufen. Als POST-Daten wird ein JSON-WebToken mit der Payload übergeben.

Der Header verwendet den Signaturalgorithmus HS256 und den Typ JWT. Die Signatur entsteht aus

```
HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), <sharedSecret des Konnektors>)
```

Ein Beispiel mit der Payload `{ "hello": "world" }` und dem SharedSecret `geheim` ergibt dieses dekodierte Token:

```
{
  "alg": "HS256",
  "typ": "JWT"
}.{
  "hello": "world"
}.HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),geheim
)
```

Kodiert sieht dasselbe Token so aus und wird genau in dieser Form als POST-Daten übergeben:

```
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJoZWxsbyI6IndvcmxkIn0.S3cQ1a4_kqxaYdY3xlJ_I5pwQFx0_8iPva_WDd87zsg
```

### Payload

| Feld | Wert | Pflicht | Beschreibung |
| - | - | - | - |
| `iss` | String | x | ID des Konnektors |
| `exp` | NumericDate oder String | | Ablaufdatum |
| `email` | String | (x) | E-Mail-Adresse des Kundenkontos. Entweder `email` oder `userindex` muss angegeben werden. |
| `userindex` | String | (x) | UserIndex des Kundenkontos. Entweder `email` oder `userindex` muss angegeben werden. |
| `return` | Objekt | | Angabe der angefragten Informationen |
| `return/loginlink` | Boolean | | Deeplink für den automatischen Login anfragen |
| `data` | Objekt | | Zu setzende oder zu aktualisierende Daten des Kundenkontos |
| `data/accountdata/surchargelimit` | String | | Kundenindividuelle Bemessungsgrenze für den Mindermengenzuschlag |
| `data/accountdata/surcharge` | String | | Kundenindividueller Betrag des Mindermengenzuschlags |
| `data/accountdata/userdiscount` | String | | Kundenindividueller Rabatt in Prozent |
| `data/accountdata/userdiscountlist` | String | | Liste kundenindividueller und produktabhängiger Rabattsätze |
| `data/accountdata/mainsubshop` | String | | HauptsubshopID des Kunden |
| `data/accountdata/subshoplist` | String | | Kommaseparierte Liste der Subshop-Berechtigungen |
| `data/accountdata/allowedpayments` | String | | Kommaseparierte Liste der Zahlungsartencodes |
| `data/accountdata/customernumber` | String | | Kundennummer |
| `data/accountdata/superuserid` | String | | SuperUserID |
| `data/accountdata/superuseridlist` | String | | SuperUserIDList |
| `data/accountdata/superuserrestricted` | Boolean | | Eingeschränkter SuperUser |
| `data/accountdata/usergroup` | String | | Kommaseparierte Liste der Kundengruppenindizes |
| `data/accountdata/subvention` | String | | Zuschuss |
| `data/accountdata/ordergenerator` | Boolean | | Berechtigung zur Verwendung des Bestellgenerators |
| `data/accountdata/setpassword` | String | | Neues Passwort. Die Zwangsänderung beim nächsten Login wird dabei automatisch mitgesetzt. |
| `data/accountdata/changeemail` | String | | Neue E-Mail-Adresse |
| `data/addressdata/fields/<id>` | String | | Wert des jeweiligen Adressdatenfelds |
| `data/addressdata/fields/TitleCode` | String | | Title-Code wie in `title.dat` definiert. Das technische Feld `Title` wird nicht unterstützt. |
| `data/addressdata/fields/SalutationCode` | String | | Salutation-Code wie in `salutation.dat` definiert. Das technische Feld `Salutation` wird nicht unterstützt. |
| `data/addressdata/fields/CountryCode` | String | | Country-Code wie in `country.dat` definiert. Das technische Feld `Country` wird nicht unterstützt. |

Das folgende Beispiel aktualisiert das Kundenkonto mit der E-Mail-Adresse `test@domain.de`, setzt 5 Prozent Kundenrabatt und das Feld `Suffix12` der Rechnungsadresse auf `conA` und fordert den Login-Link an:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "iss": "connectorA",
  "email": "test@domain.de",
  "return": {
    "loginlink": true
  },
  "data": {
    "addressdata": {
      "fields": {
        "Suffix12": "conA"
      }
    },
    "accountdata": {
      "userdiscount": "5"
    }
  }
}
```

### Antwort

Im Erfolgsfall antwortet die Schnittstelle mit dem HTTP-Statuscode 200 und einem JSON-Objekt, das einen Code und optional ein `return`-Objekt mit den angefragten Daten enthält.

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "code": "100",
  "return": {
    "loginlink": "https://...",
    "accountkey": "33221-1578774551-a665a45920422f9d417e4867efdc4fb8a04a1f3fff1f....."
  }
}
```

| Feld | Wert | Pflicht | Beschreibung |
| - | - | - | - |
| `code` | String | x | Statuscode der Anfrage |
| `return` | Objekt | | Rückgabe der angefragten Informationen |
| `return/loginlink` | String | | Zeitlich begrenzter Deeplink für den automatischen Login |
| `return/accountkey` | String | | Zeitlich begrenzter Loginparameter für den automatischen Login. Er kann jedem beliebigen Shop-Deeplink als Parameter `accountkey` mitgegeben werden. |
| `return/UserIndex` | String | x | UserIndex des betroffenen Kundenkontos. Wird bei erfolgreichen Anfragen immer zurückgegeben. |

Im Fehlerfall antwortet die Schnittstelle, soweit zutreffend, mit den HTTP-Statuscodes 401 oder 403, ansonsten mit 400. Zusätzlich kommt ein JSON-Objekt mit Fehlercode und gegebenenfalls einer Fehlermeldung zurück.

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "ErrCode": "123",
  "ErrMsg": "Description"
}
```

## Verwandte Themen

* [WS-SFTP-Kunden-Pro](https://dokumentation.websale.de/v8s/schnittstellen/kundendaten/ws-sftp-kunden-pro.md)
* [WS-Adressdatenänderungen](https://dokumentation.websale.de/v8s/schnittstellen/kundendaten/ws-adressdatenaenderungen.md)


## Related topics

- [Kundendaten](https://dokumentation.websale.de/v8s/schnittstellen/kundendaten.md)
- [Schnittstellen](https://dokumentation.websale.de/v8s/schnittstellen.md)
- [Account](https://dokumentation.websale.de/frontend/referenz/aktionen/account.md)
- [accounts - Benutzerkonten](https://dokumentation.websale.de/konfiguration/accounts-benutzerkonten.md)
- [Storefront API Kundenkonto](https://dokumentation.websale.de/schnittstellen/storefront-api/storefront-api-kundenkonto.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.