> ## 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.

# SFTP-REST-to-Shop

> Produkt-, Kunden- und Gutscheindaten per SFTP auf den Shop-Server übertragen und den Import anschließend über die REST-Schnittstelle starten und überwachen.

SFTP-REST-to-Shop importiert Produkte und Kategorien, Kundendaten und Gutscheindaten in den Shop. Der Ablauf besteht immer aus zwei Schritten: Zuerst landen die Importdateien per SFTP auf dem Shop-Server, dann stoßen Sie den Import über einen REST-Aufruf an und fragen seinen Fortschritt ab.

| Eigenschaft | Wert |
| - | - |
| Übertragungsrichtung | Warenwirtschaft → WEBSALE Shop (Data-to-Shop) |
| Übertragungsart | SFTP, REST |
| Dateiformate | CSV, JSON |

## Dateien per SFTP übertragen

Für Produkt-, Kunden- und Gutscheindaten erhalten Sie von der WEBSALE AG einen gemeinsamen SFTP-Account. Je Datenart gibt es ein eigenes Zielverzeichnis. Existiert das Verzeichnis nicht, legen Sie es an.

| Datenart | Verzeichnis | Wert für `scope` | Format und Inhalt |
| - | - | - | - |
| Produkte und Kategorien | `directimport` | `products` | [WS-SFTP-Produkte PRO](https://dokumentation.websale.de/v8s/schnittstellen/produkte-und-kategorien/ws-sftp-produkte-pro.md) |
| Kundendaten | `customerimport` | `customers` | [WS-SFTP-Kunden PRO](https://dokumentation.websale.de/v8s/schnittstellen/kundendaten/ws-sftp-kunden-pro.md) |
| Gutscheindaten | `voucherimport` | `vouchers` | [WS-SFTP-Gutscheindaten (to-Shop)](https://dokumentation.websale.de/v8s/schnittstellen/marketing-seo-und-portale/ws-sftp-gutscheindaten-to-shop.md) |

### Produktdaten: Unterverzeichnis je Subshop

Produktdateien liegen nicht direkt in `directimport`, sondern in einem Unterverzeichnis je SubShopID. Bei der SubShopID `Deutsch` lautet der Pfad also `directimport/Deutsch`.

Eine PRD-Datei `100721.prd` im Verzeichnis `Deutsch_184.prd` dieses Subshops erreichen Sie entsprechend unter:

```
../directimport/Deutsch/Deutsch_184.prd/100721.prd
```

Bevor Produkt- oder Kategoriedaten importiert werden können, müssen die benötigten Subshops und freien Felder mit dem WSPManager angelegt sein. Das wird beim ersten Importversuch am häufigsten übersehen.

## Authentifizierung

Jeder Aufruf der API wird über ein Web Token im HTTP-Header authentifiziert. Das Token holen Sie sich zuerst über einen Login-Aufruf.

**POST** `https://www.websale.de/api/authent/login/<Shop-ID>`

Request-Body mit Login-ID und Passwort als JSON-Objekt:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "username": "websaleuser",
    "password": "meinpasswort"
}
```

Im Erfolgsfall antwortet der Server mit dem Token:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
    "token": "TOKEN"
}
```

Dieses Token schicken Sie bei allen folgenden Aufrufen im HTTP-Header mit:

```
X-Authorization: Bearer TOKEN
```

Das Token ist 30 Minuten gültig. Danach beantwortet die API jede Anfrage mit dem Statuscode 401 und Sie müssen ein neues Token erzeugen. Planen Sie das in Ihrer Anbindung ein, denn ein langer Import kann die Gültigkeit überdauern.

## Import starten

**POST** `https://www.websale.de/api/import/start`

Der Body enthält als JSON-Objekt den Parameter `scope`:

| Name | Beschreibung | Pflichtfeld |
| - | - | - |
| `scope` | Welche Daten importiert werden sollen. Mögliche Werte sind `products`, `customers` und `vouchers`. Es lässt sich jeweils nur einer dieser Werte angeben. | ja |

Beispiel-Request:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "scope": "products"
}
```

Beispiel-Antwort:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "importid": 1523880633
}
```

Die zurückgegebene Import-ID brauchen Sie für die Statusabfrage.

Ein erfolgreich gestarteter Import bedeutet nicht, dass Daten erfolgreich importiert wurden. Der Start erfolgt asynchron, die REST-Funktion kehrt also zurück, bevor der Import beendet ist. Ob die Daten verarbeitet werden konnten, steht zu diesem Zeitpunkt noch nicht fest.

## Import-Status abfragen

**GET** `https://www.websale.de/api/import/status/<Import-ID>`

Im Erfolgsfall stehen die Statusinformationen als JSON-Objekt im Body der Antwort.

Diese Felder kommen immer zurück:

| Name | Wert |
| - | - |
| `state` | `0`: Import läuft. `1`: Import aufgrund eines Ausnahmefehlers abgebrochen. `2`: Import beendet, eventuell mit Fehlern oder Warnungen. |
| `progress` | Fortschritt des Imports in Prozent als ganze Zahl, beispielsweise `42` |

Diese Felder kommen erst zurück, wenn der Import beendet ist:

| Name | Wert |
| - | - |
| `errorcount` | Anzahl der minder schweren Fehler, beispielsweise `123` |
| `warncount` | Anzahl der Warnungen, beispielsweise `328` |
| `errors` | Array mit den aufgetretenen Fehlern |
| `warnings` | Array mit den aufgetretenen Warnungen |
| `addedcustomers` | Array mit Userindizes, Kundennummern und E-Mail-Adressen der beim Import angelegten Kunden |

Beispiel einer Antwort ohne Importdaten:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "errorcount": 1,
  "errors": [
      "Keine Importdaten vorhanden"
  ],
  "progress": 0,
  "state": 2,
  "warncount": 0,
  "warnings": []
}
```

Beispiel eines abgebrochenen Kundendatenimports:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "errorcount": 2,
  "errors": [
      "EC001: Weder 'UserIndex' noch 'CustomerID' vorhanden (Datei: 'billcomplete.csv')",
      "Kundendatenimport abgebrochen"
  ],
  "progress": 0,
  "state": 2,
  "warncount": 0,
  "warnings": []
}
```

## Fehler, Warnungen und Statuscodes

### Was Fehler von Warnungen unterscheidet

Schwere Fehler lassen keine andere Wahl, als den Import abzubrechen oder gar nicht erst zu starten. Das ist beispielsweise der Fall, wenn in einer Produkt-Importdatei die Spalte mit dem Pflichtfeld `ProdIndex` komplett fehlt.

Minder schwere Fehler führen dazu, dass einzelne Datensätze nicht importiert werden. Das passiert beispielsweise, wenn die Spalte `ProdIndex` zwar vorhanden ist, aber für einzelne Produkte leer bleibt. Man könnte auch hier abbrechen, denn das Ergebnis entspricht offensichtlich nicht der Absicht. Die Erfahrung zeigt jedoch, dass den meisten Betreibern ein durchlaufender Import wichtiger ist als ein vollständiger.

Warnungen treten auf, wenn Importdaten nicht der Spezifikation entsprechen, der Import sie aber mit hoher Wahrscheinlichkeit richtig interpretiert hat. Beispiel: Als Produktpreis kommt `0,99` an. Das entspricht nicht der Spezifikation, weil als Dezimaltrenner ein Komma statt eines Punktes steht. Der Import ersetzt das Komma durch einen Punkt und schreibt eine Warnung.

### Fehler bei der Authentifizierung

| Status-Code | Status-Text | Beschreibung |
| - | - | - |
| 400 | Bad Request | Übergabe nicht korrekt, also Formatierungsfehler oder fehlende Felder, oder unbekannte Aktion |
| 401 | Unauthorized | Der Benutzer hat keine Berechtigung für die angegebene ShopID |
| 403 | Forbidden | Unbekannte oder falsche Login-Daten |
| 423 | Locked | Der Benutzer wurde wegen mehrfach fehlerhafter Logins zeitweise gesperrt |

### Fehler beim Starten des Imports oder bei der Statusabfrage

| Status-Code | Status-Text | Beschreibung |
| - | - | - |
| 401 | Unauthorized | Kein Token im Header `X-Authorization` gesendet, Token ungültig oder abgelaufen |
| 404 | Not Found | Für die angegebene Status-ID existiert kein Import |
| 503 | Service Unavailable | Die Funktion steht derzeit nicht zur Verfügung. Versuchen Sie es später erneut oder wenden Sie sich an den Support der WEBSALE AG. |

Zusätzlich zum Statuscode kann im Body ein JSON-Objekt mit weiteren Informationen stehen:

```json theme={"theme":{"light":"github-light","dark":"github-dark"},"languages":{"custom":["/languages/websale.json"]}}
{
  "error": "invalidParams",
  "detail": "Invalid parameters sent",
  "paramErrors": {
        "scope": [
            {
                "kind": "invalidValue"
            }
        ]
  }
}
```

`error` enthält einen Fehler-Code für die Auswertung durch das aufrufende Programm. Zu einem HTTP-Statuscode kann es mehrere Fehler-Codes geben. `detail` enthält eine ausführlichere Meldung für den menschlichen Leser.

`paramErrors` wird nur beim Fehler `invalidParams` zurückgegeben. Jedes Feld darin entspricht einem ungültigen Parameter. Weil es je Parameter mehrere Fehler geben kann, ist der Wert ein Array. Jeder Eintrag hat mindestens das Feld `kind`, das die Art des Fehlers angibt, und je nach `kind` weitere Felder.

### Fehler, die die Statusabfrage zurückgibt

| Fehlermeldung | Beschreibung |
| - | - |
| `EI001 Keine Importdaten vorhanden` | Auf dem Shop-Server liegen keine Importdaten. |
| `EI002 Import läuft bereits` | Für den Shop läuft bereits ein Importprozess. |
| `EI003 Ein anderer Prozess greift bereits auf die Shopdaten zu` | Ein anderer Prozess liest oder schreibt bereits Produktdaten. Um Inkonsistenzen zu vermeiden, startet kein Import. Auslöser können sein: Export durch die PricePush Feed Engine, Datenübertragung durch den WSPManager, Aktualisierung von Glossardaten. |
| `EI004 Artikelimport Pro nicht freigeschaltet` | Für den Shop ist der Artikelimport Pro nicht freigeschaltet. |
| `EI005 Ungültige Shop Version` | Der Import ist freigeschaltet, aber die aufgerufene Schnittstelle passt nicht zur Version des Shops. |
| `EI006 Kundendatenübertragung nicht freigeschaltet` | Der Import ist freigeschaltet, aber die Übertragung von Kundendaten ist nicht eingerichtet. |
| `EI007 Interner Fehler` | Der Import wurde wegen eines Ausnahmefehlers abgebrochen. Versuchen Sie es später erneut oder wenden Sie sich an die WEBSALE AG. |

Beim Kundendatenimport kommen diese Meldungen hinzu:

| Fehlermeldung | Beschreibung |
| - | - |
| `EC001` | Weder `UserIndex` noch `CustomerID` vorhanden |
| `EC002` | Weder `TableIndex` noch `ExternalID` vorhanden |
| `EC003` | Sowohl `CustomerID` als auch `UserIndex` sind leer |
| `EC004` | Sowohl `ExternalID` als auch `TableIndex` sind leer |
| `EC005` | `CustomerID` und `UserIndex` leer oder nicht in der Datenbank vorhanden |
| `EC006` | Der angegebene `TableIndex` ist bereits vergeben |
| `EC007` | Datensatz ohne E-Mail-Adresse |
| `EC008` | E-Mail-Adresse wird bereits verwendet |
| `EC009` | `CustomerID` wird bereits verwendet |
| `EC010` | `CharsetImport` ohne `CharsetShop` wird ignoriert |
| `EC011` | `CharsetShop` ohne `CharsetImport` wird ignoriert |
| `EC012` | Datensatz konnte nicht fehlerfrei in den Zielzeichensatz konvertiert werden |
| `EC013` | Ungültiger Zeichensatz |
| `EC014` | Es sind sowohl verschlüsselte als auch per SFTP übertragene Daten vorhanden |
| `EC015` | Feld `UserIndex` nicht vorhanden |
| `EC016` | Der angegebene `UserIndex` existiert nicht |
| `EC017` | `TableIndex` wurde ersetzt |
| `EC018` | Mehr als eine Rechnungsadresse vorhanden |
| `EC019` | In der Datei fehlt ein Pflichtfeld |
| `EC020` | Ein Pflichtfeld ist leer |
| `EC021` | Ungültiger Datentyp in einem Feld |

## Import aus mehreren Systemen

Es ist möglich, Produktdaten aus einem System und Kundendaten aus einem anderen zu importieren. Dabei müssen Sie allerdings selbst sicherstellen, dass Übertragung und Import nicht gleichzeitig laufen. Jeder Versuch, einen Import zu starten, während bereits einer läuft, endet mit `EI002 Import läuft bereits`.

Kritischer als der Start ist die Übertragung. Sie läuft über SFTP, und die Importverzeichnisse sind nicht nach Quellsystem getrennt. Daraus folgen zwei Risiken: Eine gleichzeitige Übertragung aus mehreren Systemen kann die Import-Software nicht verhindern, und ein System kann den Import von Daten starten, die ein anderes System übertragen hat. Wenn Sie mehrere Quellsysteme anbinden, müssen Sie die Reihenfolge außerhalb des Shops koordinieren.

## Basis-URL

Die derzeitige Basis-URL der REST-Schnittstelle für den Import lautet:

```
https://www.websale.de/api/...
```

Die URL kann sich künftig ändern. Hinterlegen Sie sie in Ihrer Anbindung so, dass sie sich ohne größeren Aufwand anpassen lässt.

## Verwandte Themen

* Wegweiser: [Übertragung: Trigger für Import und Export](https://dokumentation.websale.de/v8s/schnittstellen/uebertragung.md)
* Wegweiser: [SFTP-SOAP-to-Shop](https://dokumentation.websale.de/v8s/schnittstellen/uebertragung/sftp-soap-to-shop.md)
* Wegweiser: [WS-SFTP-Produkte PRO](https://dokumentation.websale.de/v8s/schnittstellen/produkte-und-kategorien/ws-sftp-produkte-pro.md)


## Related topics

- [SFTP-SOAP-to-Shop](https://dokumentation.websale.de/v8s/schnittstellen/uebertragung/sftp-soap-to-shop.md)
- [WS-SFTP-Kunden PRO](https://dokumentation.websale.de/v8s/schnittstellen/kundendaten/ws-sftp-kunden-pro.md)
- [WS-SFTP-Gutscheindaten (to-Shop)](https://dokumentation.websale.de/v8s/schnittstellen/marketing-seo-und-portale/ws-sftp-gutscheindaten-to-shop.md)
- [WSPManager-to-Shop](https://dokumentation.websale.de/v8s/schnittstellen/uebertragung/wspmanager-to-shop.md)
- [Übertragung: Trigger für Import und Export](https://dokumentation.websale.de/v8s/schnittstellen/uebertragung.md)


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