Für Entwickler

Ihre Software, in jedem SIDES-Restaurant

SIDES LABS ist die API der Plattform, auf der Gastronomiebetriebe ihre Bestellungen, Zahlungen und ihr Backoffice führen. Bauen Sie dagegen, listen Sie das Gebaute im Marktplatz, und SIDES-Kunden installieren es.

POST /v1/oauth/token die erste Anfrage
curl -X POST https://api.sideslabs.com/v1/oauth/token \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=password' \
  --data-urlencode "username=$CLIENT_ID" \
  --data-urlencode "password=$CLIENT_SECRET" \
  --data-urlencode 'scope=marketplace.apps'

{ "access_token": "eyJhbGciOi...",
  "token_type": "Bearer",
  "expires_in": 900,
  "scope": "marketplace.apps" }

Die Oberfläche

Was die API abdeckt

Das sind die Gruppen und die Zählungen des Vertrags selbst, gelesen aus GET /v1/publication/public/api-reference — demselben Dokument, gegen das der Server seinen Router beim Start prüft. Diese Seite führt keine eigene Endpunktliste, es gibt hier also nichts, was veralten könnte.

Der Vertrag dokumentiert 388 Operationen, in Version 1.0.0.

system

5 Operationen

Health, readiness, the contract itself, and the identity of the calling principal. None of these carry business data.

auth

31 Operationen

Both authentication planes. Machine clients exchange configured credentials at /v1/oauth/token (plane 1); partner users register, sign in, rotate and sign out under /v1/auth (plane 2).

The two issue the same kind of access token and are checked by the same middleware, and they identify different things: a client id names a program an operator provisioned, a subject names a person. A partner user's scopes are derived from their role and their tier and are never requested; a machine client may down-scope its own token, because it is a program with a purpose.

publication

25 Operationen

Everything SIDES publishes to partner developers: the API changelog, the developer blog, and the developer-resources area with the API reference and its downloadable artefacts.

The changelog is part of the API contract, not marketing. Every release writes an entry through this API, which is what keeps our own release notes and the public changelog one thing rather than two that drift.

Nothing here reaches a reader without an explicit, recorded transition under labs.admin.publication:write — one editorial capability over all three, not three. Developer resources carry a second, orthogonal question besides: audience decides whether a released resource is for the open internet or for authenticated partners, and the anonymous surfaces gate on both.

subscription

26 Operationen

Partner tiers and what they grant: the public catalogue the pricing page and the registration form render, and the resolved entitlements of one business partner.

A tier is data, not code — a new tier is a row set — and the subscription row, never the payment provider, is what decides access.

marketplace

81 Operationen

The marketplace: the apps a partner offers with their version history, and the category tree those apps are sorted into.

Categories are SIDES-internal to write and public to read — two access classes over one set of rows, and a third in between: an internal READ that sees the deactivated categories the public endpoint never returns. A partner chooses a category and cannot invent one, which is a fact about the scope tree rather than a check in a handler: every category write sits under labs.admin, and a principal bound to a business partner can never reach that subtree.

Apps are the other way round: partner-scoped throughout, under marketplace.apps. The partner appears in no path and in no body — it comes from the token — so a request naming somebody else's app is not refused, it is unrepresentable.

The storefront is here, and it is a different set of paths. Everything under /v1/marketplace/public/ — the catalogue, one listing, its media and the category tree — carries the storefront scope rather than an owner's, and shows only what an explicit, recorded transition has put there. Everything else in this tag answers for one owner. The two never share a shape.

partner

45 Operationen

A business partner's own record: its team, the invitations it has sent, and later its profile and imagery.

Every path here carries the partner's uuid, and every one of them COMPARES it against the token rather than selecting by it. The business partner a query sees comes from the authenticated principal; a uuid naming somebody else is 403, which is what makes reaching into another partner's team unrepresentable rather than merely forbidden.

statistics

6 Operationen

How many SIDES customers use a partner's apps, and the state of the import that answers that question.

The numbers are a CACHE with a ledger beside it, and the ledger is what makes the cache honest. Platform usage is read through the SIDES API and never by querying the platform's own schema, so what SIDES LABS holds is a rollup of what that API last said. Every endpoint here therefore answers when it last said it: GET /v1/statistics/import-status is that answer on its own, and the partner-facing reads carry the same freshness from the same computation.

Which SIDES API, at which granularity, and whether it is pulled or pushed is an OPEN question. The assumption in force is a scheduled pull of completed days into a rollup, and the default configuration imports nothing at all and says so — source: DISABLED — because a platform with no statistics is supportable and one with invented statistics is not.

Both endpoints in this tag are SIDES-internal. They are about the JOB; a partner's own numbers are a different access class over the same rows.

admin

125 Operationen

SIDES-internal administration across every partner: the business partners themselves, and the platform overview an administrator opens on.

Everything in this tag is a cross-partner read or write, and every operation in it is audited — reads included. That is what the tag IS: each operation writes one audit_log record, in the same transaction as the answer, and an answer whose record cannot be written is refused rather than given untraced.

/v1/admin/… is not /v1/partner/… with a wider filter. Every path in the partner tag carries a partner uuid and COMPARES it against the token; nothing there can name a partner the caller is not. The uuid in these paths ADDRESSES any partner on the platform. They are two collections for two audiences, and no query parameter widens one into the other — a single endpoint serving both is a shape this platform does not build.

The other SIDES-internal surfaces are not in this tag and that is deliberate: tier administration, category maintenance, app approval, review moderation and the support desk each live beside the partner-facing operations over the same rows, where a reader compares the two. What is here is what has no partner-facing twin.

engagement

44 Operationen

The community surfaces: the feature-request board partners propose on and vote on, and the comments under it.

The board is read across every partner, and that is its design rather than a leak. A board on which each company saw only its own wishes cannot be voted on, and voting is the feature. What makes it safe is the shape of the answer, not a filter: every entry names the proposing COMPANY and names the person only on that person's own opt-in, and no endpoint here says who voted — only how many did, and whether the caller is one of them.

Nothing on this board is public. Every path requires a token and there is no …/public/… route in this tag. A state called SHIPPED is SIDES answering a partner, not a publication state.

Two access classes: a partner proposes, votes and comments under engagement.feature-requests; SIDES changes a status, merges duplicates, pins, suspends and moderates under labs.admin.engagement. The second is inside the SIDES-internal tree, which is what makes "a partner cannot change a status" a fact about the authorization model rather than a check in a handler.

A proposal is not moderated on the way in and can be taken off the board afterwards. Its title and body reach every other partner the moment it is written, deliberately — and :suspend is the way back, the only operation here that removes a partner's words.

Die vollständige Referenz steht im Partnerportal. Jede Operation mit ihren Parametern, ihren Antworten und dem Scope, den sie verlangt, steht in der API-Referenz, und das OpenAPI-Dokument selbst ebenso. Die Registrierung öffnet beides, und sie ist ein Schritt: Sie legt Ihren Geschäftspartner, Ihren ersten Administrator und Ihr Abonnement zusammen an.

Anmeldung

Zwei Ebenen, eine Art Token

Ein Maschinenclient und ein Partnernutzer melden sich unterschiedlich an und landen bei derselben Art Zugriffstoken, geprüft von derselben Middleware. Welche Sie brauchen, hängt davon ab, ob ein Mensch anwesend ist.

Ein Server-zu-Server-Verbraucher — Ihre CI, die Changelog-Einträge einliefert, Ihr Backend, das eine App-Version abgleicht. Die Zugangsdaten sind eine Client-Kennung und ein Geheimnis, das SIDES ausgibt; es gibt keine Person und kein Erneuerungs-Cookie.

POST /v1/oauth/token
grant_type=password
username=$CLIENT_ID
password=$CLIENT_SECRET
scope=publication.changelog:write

Die angeforderte Berechtigung wird mit dem geschnitten, was der Client darf. Mehr anzufordern ist kein Fehler und bringt Ihnen nicht mehr.

Ein Mensch, der sich am Partnerportal anmeldet. Die Antwort trägt ein kurzlebiges Zugriffstoken und setzt ein Erneuerungs-Cookie, das HttpOnly; Secure; SameSite=Strict ist — das einzige Zugangsmittel, das ein Neuladen der Seite überlebt, und es wird bei jeder Verwendung erneuert.

POST /v1/auth/sessions
{ "email": "[email protected]",
  "password": "…" }

200 { "access_token": "eyJhbGciOi...",
      "expires_in": 900 }
Set-Cookie: __Host-refresh=…; HttpOnly; Secure; SameSite=Strict

Zweiter Faktor aktiv? Der erste Aufruf antwortet MFA_REQUIRED und der Code geht an /v1/auth/sessions:verify-mfa. Das ist absichtlich eine eigene Anfrage: zwei Aufrufe, zwei Budgets, zwei Protokollzeilen.

Welche Ebene es auch ausgegeben hat — das Token gehört in die Authorization -Kopfzeile und nirgendwo sonst. Nie in einen Abfrageparameter — eine URL erreicht das Zugriffsprotokoll, den Browserverlauf und die Referrer-Kopfzeile.

GET /v1/system/me
curl https://api.sideslabs.com/v1/system/me \
  -H "Authorization: Bearer $ACCESS_TOKEN"

{ "principal_type": "PARTNER_USER",
  "scopes": ["partner:write", "marketplace.apps:write", …],
  "rate_limit": { "limit_per_second": 10, "remaining_day": 49873 } }

/v1/system/me ist der Endpunkt, den man zuerst aufruft, wenn etwas antwortet mit 403: Er sagt Ihnen, welche Berechtigungen das Token tatsächlich trägt, und das ist meist die ganze Antwort.

Berechtigungen

Vier Regeln — die vierte überrascht

Jeder Endpunkt hat eine
Grundsätzlich verboten. Ein Endpunkt ohne Berechtigung existiert nur durch eine ausdrückliche, dokumentierte Entscheidung — Gesundheitsprüfung, Token-Endpunkt, öffentliche Dokumentation und die bewusst öffentlichen Lesezugriffe. Die Referenz sagt bei jedem, welches davon gilt.
Sie verschachteln nach Domäne
marketplace → marketplace.apps → marketplace.apps:write. Eine übergeordnete gewährt ihre untergeordneten, ein Token mit der übergeordneten erreicht also alles darunter.
:write schließt Lesen ein
Eine Berechtigung ohne :write ist nur lesend, und wer die Schreibberechtigung hält, muss die Leseberechtigung nicht zusätzlich anfordern.
Eine lesende übergeordnete gewährt nur lesende untergeordnete
Die hier lohnt zweimaliges Lesen. marketplace gewährt marketplace.apps — und nicht marketplace.apps:write. Eine übergeordnete gewährt ihre untergeordneten auf ihrer eigenen Zugriffsstufe, nie darüber.

Ressourcen

Leitfäden, Sammlungen und Beispieldaten

Dargestellt aus GET /v1/publication/public/developer-resources. Alles hier ist öffentlich. Hinter einer Partneranmeldung gibt es mehr — die Ressourcen, deren Zielgruppe partner ist, werden nicht aus dieser Liste gefiltert, sie standen nie darin.

Noch nichts veröffentlicht

Bisher wurde keine öffentliche Anleitung und keine Sammlung veröffentlicht. Partnerinternes Material kann es geben — das liegt hinter der Partneranmeldung und zählt hier nicht mit.

Fragen

Bevor Sie Code schreiben

Muss ich Partner sein, bevor ich mir etwas ansehen kann?

Nein. Der Vertrag ist das Produkt: Die Referenz, diese Seite, das Changelog und der Blog brauchen überhaupt kein Token, und das OpenAPI-Dokument wird als YAML ausgeliefert. Eine Partnerschaft brauchen Sie für Zugangsdaten und um Software im Marktplatz zu listen — nicht, um zu beurteilen, ob die API tut, was Sie brauchen.

Was passiert, wenn sich die API ändert?

Ein Feld, einen Endpunkt oder einen Aufzählungswert zu ergänzen ist keine brechende Änderung, und von Ihrem Client wird erwartet, dass er ignoriert, was er nicht kennt. Eines zu entfernen, umzubenennen oder umzutypisieren braucht eine neue Hauptversion und mindestens sechs Monate Vorlauf, mit dem Abschaltdatum im Changelog und in der X-SIDES-Deprecation -Kopfzeile jeder betroffenen Antwort.

Wie hart sind die Ratenbegrenzungen?

Zwei Budgets, nicht eines: eine Stoßgrenze pro Sekunde und ein Tagesbudget, beide vom Partnertarif gesetzt. Jede Antwort trägt X-RateLimit-*, und ein Überschreiten antwortet 429 RATE_LIMITED mit einem Retry-After , dem Sie folgen sollten, statt zu raten. Die Tarife sagen, was jede Stufe erlaubt.

Gibt es eine Testumgebung?

Noch nicht, und diese Seite tut nicht so. Es gibt heute ein Partnerkonto im kostenfreien Tarif gegen die Live-API, mit Ihren eigenen Daten — genug, um eine Anbindung zu bauen, nicht genug, um sie unter Last zu prüfen. Fragen Sie den Support, bevor Sie eine Testsuite darauf richten.

Welche Sprache und welches SDK?

Jede, und keines. Die API ist REST über HTTP mit JSON-Rümpfen und OAuth-2.0-Bearer-Token — es gibt kein SDK, das Sie übernehmen müssten, und keine Clientbibliothek, die mitgeführt werden muss. Die Postman- und Insomnia-Sammlungen oben werden aus demselben Vertrag erzeugt, den der Server durchsetzt.

Der erste Aufruf dauert etwa zehn Minuten

Die Registrierung legt Ihren Geschäftspartner, Ihren ersten Administrator und Ihr Abonnement in einem Schritt an. Der kostenfreie Tarif reicht, um dagegen zu bauen.