API-Dokumentation
Das Shoppi SDK, die JSON-API und TagCodes: alles, was ein Partner braucht, um auf einem Shoppi-Shop aufzubauen.
So funktioniert es
Jeder Shop auf Shoppi Cloud lässt sich mit dem Shoppi SDK erweitern, einer JavaScript-Bibliothek, die die Plattform auf jeder von Shoppi gehosteten Domain bereitstellt, und mit TagCodes, serverseitigen Platzhaltern, die die Seiten-Engine auflöst, bevor die Seite den Browser erreicht. Beide sprechen mit derselben JSON-API, die auch direkt nutzbar ist.
- Keine API-Schlüssel im Browser. Der Shop wird an der Domain erkannt, von der die Anfrage kommt: Das SDK funktioniert auf der Shop-Domain ohne Geheimnisse im Code.
- Zahlungen laufen über Stripe. Checkout-Sitzungen entstehen auf dem eigenen Stripe-Konto des Händlers (Stripe Connect); Shoppi hält nie das Geld der Kunden des Händlers. Auch Erstattungen laufen vollständig über Stripe.
- Zwei Datenbanken. Der Katalog wird aus der Shoppi-Datenbank gelesen, die der Händler in der App pflegt; jede Shop-Domain hat außerdem eine eigene Datenbank. Du wählst, woraus jede API liest (siehe Katalog). Kundenkonten liegen immer in der eigenen Datenbank der Shop-Domain, getrennt von anderen Shops.
- Aktuelle SDK-Version: 2.9.0. Antworten haben immer dieselbe Form:
{"result": "ok" | "ko", "feedback": …}.
Einrichtung
Binden Sie das SDK einmal im <head> der Seite ein. Beim Laden entsteht das globale Objekt window.Shoppi.
<script>
window.ShoppiConfig = {
pageId: "%_ID%", // store id; the page engine fills it in (use %_ID% inside JS, not {id})
currency: "EUR", // default currency for cart and checkout
defaultLocale: "it", // language used when the URL has no /xx/ prefix
baseUrl: "", // leave empty: API calls go to the same origin
sources: "shoppi" // catalog database: "shoppi" (default) or "local"
};
</script>
<script src="/shoppi/shoppi-sdk.js?v=2.9.0"></script>
Alle Einstellungen sind optional: Ohne ShoppiConfig erkennt das SDK den Shop an der Domain und nutzt EUR. Erhöhen Sie den Parameter ?v=, damit Browser ein neueres SDK laden.
Shop und Inhalte — Shoppi.site
| Methode | Liefert |
|---|---|
Shoppi.site.getInfo() |
Shop-Profil: Name, Logo, Titelbild, Beschreibung, Kategorie, Stadt, Land, Sprache. |
Shoppi.site.getPage(slug) |
Eine Inhaltsseite über ihren Slug: Titel, HTML-Inhalt und Schlüsselwörter, oder null. |
Shoppi.site.getPages() |
Die Bereiche des Shops: Inhaltsseiten und die Kategorien der Produkte. |
Shoppi.site.getProducts(options) |
Wie Shoppi.catalog.products(). |
Shoppi.site.getProduct(idOrSlug) |
Wie Shoppi.catalog.product(). |
Shoppi.site.getCategories() |
Wie Shoppi.catalog.categories(). |
Shoppi.site.search(q) / getSuggestions(q) |
Wie Shoppi.catalog.search() und suggestions(). |
const info = await Shoppi.site.getInfo();
document.getElementById('store-name').textContent = info.title;
Katalog — Shoppi.catalog
Produkte, Kategorien, Fotos und Suche: die Daten, die der Händler in der Shoppi-App pflegt, bereit für eine Storefront. Jeder Artikel kommt in derselben Form zurück, egal welcher Typ:
{
id: 9610389, type: 'products', // products | services | files | offers
slug: 'curtirisorisobasmati2×500g',
title: 'Curtiriso Riso Basmati 2 × 500 g',
description: '', content: 'Basmati', // content may contain HTML
price: 4.79, currency: 'EUR', price_format: '4,79 €',
photo: 'https://storage.shoppi.app/…', photo_hires: '…', photos: ['…'],
quantity: 5, in_stock: true, ship_cost: 0, code: 'CX-DIS-000001',
category: 'Dispensa', keywords: ['dispensa'], link: '…', date: 1791312283
}
| Methode | Liefert |
|---|---|
Shoppi.catalog.products(options) |
Liefert { items, count, limit, skip, hasMore }. Optionen: type (products, services, files, offers, all), limit (24), skip, sort (newest, updated, popular, price_asc, price_desc, title), category (ID, Slug oder Titel), q, ids, inStock. |
Shoppi.catalog.product(idOrSlug, { type }) |
Ein Artikel oder null. Artikel eines anderen Shops werden nie geliefert. |
Shoppi.catalog.categories({ type }) |
sections (Standard: die Kategorien, denen Produkte zugeordnet sind), albums oder tree. |
Shoppi.catalog.category(ref) |
Eine Kategorie über ID, Slug oder Titel. |
photos(), pages(), page(slug), news(), videos() |
Die Inhalte des Shops. |
Shoppi.catalog.search(q, { type, limit, minPrice, maxPrice }) |
Liefert { items, count, suggestions, did_you_mean }. |
Shoppi.catalog.suggestions(q) |
Titel für eine Autovervollständigung. |
Shoppi.catalog.info() |
Shop-Profil. |
const page = await Shoppi.catalog.products({ limit: 12 });
const cats = await Shoppi.catalog.categories(); // [{ id: 600, slug: 'dispensa', title: 'Dispensa' }, …]
const food = await Shoppi.catalog.products({ category: 'dispensa' });
const one = await Shoppi.catalog.product(9610389); // or by slug
const hits = await Shoppi.catalog.search('riso'); // { items, count, suggestions }
Welche Datenbank: pro API, pro Aufruf
'shoppi' (Standard) liest die Shoppi-Datenbank, in der der Händler seine Produkte über die App pflegt. 'local' liest die eigene Datenbank der Shop-Domain, leer, bis du hineinschreibst. Wähle pro API in ShoppiConfig.sources, zur Laufzeit mit Shoppi.catalog.use() oder für einen einzelnen Aufruf mit { source }. Eine Quelle kann auch die Basis-URL eines anderen Hosts oder eine Funktion mit eigenen Daten sein. Warenkorb, Checkout, Kundenkonten und E-Mail laufen immer über die Domain des Shops.
window.ShoppiConfig = {
pageId: "%_ID%",
sources: { products: 'shoppi', categories: 'local' } // or one value: 'local'
};
Shoppi.catalog.use('search', 'local'); // at runtime, one API
await Shoppi.catalog.products({ limit: 12 }, { source: 'local' }); // for one call
Rendering und Events
Shoppi.render(target, items, template) füllt ein Element mit einer Liste: Das Template ist eine Funktion, ein Handlebars-String oder nichts für die eingebaute Karte mit In-den-Warenkorb-Button. Elemente mit data-shoppi-list füllen sich beim Laden der Seite selbst; ihre übrigen data-shoppi-*-Attribute sind die Optionen der passenden Methode. Events auf document: shoppi:cart:added, shoppi:cart:updated, shoppi:checkout:started, shoppi:rendered.
const r = await Shoppi.catalog.products({ limit: 12 });
Shoppi.render('grid', r); // built-in card with add-to-cart button
Shoppi.render('grid', r, p => `<h3>${p.title}</h3><p>${p.price_format}</p>`);
<div data-shoppi-list="products" data-shoppi-limit="12" data-shoppi-category="dispensa">
<template><div class="card"><img src="{{photo}}"><h3>{{title}}</h3>
<button data-shoppi-add="{{id}}" data-shoppi-price="{{price}}"
data-shoppi-title="{{title}}" data-shoppi-image="{{photo}}">Add</button></div></template>
</div>
document.addEventListener('shoppi:cart:added', e => console.log(e.detail.title));
Warenkorb — Shoppi.cart
Der Warenkorb liegt im Browser (localStorage) und übersteht ein Neuladen. Übergebene Preise und Titel gehen bis zum Checkout, setzen Sie sie also immer.
| Aufruf | Funktion |
|---|---|
Shoppi.cart.add(id, qty, { price, title, image }) |
Fügt ein Produkt hinzu (Menge standardmäßig 1). |
Shoppi.cart.updateQty(id, qty) |
Setzt die Menge; 0 entfernt die Zeile. |
Shoppi.cart.remove(id) |
Entfernt eine Zeile. |
Shoppi.cart.clear() |
Leert den Warenkorb. |
Shoppi.cart.setCountry(code) |
Setzt das Versandland (ISO-Code, z. B. 'IT'). |
Shoppi.cart.data |
Aktueller Stand: { items, count, total, country }. |
Ohne JavaScript, mit HTML-Attributen:
<button data-shoppi-add="10034"
data-shoppi-price="29.90"
data-shoppi-title="Leather wallet"
data-shoppi-image="/img/wallet.jpg">Add to cart</button>
<span class="shoppi-cart-count"></span> <!-- item count, updated automatically -->
<span class="shoppi-cart-total"></span> <!-- total, formatted in the store currency -->
<select data-shoppi-country> <!-- shipping country -->
<option value="IT">Italia</option>
<option value="DE">Deutschland</option>
</select>
<button data-shoppi-checkout>Checkout</button>
Checkout — Shoppi.checkout
| Methode | Funktion |
|---|---|
Shoppi.checkout.start() |
Erstellt eine Stripe-Checkout-Sitzung für den Warenkorb auf dem Stripe-Konto des Händlers und leitet den Kunden dorthin. |
Shoppi.checkout.startDirect(productId, metadata) |
Kauf eines einzelnen Produkts mit einem Klick, ohne Warenkorb (Dienstleistungen, Buchungen, Downloads). |
Shoppi.checkout.createOnboardingLink() |
Liefert den Stripe-Onboarding-Link des Shops, um sein Stripe-Konto zu verbinden oder zu vervollständigen. |
document.querySelector('#buy').addEventListener('click', () => Shoppi.checkout.start());
// Stripe onboarding for the merchant
const url = await Shoppi.checkout.createOnboardingLink();
window.location.href = url;
Jeder Button mit data-shoppi-checkout macht dasselbe wie Shoppi.checkout.start(). Die Zahlungskosten richten sich nach dem Tarif des Shops: Stripe-Gebühren plus die Shoppi-Pay-App-Gebühr von 0,4 % + 1 Cent pro Zahlung. Auch Erstattungen, ganz oder teilweise, online oder an der Kasse, laufen über Stripe.
Kundenkonten — Shoppi.user
Konten für die Kunden des Shops, gespeichert in der Datenbank des Shops. Nach dem Login bleibt das Sitzungstoken im Browser und wird mit jeder SDK-Anfrage im Header X-User-Token gesendet. Konten sind an die Shop-Domain gebunden: Zwei Shops sehen nie die Kunden des anderen.
| Methode | Funktion |
|---|---|
Shoppi.user.register(email, password, firstName, lastName) |
Legt ein Konto an und meldet an. |
Shoppi.user.login(email, password) |
Meldet an. |
Shoppi.user.getProfile() |
Profil des angemeldeten Kunden (null, wenn abgemeldet). |
Shoppi.user.updateProfile(data) |
Aktualisiert Profilfelder, z. B. { phone }. |
Shoppi.user.saveAddress(type, address) |
Speichert eine Adresse; type ist z. B. 'shipping'. |
Shoppi.user.logout() |
Beendet die Sitzung und lädt die Seite neu. |
Navigation und Übersetzungen — Shoppi.router, Shoppi.lang
URLs folgen dem Muster /<language>/<page>, z. B. /it/contatti. Shoppi.router.navigate(slug, locale) lädt eine Seite ohne komplettes Neuladen und zeigt sie in <main>; Links mit data-shoppi-link tun dasselbe.
<a href="/it/contatti" data-shoppi-link="contatti">Contatti</a>
Shoppi.lang.load(locale) lädt die Übersetzungen des Shops; Shoppi.lang.t(key, vars) liefert einen Text und ersetzt Platzhalter der Form %_NAME%.
Lokales Verzeichnis — Shoppi.local
| Methode | Rückgabe |
|---|---|
Shoppi.local.getCities() |
Im lokalen Verzeichnis verfügbare Städte. |
Shoppi.local.getBusinesses(cityId, categoryId) |
Betriebe einer Stadt, optional nach Kategorie gefiltert. |
E-Mail — Shoppi.mailer
Sendet eine Transaktions-E-Mail aus dem Shop, z. B. aus einem Kontaktformular. Begrenzt auf 10 E-Mails pro Tag und Gerät.
await Shoppi.mailer.send({
to: '[email protected]',
subject: 'New request from the website',
body: '<p>Hello!</p>',
replyTo: '[email protected]' // optional
});
Shoppi.mailer.remaining(); // emails left today on this device
JSON-API
Jede SDK-Methode ist ein Aufruf der JSON-API, die Sie direkt mit Shoppi.call(endpoint, params, method) oder einfachem fetch nutzen können: Das Muster ist /api/<module>/<method>/json, auf der Domain des Shops.
| Endpunkt | Zweck |
|---|---|
GET /api/website/info/json |
Shopprofil |
GET /api/website/section/json?clear_title=<slug> |
Inhaltsseite |
POST /api/checkout/createStripeSession/json |
Stripe-Checkout-Sitzung aus einem Warenkorb |
POST /api/checkout/startDirect/json |
Direktkauf eines Produkts |
GET /api/checkout/createOnboardingLink/json |
Stripe-Onboarding-Link |
POST /api/frontend_user/register/json |
Kundenregistrierung |
POST /api/frontend_user/login/json |
Kundenlogin |
GET /api/local/getCities/json |
Lokales Verzeichnis: Städte |
GET /api/website/products/json |
Produkte (auch listServices, listFiles, listOffers) |
GET /api/website/product/json?id= |
Ein Produkt, über id oder clear_title
|
GET /api/website/sections/json |
Bereiche und Kategorien |
GET /api/website/listSells/json?parent= |
Artikel eines Bereichs |
GET /api/search/results/json?query= |
Suche |
GET /api/search/suggestions/json?query= |
Autovervollständigung |
const res = await fetch('/api/website/info/json', { credentials: 'include' });
const data = await res.json(); // { "result": "ok", ... } or { "result": "ko", "feedback": "reason" }
Die Katalog-Endpunkte antworten auf der Shop-Domain (ihre eigene Datenbank) und auf https://shoppi.app (die Shoppi-Datenbank). Für die Quelle 'shoppi' ruft das SDK shoppi.app mit der Shop-ID auf: Eine ID, die nicht zur aufrufenden Domain gehört, wird abgelehnt. Shoppi.call(endpoint, params, method, { base }) wählt den Host.
Shoppi.call() liefert den nützlichen Teil einer ok-Antwort und wirft bei ko einen Error mit der feedback-Meldung.
TagCodes (serverseitig)
TagCodes sind Platzhalter in den HTML-Templates des Shops, die auf dem Server aufgelöst werden, bevor die Seite gesendet wird: Der Inhalt steht im HTML, das Suchmaschinen sehen.
| TagCode | Ausgabe |
|---|---|
{css} / {js}
|
Stylesheets und Skripte der Seite und ihrer Plugins |
{page_title}, {page_description}
|
SEO-Titel und -Beschreibung |
{page_name}, {page_logo}
|
Shopname und Logo |
{locale}, {currency}, {country}
|
Aktive Sprache, Währung, Land des Besuchers |
{title}, {content}, {photo}, {price}, {link}
|
Felder des aktuellen Produkts oder Artikels |
{cfield:title}, {cfield:description}, {cfield:cover}
|
Felder des Shopprofils |
{cart:act=drawer} |
Seitlicher Warenkorb |
{search:nout=true} |
Suche, ohne Standardausgabe initialisiert |
{cookieconsent} |
Cookie-Einwilligungsbanner |
{offers:act=seo} |
Strukturierte JSON-LD-Daten für Produkte |
Innerhalb eines JavaScript-Objekts verwenden Sie %_ID% für die Shop-ID: Geschweifte Klammern würden dort als TagCode gelesen.
Zugriff auf Dateien und Daten
Die Dateien jedes Shops sind per WebDAV erreichbar (auch über die Desktop-App Shoppi Go), und die Daten bleiben exportierbar: Standard-HTML-Templates, die eigene Datenbank des Shops und die JSON-API oben. Die Zugangsdaten stehen im Kontobereich des Shops.
Fragen oder ein Fall, der hier fehlt? Termin buchen mit dem Partnerteam, oder zurück zum Partner-Kit.