Klicke hier, um ein unverbindliches Erstgespräch zu buchen!

Veröffentlicht von Markus Wals

Mehr API, als die Doku zeigt: inoffizielle weclapp-Endpunkte sicher nutzen

API Filter Integration OpenAPI Praxiswissen weclapp

Mehr API, als die Doku zeigt: inoffizielle weclapp-Endpunkte sicher nutzen

Du willst 400 Kundendatensätze anhand einer Liste von Kundennummern abgleichen. Mit GET packst du alle 400 Nummern in einen Filter, und plötzlich ist die URL länger als das, was Proxy und Server annehmen. Die übliche Lösung ist, die Liste in kleine Pakete zu zerlegen und viele Requests zu schicken. Es geht auch eleganter: mit einem Endpunkt, den die weclapp-Doku im Text empfiehlt, der in der öffentlichen Pfadliste aber fehlt.

Er ist nicht der einzige. Die öffentliche Spec ist die Grundlage jeder Integration, aber sie ist nicht die ganze API. In diesem Artikel zeigen wir dir, wie du herausfindest, was dein Mandant zusätzlich kann, welcher dieser Endpunkte im Alltag am meisten bringt und nach welchen Regeln du ihn einsetzt, damit deine Integration nicht an etwas hängt, das sich ohne Vorwarnung ändern kann.

Alle Beispiele nutzen die Basis-URL https://<dein-mandant>.weclapp.com/webapp/api/v2/ und den Header AuthenticationToken: <dein-token>. Probiere sie zuerst auf einem Testsystem aus, nie direkt auf deinem Produktivmandanten.

Mehr API, als die Pfadliste zeigt

Die öffentliche v2-Spec auf weclapp.com listet 712 Pfade. Rufst du die Spec stattdessen an einem Mandanten ab, mit dem Parameter includeHidden=true, sind es deutlich mehr: An unseren beiden Testmandanten waren es 1.013 und 1.020 Pfade. Rund 300 Pfade, die in keiner öffentlichen Liste stehen.

Was heißt das für dich? Diese Endpunkte funktionieren, aber sie haben keinen Vertrag. Schon für die offizielle API behält sich weclapp in der Change Policy vor, Ressourcen ohne Vorankündigung zu ändern. Für Endpunkte, die nicht einmal im Katalog stehen, solltest du damit erst recht rechnen. Dazu kommt: Ein Mandant zeigt nur die Endpunkte seiner Lizenz. Was bei dir fehlt, kann es bei einem Kunden mit anderem Modulumfang geben, und umgekehrt.

Für dich heißt das: Inoffizielle Endpunkte sind kein Tabu, aber jede Nutzung ist eine bewusste Entscheidung mit eingebautem Plan B.

Grafik: Mehr API, als die Pfadliste zeigt. Die öffentliche weclapp-Spec v2 hat 712 Pfade, zwei Testmandanten mit includeHidden=true haben 1.013 und 1.020 Pfade, also 301 und 308 mehr.

So findest du heraus, was dein Mandant kann

Die Spec deines Mandanten lädst du direkt an deinem Mandanten-Endpunkt herunter. Den Pfad meta/openapi.yaml nennt die weclapp-Doku selbst, der Parameter includeHidden=true liefert die vollständige Fassung. Mit zwei Downloads und ein paar Zeilen Python siehst du, welche Operationen dein Mandant zusätzlich kennt:

curl -s --compressed -H "AuthenticationToken: <dein-token>" \
  "https://<dein-mandant>.weclapp.com/webapp/api/v2/meta/openapi.yaml?includeHidden=true" -o tenant.yaml
curl -s --compressed https://www.weclapp.com/api/openapi_v2.yaml -o public.yaml

pip install pyyaml
python3 - <<'EOF'
import yaml
def ops(f):
    spec = yaml.safe_load(open(f))
    return {(m.upper(), p) for p, item in spec["paths"].items()
            for m, o in item.items() if isinstance(o, dict) and "responses" in o}
for method, path in sorted(ops("tenant.yaml") - ops("public.yaml")):
    print(method, path)
EOF

Die Liste, die dabei herauskommt, ist mehr als eine Kuriosität. Lass das Skript regelmäßig laufen, zum Beispiel einmal pro Woche, und vergleiche das Ergebnis mit dem letzten Lauf. Verschwindet ein Endpunkt, den du nutzt, siehst du es im Diff und nicht erst, wenn ein Kunde anruft.

Für dich heißt das: Du hast in fünf Minuten ein Inventar und ein Frühwarnsystem in einem.

Der nützlichste Fund: Filter im Body mit POST /query

Den größten Block in dieser Liste bilden zwei Operationen, die es für jede Entity gibt: POST /{entity}/query und POST /{entity}/count, in unserer Spec je 183 Mal. Das Spannende daran: Sie sind kein Geheimnis. Die weclapp-Doku beschreibt im Abschnitt „Querying“ ausdrücklich POST /party/query und empfiehlt für POST-Abfragen Filter Expressions im Request-Body, weil POST weniger Einschränkungen hat als GET. Nur in der Pfadliste der öffentlichen Spec tauchen sie nicht auf.

Damit löst sich das Problem vom Anfang. Die lange Liste wandert aus der URL in den Body:

POST https://<dein-mandant>.weclapp.com/webapp/api/v2/party/query
AuthenticationToken: <dein-token>
Content-Type: application/json

{
  "filter": "customerNumber in [\"10004\", \"10005\", \"10006\"]",
  "pageSize": 1000
}

Die Antwort hat dieselbe Form wie bei GET /party, ein Objekt mit result. Brauchst du nur die Anzahl, nimmst du POST /party/count mit demselben Filter.

Zwei Unterschiede zu GET solltest du kennen. Erstens kennt der Body keine Einzelfilter wie customerNumber-in, sondern nur das Feld filter mit einer Filter Expression. Die Doku kennzeichnet Filter Expressions noch als Beta. Zweitens heißen einige Felder anders: Laut Schema gibt es neben filter, page, pageSize und offset auch properties, includeReferencedEntities, additionalProperties und orderBy, jeweils als Liste von Strings. Wie bei GET gilt: Mehr als 1.000 Einträge pro Seite liefert weclapp in der Regel nicht.

Für dich heißt das: Abgleiche gegen lange ID- oder Nummernlisten brauchen einen Request statt vieler, und deine URLs bleiben kurz und lesbar.

Grafik: Lange Filter gehören in den Body. GET /party mit customerNumber-in in der URL führt zu langen URLs und vielen Requests, POST /party/query mit Filter Expression im Body braucht einen Request und liefert dieselbe Antwort.

So setzt du inoffizielle Endpunkte sicher ein

Ein Endpunkt ohne Vertrag ist dann unproblematisch, wenn dein Code auch ohne ihn weiterläuft. Für POST /query ist das einfach, denn der offizielle Weg existiert: GET mit id-in, in Paketen, damit die URL kurz bleibt. Der Code versucht zuerst den POST, und erst wenn weclapp mit 404 oder 405 antwortet, schaltet er um und meldet das:

// unofficial: POST /party/query, weclapp kann ihn ohne Ankündigung ändern.
// Fallback: GET /party mit id-in in Paketen zu 100 IDs.
async function queryParties(ids) {
  const filter = `id in [${ids.map((id) => `"${id}"`).join(",")}]`;
  try {
    return await post("/party/query", { filter, pageSize: 1000 });
  } catch (err) {
    if (![404, 405].includes(err.status)) throw err;
    console.warn("POST /party/query nicht verfügbar, Fallback auf GET");
    const result = [];
    for (let i = 0; i < ids.length; i += 100) {
      const chunk = ids.slice(i, i + 100);
      const page = await get(`/party?id-in=${encodeURIComponent(JSON.stringify(chunk))}&pageSize=100`);
      result.push(...page.result);
    }
    return { result };
  }
}

Die Funktion ist für bis zu 1.000 IDs ausgelegt. Hast du mehr, teilst du die Liste vorher auf.

Aus unserem Integrationsalltag haben sich dazu ein paar Regeln bewährt. Jeder inoffizielle Endpunkt im Code bekommt einen Kommentar wie oben, damit auch Kolleg:innen in einem Jahr wissen, worauf sie sich verlassen. Der wöchentliche Spec-Diff zeigt dir, ob die Endpunkte noch da sind. Lesende Endpunkte wie /query sind ein überschaubares Risiko. Schreibende inoffizielle Endpunkte gehören nur mit Vorschau, Freigabe und anschließender Kontrolle in eine Integration und nie in einen Auftragsfluss, der ohne sie stillsteht. Und weil jeder Mandant nur die Endpunkte seiner Lizenz zeigt, prüfst du beim Rollout zu einem neuen Kunden, ob der Endpunkt dort überhaupt existiert.

Für dich heißt das: Du bekommst den Komfort der zusätzlichen Endpunkte, ohne dass deine Integration an ihnen hängt.

Grafik: Inoffiziell nutzen, offiziell absichern. Drei Schritte: zuerst POST /query mit allen IDs, bei 404 oder 405 schaltet der Code um und meldet es, dann der offizielle Weg GET mit id-in in Paketen zu 100 IDs.

Was sonst noch in der Liste steht

Dein Spec-Diff wird mehr zeigen als /query. Darunter sind lesende Positions-Entities wie salesOrderItem, eine Änderungshistorie über auditing/history, Projekt- und Aufgabenverwaltung, ein Schlüssel-Wert-Speicher (appSettings) und asynchrone Massenoperationen zum Ändern und Löschen. Gerade die letzten beiden schreiben in deinen Mandanten, und für Massenlöschungen kennt die Spec keinen Probelauf. Solche Endpunkte testest du ausschließlich auf einem Testsystem und mit den Regeln von oben.

Checkliste

  • Spec deines Mandanten mit includeHidden=true abgerufen und mit der öffentlichen verglichen
  • Genutzte inoffizielle Endpunkte im Code kommentiert
  • Offizieller Fallback je inoffiziellem Endpunkt vorhanden
  • Spec-Diff läuft regelmäßig
  • Schreibende inoffizielle Aufrufe nur mit Vorschau, Freigabe und Kontrolle
  • Beim Rollout zu einem neuen Kunden Verfügbarkeit geprüft

Weiterlesen und Werkzeuge

Die offiziellen Endpunkte probierst du am schnellsten mit unserer kostenlosen Postman Collection 4 weclapp aus. Die inoffiziellen Requests aus diesem Artikel legst du dort als eigene Requests an, Mandant und Token setzt du einmal als Variablen. Wie du große Datenmengen gezielt und paketweise liest, zeigt Teil 2 der Serie (Gezielt lesen). Die Grundlagen zu Filtern und Projektion erklärt das YouTube-Webinar „weclapp API Deep Dive“.

Du willst wissen, wie robust deine Integrationen gegenüber Änderungen an der weclapp-API sind? Lass uns draufschauen: wals.pro/termin.