Einbau
Eine Zeile im Shop, ein Aufruf auf Ihrem Server
EdelVerify prüft das Alter und gibt Ihrem Shop genau eine Auskunft zurück: alt genug, ja oder nein — gegen 16 oder gegen 18, je nachdem, was Ihre Ware verlangt. Diese Seite beschreibt den Einbau vollständig — inklusive Testschlüsseln, mit denen Sie die Einbindung heute bauen und prüfen können. Woher Sie die Schlüssel bekommen und was das kostet, steht gleich im ersten Abschnitt.
Wie es zusammenspielt
Der Einbau besteht aus zwei Hälften, und die Trennung ist der eigentliche Entwurf:
Im Browser läuft die Bedienung — ein Fenster mit QR-Code, das Ihre Kundschaft durch die Prüfung führt. Das ist Anzeige, und Anzeige lässt sich mit den Entwicklerwerkzeugen umgehen.
Auf Ihrem Server sitzt der Riegel. Vor dem Bestellabschluss lösen Sie den Nachweis ein. Erst dieser Aufruf ist bindend. Wer ihn weglässt, hat eine hübsche Schranke ohne Schloss.
Geprüft wird heute über den Chip im Ausweis. Der E-ID-Weg ist gebaut, unser Verifier steht im Vertrauensregister des Bundes — und er ist abgeschaltet, solange der Bund die E-ID nicht produktiv ausgibt (Termin offen, vom Bund am 30. Juni 2026 verschoben). Die Altersprüfung startet deshalb ohne Wahlschirm direkt mit dem Ausweis; es gibt nichts zu wählen. Die App, die den Chip liest, steht im Play Store; die iPhone-Fassung fehlt noch. Für Ihre Einbindung macht der Weg keinen Unterschied: Die Schnittstelle bleibt dieselbe, nur was dahinter passiert, ändert sich. Kommt die E-ID zurück, kommt sie ohne Änderung an Ihrem Code — daran, ob sie angeboten wird, erkennen Sie es am Feld eid_available in der Antwort auf POST /api/v1/verifications.
Schlüssel, Preis und der Weg zum Gespräch
Diese Seite verspricht Testschlüssel. Hier steht, woher Sie sie bekommen — und was Sie dafür bezahlen.
Testschlüssel gibt es nicht per Knopfdruck. Wir legen Ihren Shop von Hand an und schicken Ihnen das Paar: einen öffentlichen pk_test_… und einen geheimen sk_test_…. Im selben Zug hinterlegen wir die erlaubten Herkunftsadressen und, wenn Sie einen wollen, den Webhook — beides ist ebenfalls nichts, was Sie selbst einstellen können.
Sagen Sie uns dafür: die Adressen Ihres Shops (mit und ohne www, dazu das Testsystem), die Altersgrenze, die Ihre Ware verlangt, und welches Shop-System Sie einsetzen.
Bauen kostet nichts, Betrieb schon. Testschlüssel sind kostenlos; mit ihnen können Sie die ganze Einbindung fertigstellen. Was der Betrieb kostet, steht offen unter /preise — Abschluss über Stripe mit Karte oder TWINT, das Konto entsteht nach der Zahlung.
Der geheime Schlüssel gehört auf Ihren Server, sonst nirgendwohin
Kein Chatverlauf, kein Ticket, kein Bildschirmfoto. Wer ihn hat, stellt sich Nachweise selbst aus. Ist er hinausgefallen, sagen Sie es uns — wir ziehen ihn zurück und geben Ihnen einen neuen. Das dauert eine Minute und ist immer die richtige Entscheidung.
Pakete zum Herunterladen
Für alle vier Shop-Systeme gibt es ein Archiv, eine Einbauanleitung und einen Prüfplan. Der Prüfplan ist der wichtigere Teil: Er sagt nicht, wie man einbaut, sondern woran man erkennt, dass der Riegel wirklich hält — samt der Befehle zum Nachmessen.
| System | Archiv | Zum Lesen |
|---|---|---|
| WooCommercePlugins → Installieren → Plugin hochladen | edelverify-plugin.zip | Anleitung und Prüfplan |
| Shopware 6Erweiterungen → Meine Erweiterungen → Erweiterung hochladen | edelverify-shopware.zip | Anleitung und Prüfplan |
| Magento 2Baum nach app/code/ entpacken, dann setup:upgrade | edelverify-magento.zip | Anleitung und Prüfplan |
| ShopifyProjektbaum für die Shopify-CLI (shopify app deploy) | edelverify-shopify.zip | Anleitung und Prüfplan |
Anleitung und Prüfplan liegen zusätzlich im Archiv. Wer es über «Hochladen» installiert, sieht unser Repository nie und hätte sonst nur die halbe Anleitung.
Ein Archiv sagt nichts über den Stand. Erprobt in Läden, die wir selbst betreiben: WooCommerce, Shopware 6 und Magento 2. Noch nicht: Shopify. Was das heisst, steht weiter unten unter Stand je Shop-System.
Testbetrieb ohne Wallet
Die produktive E-ID des Bundes ist noch nicht ausgegeben (Termin offen, vom Bund am 30. Juni 2026 verschoben). Damit Sie Ihre Einbindung nicht bis dahin aufschieben müssen, gibt es Testschlüssel: Sie erkennen sie am Anfang pk_test_ und sk_test_.
Eine Prüfung mit Testschlüssel spricht den Prüfdienst des Bundes gar nicht erst an. Sie steht vier Sekunden auf PENDING — damit Ihre Abfrageschleife wirklich durchläuft — und nimmt dann den Ausgang, den Sie bestellt haben.
curl -X POST https://verify.edelbyte.ch/api/v1/verifications \
-H "Authorization: Bearer sk_test_…" \
-H "content-type: application/json" \
-d '{"reference":"warenkorb-4711","min_age":16,"test_outcome":"under_18"}'min_age ist optional und nimmt die Zahl 16 oder 18. Ohne Angabe gilt die Vorgabe Ihres Shops, ab Werk 18. Im Beispiel oben prüft der Testlauf gegen 16 und liefert jemanden, der auch das nicht erreicht.
| test_outcome | Ergebnis |
|---|---|
success | Vorgabe. status SUCCESS, age_ok true, Nachweis wird ausgestellt — gegen die Grenze, die Sie mit min_age bestellt haben. |
under_18 | status SUCCESS, age_ok false, kein Nachweis. Der Name ist geblieben, die Bedeutung ist jetzt «unter der bestellten Grenze» — bei einer Prüfung ab 16 also unter 16. Der Fall, den Ihre Einbindung am seltensten sieht und am dringendsten können muss. |
failed | status FAILED mit error_code test_failed — die Wallet hat abgebrochen. |
expired | status EXPIRED — niemand hat die Prüfung abgeschlossen. |
Ein unbekannter Wert wird mit 400 invalid_test_outcome abgewiesen und nicht stillschweigend zu «success» geglättet. Wer sich bei under_18 vertippt, soll es merken.
Die beiden Welten berühren sich nie
Ein Nachweis aus dem Testbetrieb lässt sich mit einem Live-Schlüssel nicht einlösen, und umgekehrt. Eine Prüfung, die mit pk_test_ begonnen wurde, ist für einen Live-Schlüssel schlicht unbekannt. Entschieden wird das ausschliesslich am Schlüssel — nie an einem Feld, das Sie mitschicken.
Schritt 1 — im Shop
Eine Zeile ins Layout, vor dem schliessenden Body-Tag:
<script src="https://verify.edelbyte.ch/v1/gate.js"
data-key="pk_test_…"
data-callback="/wp-json/edelverify/v1/confirm"
defer></script>| Attribut | Bedeutung |
|---|---|
data-key | Pflicht. Ihr öffentlicher Schlüssel. Er darf im Quelltext stehen. |
data-callback | Adresse auf Ihrem Server, an die nach Erfolg die Kennung gemeldet wird. |
data-accent | Akzentfarbe des Fensters. Vorgabe #0f62d6. |
data-title | Überschrift im Fenster. |
data-lang | de, fr, it oder en. Vorgabe de. |
data-min-age | 16 oder 18. Die Vorgabe für alle Auslöser, die keine eigene Grenze mitbringen. Fehlt das Attribut, schickt das Skript gar keine Grenze mit — dann gilt die für Ihren Shop hinterlegte, ab Werk 18. Eine bestehende Einbindung ändert ihr Verhalten dadurch nicht. |
data-test-outcome | Nur mit Testschlüssel. Bestellt den Ausgang für alle Prüfungen dieser Seite: success, under_18, failed oder expired. Damit lassen sich die vier Fälle im Shop durchspielen, ohne den Aufruf selbst zu bauen. |
Ausgelöst wird über ein Attribut am Knopf — kein eigener JavaScript-Code nötig. Verlangt die Ware nur 16, kommt die Grenze an den Knopf und sticht die Vorgabe am Skript-Tag:
<button data-edelverify
data-edelverify-reference="warenkorb-4711"
data-edelverify-min-age="16">
Alter bestätigen
</button>Wer den Ablauf selbst steuern will, ruft window.EdelVerify.open() auf. Zurück kommt ein Promise:
const { verified, id } = await window.EdelVerify.open({
reference: 'warenkorb-4711',
min_age: 16,
test_outcome: 'under_18', // nur mit Testschlüssel
})min_age und test_outcome gelten für diesen einen Aufruf und gehen den Attributen am Skript-Tag vor. Ohne test_outcome nimmt eine Testprüfung immer den glücklichen Ausgang — bauen Sie Ihre Einbindung deshalb nicht ohne: der Fall, den Sie sehen müssen, ist under_18.
Zusätzlich meldet das Skript jeden Schritt am document: edelverify:started, edelverify:verified, edelverify:stored, edelverify:failed, edelverify:error und edelverify:closed. Das ist der Weg für Systeme, in denen sich kein data-callback setzen lässt.
«verified» ist nicht der Moment zum Neuladen
verified sagt: die Prüfung ist bestanden. Es sagt nicht, dass Ihr Server davon weiss — die Rückmeldung an data-callback läuft in diesem Augenblick erst los. Wer hier neu lädt, bricht sie ab. Der Nachweis wird nur einmal ausgeliefert und ist damit verbrannt: Die Seite kommt mit derselben Schranke zurück, und für Ihre Kundschaft sieht es aus, als hätte die Prüfung nichts bewirkt.
Warten Sie stattdessen auf edelverify:stored. Das feuert, sobald Ihre Route die Kennung angenommen hat — oder sofort, wenn Sie gar kein data-callback gesetzt haben und den Stand selbst abholen.
Das Fenster hängt in einem eigenen Shadow DOM. Ihr Shop-CSS kann es nicht verschieben, und es kann Ihres nicht durcheinanderbringen.
Schritt 2 — auf Ihrem Server
Der Browser meldet Ihnen nur die Kennung der Prüfung. Alles Weitere macht Ihr Server mit dem geheimen Schlüssel — er verlässt Ihren Server nie.
a) Nachweis abholen. Direkt nachdem der Browser die Kennung gemeldet hat:
GET https://verify.edelbyte.ch/api/v1/verifications/<id>
Authorization: Bearer sk_test_…
→ { "status": "SUCCESS", "min_age": 18, "age_ok": true, "over_18": true,
"method": "ausweis_nfc", "authenticity": "daten_echt",
"proof": "av_…", "proof_expires_at": "2026-09-13T…" }over_18 beantwortet nicht die Frage, die Sie stellen
over_18 ist nur dann true, wenn gegen 18 geprüft wurde. Haben Sie mit min_age: 16 gefragt, steht dort false — auch wenn die Person in Wirklichkeit dreissig ist. Das ist kein Fehler, sondern Datensparsamkeit: Sie haben nach 16 gefragt, also erfahren Sie nur, ob 16 erreicht ist.
Massgeblich für Ihre Ware sind deshalb age_ok und min_age zusammen: age_ok sagt, ob die Grenze erreicht ist, min_age, welche Grenze das war. Wer nur over_18 abfragt, weist bei einer 16er-Prüfung jede Bestellung ab.
method sagt, welcher Weg dahintersteht
eid heisst: ein vom Bund signierter Nachweis aus der swiyu-Wallet, geprüft gegen das eidgenössische Vertrauensregister. ausweis_nfc heisst: Die EdelVerify-App hat den Chip im Pass oder Ausländerausweis gelesen. ausweis_mrz heisst: Sie hat nur die maschinenlesbaren Zeilen am Rand mit der Kamera gelesen.
Die drei belegen nicht dasselbe, und die Reihenfolge ist echt. Der Chip gibt nur etwas heraus, wenn ihm die abgelesenen Zeilen der Datenseite gezeigt werden — er belegt damit, dass das Dokument beim Lesen körperlich vorlag. Über die Echtheit des Dokuments sagt method nichts — das steht in einem eigenen Feld daneben (siehe unten). Die blossen Zeilen belegen auch das nicht mehr: Ein Foto der Rückseite genügt ihnen, denn die Kamera unterscheidet ein Dokument nicht von seinem Abbild. Sie sind trotzdem da, weil die Schweizer Identitätskarte keinen Chip trägt — und der Erläuternde Bericht des BSV zur Jugendschutzverordnung nennt die Überprüfung der maschinenlesbaren Zeichen eines amtlichen Ausweises ausdrücklich als geeignet.
Sie müssen das nicht selbst nachrechnen. In Ihren Einstellungen steht eine Mindeststufe, ab Werk ausweis_nfc — die Zeilen-Stufe ist also aus, und ein Nachweis, der auf ihr entstanden ist, kommt bei Ihnen mit valid: false zurück. Die Einlösung nennt beides: method, wie der Nachweis entstand, und required_method, was Sie verlangen. Der Unterschied der beiden ist die Erklärung für eine Absage, die sonst aussähe wie ein abgelaufener Nachweis.
Wer alle Wege gelten lässt, ignoriert die Felder. Wer für einen Teil seines Sortiments den staatlichen Nachweis verlangen muss, prüft zusätzlich auf method === 'eid' — und zwar serverseitig beim Einlösen, nicht im Browser. Das Feld steht in der Auskunft, in der Einlösung und in der Webhook-Meldung.
Heute liefert es nie eid. Der E-ID-Weg ist abgeschaltet, bis der Bund produktiv ausgibt — Termin offen, vom Bund am 30. Juni 2026 verschoben. Wer jetzt auf method === 'eid' prüft, weist damit jede Bestellung ab. Bauen Sie die Abfrage ein, wenn Sie sie brauchen werden; scharf schalten Sie sie an dem Tag, an dem eid_available wahr wird.
authenticity sagt, ob der Ausweis echt ist — eine andere Frage
method beantwortet, wie das Dokument vorgelegt wurde. authenticity beantwortet, ob es echt ist. Das sind zwei Fragen, und ein Chip, der antwortet, beantwortet nur die erste: Ein nachgebauter Chip mit abgeschriebenem Datenbestand antwortet genauso.
Drei Werte, vom schwächsten zum stärksten. keine: Nicht, dass das Dokument echt ist. Ein nachgebauter Chip mit abgeschriebenem Datenbestand antwortet genauso. Das ist kein Verdacht gegen ein einzelnes Dokument, sondern die Beschreibung dessen, was ohne die Länderzertifikate feststeht: nichts. daten_echt: Dass die gelesenen Daten von einer staatlichen Ausgabestelle unterschrieben sind und deren Zertifikat auf ein Wurzelzertifikat des ausstellenden Staates zurückgeht, das wir vorher kannten. Das Geburtsdatum stammt also aus einem echten Ausweis. Nicht, dass der CHIP echt ist. Ein Nachbau, der einen echten Datenbestand abgeschrieben hat, besteht diese Prüfung — die Daten sind ja echt, sie stecken nur in der falschen Karte. Und nicht, dass die Person vor der Kasse die Person im Ausweis ist; das prüft kein Verfahren, das ohne Blick auf ein Gesicht auskommt. chip_echt: Zusätzlich, dass der Chip den Besitz eines privaten Schlüssels nachgewiesen hat, dessen öffentliche Hälfte in den staatlich unterschriebenen Daten steht. Ein Nachbau mit abgeschriebenem Inhalt scheitert daran: Den Schlüssel kann er nicht abschreiben. Nicht, dass der Ausweis der Person gehört, die ihn auflegt. Ein echter, unverfälschter Ausweis in fremder Hand besteht jede Prüfung dieser Achse. Und nicht, dass die meldende App unverändert ist — dafür fehlt die Geräte-Attestierung. Diese Stufe ist die stärkste, die ein Ausweischip hergibt, und sie ist trotzdem nicht alles.
null heisst «unbekannt», nicht «nichts geprüft». Zwei Ursachen: Die meldende Fassung unserer App kennt den Befund noch nicht, oder es war gar kein Chip im Spiel. Wer null wie keine behandelt, schreibt einer Prüfung ein Ergebnis zu, das nie gemeldet wurde — und weist womöglich jede ältere App-Fassung ab, ohne es zu merken.
Verlangen können Sie es wie die Mindeststufe: In den Einstellungen steht eine verlangte Echtheitsprüfung, ab Werk keine — dann geht auch null durch, und für Sie ändert sich nichts. Wer sie höher stellt, verlangt damit zugleich den Chip-Weg und eine App-Fassung, die den Befund mitschickt. Für Tabakwaren nach Art. 25 TabPG ist das der richtige Tausch; für Bier ab 16 vermutlich nicht. Die Einlösung nennt beides: authenticity und required_authenticity.
Woran es hängt: Die App braucht dafür die Wurzelzertifikate der ausstellenden Staaten. Sie holt sie als unterschriebenes Bündel von uns (GET /api/v1/anker, öffentlich) und rechnet die Kette im Gerät nach. Liegt für einen Staat keine Wurzel vor, bleibt es bei keine — das ist dann keine Aussage über das Dokument, sondern eine Lücke bei uns.
Der Nachweis kommt genau einmal
Er entsteht im Moment des Übergangs auf SUCCESS und wird nur in dieser einen Antwort ausgeliefert. Legen Sie ihn sofort ab — in der Sitzung, im Kundenkonto oder in einem HttpOnly-Cookie. Geht er verloren, muss die Kundschaft erneut prüfen.
b) Nachweis einlösen. Vor jedem Bestellabschluss. Das ist der Riegel:
POST https://verify.edelbyte.ch/api/v1/proofs/verify
Authorization: Bearer sk_test_…
{ "proof": "av_…", "min_age": 16 }
→ { "valid": true, "min_age": 18, "required_min_age": 16, "over_18": true,
"method": "ausweis_nfc", "required_method": "ausweis_nfc",
"authenticity": "daten_echt", "required_authenticity": "keine",
"expires_at": "2026-09-13T…", "reference": "warenkorb-4711" }Beim Einlösen sagt min_age, was die Ware verlangt. Ohne Angabe gilt 18. Zurück kommen beide Zahlen: min_age ist die Grenze, gegen die der Nachweis ausgestellt wurde, required_min_age die, gegen die eingelöst wurde. Im Beispiel oben deckt ein Nachweis ab 18 eine Ware ab 16 ab.
Ein Nachweis ab 16 löst keine Ware ab 18 ein; ein Nachweis ab 18 löst Ware ab 16 ein. Der Vergleich läuft in eine Richtung, und zwar auf unserer Seite — Sie müssen nichts nachrechnen. Wer beim Einlösen gar kein min_age mitschickt, prüft gegen 18: Ein 16er-Nachweis kommt dann als valid: false zurück.
Sobald der Schlüssel angenommen ist, antwortet dieser Aufruf immer mit HTTP 200; ob der Nachweis taugt, steht in valid. Das ist Absicht: Ein 4xx an dieser Stelle verleitet Einbindungen dazu, den Fehlerfall als «Dienst kaputt, durchlassen» zu behandeln. Auch die zu niedrige Altersstufe ist deshalb kein Fehler, sondern valid: false.
Davor steht die Anmeldung. Die läuft vor der 200-Regel: Ein unbekannter, zurückgezogener oder falscher Schlüssel wird mit 401 unauthorized abgewiesen, und ein öffentlicher pk_-Schlüssel gilt hier als falsche Art — auch er bekommt 401. Die 200-Regel gilt also für die Antwort auf Ihren Nachweis, nicht für die Anfrage an sich. Ein 401 heisst blockieren, nicht durchlassen: Wenn der Schlüssel nicht stimmt, ist überhaupt nichts geprüft.
Im Zweifel blockieren
Kein Nachweis, kein Netz, kein Schlüssel — in jedem dieser Fälle gehört die Bestellung angehalten, nie freigegeben. Der Schaden einer abgewiesenen Bestellung ist ein verärgerter Kunde. Der Schaden einer durchgelassenen ist eine Anzeige.
Die Schnittstelle
Vier Endpunkte. Der Schlüssel geht als Authorization: Bearer … oder x-api-key.
| Endpunkt | Schlüssel | Zweck |
|---|---|---|
POST /api/v1/verifications | pk oder sk | Prüfung beginnen. Optional min_age. Zurück: id, deeplink, expires_at, min_age, eid_available. Die Prüfung verfällt nach 20 Minuten. |
GET /api/v1/verifications/:id | pk oder sk | Stand abfragen: status, min_age, age_ok, over_18. Mit sk zusätzlich der Nachweis — einmalig. |
POST /api/v1/proofs/verify | nur sk | Nachweis einlösen, optional gegen min_age. Der Riegel. Ohne CORS — gehört auf den Server. |
GET /api/v1/verifications/:id/qr.svg | keiner | QR-Code als Bild, direkt als img einbindbar. Nur solange die Prüfung läuft. |
qr.svg gilt nur, solange die Prüfung läuft
Das Bild gibt es ausschliesslich im Zustand PENDING. Sobald die Prüfung abgeschlossen oder verfallen ist, antwortet die Adresse mit 404 als schlichtem Text — kein Bild. Das ist Absicht: Ein QR-Code, der ins Leere führt, gehört nicht an eine Bestellseite.
Für Ihre Einbindung heisst das: Ein <img>, das nach dem Erfolg stehen bleibt, läuft auf ein kaputtes Bild. Nehmen Sie es weg, sobald der Stand nicht mehr PENDING ist.
status ist einer von PENDING, SUCCESS, FAILED oder EXPIRED. Achtung: SUCCESS heisst «die Prüfung ist abgeschlossen», nicht «alt genug». Massgeblich sind age_ok und min_age.
Zwei Altersstufen. min_age nimmt die Zahl 16 oder 18 — nicht die Zeichenkette "18". Alles andere, auch 17 oder 21, wird mit 400 invalid_min_age abgewiesen; wir raten nicht, was gemeint war. Lassen Sie das Feld weg, gilt die für Ihren Shop hinterlegte Vorgabe, ab Werk 18.
over_18 bleibt für bestehende Einbindungen erhalten, beantwortet aber ausschliesslich die 18er-Frage: Bei einer Prüfung gegen 16 steht dort false, unabhängig vom tatsächlichen Alter. Neue Einbindungen lesen age_ok zusammen mit min_age.
Herkunftsprüfung. Für den öffentlichen Schlüssel lässt sich hinterlegen, von welchen Adressen er benutzt werden darf. Solange für Ihren Shop keine Adresse hinterlegt ist, wird jede Herkunft angenommen — auch eine fremde, und auch gar keine. Erst mit dem ersten Eintrag greift die Sperre, und dann antwortet die Schnittstelle jeder nicht gelisteten Herkunft mit 403 origin_not_allowed.
Das ist so gebaut, damit eine neue Einbindung nicht an einer Kleinigkeit scheitert, bevor sie je lief. Vor dem Kundenbetrieb gehört die Liste aber gefüllt — sonst kann jede beliebige Seite Prüfungen auf Ihren Schlüssel beginnen. Diese Einstellung nehmen wir für Sie vor — sagen Sie uns Adresse und gewünschte Grenze. Einen Selbstbedienungszugang gibt es heute noch nicht. So erreichen Sie uns.
Ein Nachweis gilt standardmässig 30 Tage und ausschliesslich bei dem Shop, für den er ausgestellt wurde. Die Frist stellt der Händler im Portal ein — die Gebrauchsanleitung zeigt, wo.
Fehlerschlüssel
| Schlüssel | HTTP | Bedeutung |
|---|---|---|
unauthorized | 401 | Schlüssel unbekannt, zurückgezogen oder von der falschen Art. |
origin_not_allowed | 403 | Für Ihren Shop ist eine Herkunftsliste hinterlegt, und die aufrufende Herkunft steht nicht darin. Ist die Liste leer, tritt dieser Fall nie auf. |
not_found | 404 | Unbekannte Prüfung — oder eine aus der jeweils anderen Welt. |
invalid_test_outcome | 400 | Unbekannter Wert in test_outcome. |
invalid_min_age | 400 bzw. 200 | min_age ist nicht die Zahl 16 oder 18. Auch "18" als Text, 17, 21, null und 0 fallen darunter. Bei POST /verifications als 400, bei POST /proofs/verify als error_code im 200er-Rumpf. |
simulation_mode | 503 | Der Dienst ist ohne angebundene Prüfstelle konfiguriert und stellt deshalb keine Nachweise aus. Auf verify.edelbyte.ch tritt das nicht auf. |
verifier_unavailable | 502 | Die Prüfstelle ist nicht erreichbar. |
Ein Sonderfall, damit Sie ihn nicht suchen: Beim Einlösen über /api/v1/proofs/verify gibt es für eine zu niedrige Altersstufe kein 4xx. Sobald der Schlüssel angenommen ist, antwortet dieser Aufruf immer mit 200 — die Absage steht als valid: false im Rumpf, zusammen mit required_min_age.
error_code beim Einlösen. Auch eine unbrauchbare Altersgrenze führt hier zu keinem 4xx: Ein min_age: 17 kommt als 200 zurück, mit valid: false und error_code "invalid_min_age". min_age und required_min_age stehen dann beide auf null — es wurde gar nichts geprüft. invalid_min_age gibt es also an beiden Endpunkten, nur in verschiedener Gestalt.
Das Feld error_code steht in dieser Antwort nur im Fehlerfall. Ein regulärer Einlösevorgang — gültig wie ungültig — liefert es gar nicht mit. Lesen Sie es deshalb als «vorhanden heisst: Ihre Einbindung ist zu reparieren», nicht als Feld, das Sie immer erwarten dürfen. Und behandeln Sie diesen Fall wie jede andere Absage: blockieren.
Webhook
Der Stand lässt sich abfragen — er kommt aber auch von selbst, wenn Sie das wollen. So sparen Sie sich die Abfrageschleife auf Ihrem Server und erfahren das Ergebnis, sobald es feststeht.
Eingerichtet wird der Webhook mit Adresse und Geheimnis. Die Adresse muss https sein. Zugestellt wird als POST mit JSON-Rumpf. Diese Einstellung nehmen wir für Sie vor — sagen Sie uns Adresse und gewünschte Grenze. Einen Selbstbedienungszugang gibt es heute noch nicht. So erreichen Sie uns.
POST /ihr/endpunkt
X-EdelVerify-Event: evt_…
X-EdelVerify-Signature: t=1786742825,v1=9f86d081…
{ "id": "evt_…", "type": "verification.completed",
"created_at": "2026-08-15T09:12:44.000Z",
"verification_id": "ver_…", "mode": "test",
"status": "SUCCESS", "min_age": 16, "age_ok": true, "over_18": false,
"method": "eid",
"reference": "warenkorb-4711", "error_code": null }Es gibt genau einen Ereignistyp — und er heisst nicht «bestanden»
type ist immer verification.completed. Einen zweiten Typ gibt es nicht, und einen mit «success» oder «succeeded» im Namen hat es nie gegeben. Wer auf einen solchen filtert, verarbeitet niemals etwas.
«Completed» heisst abgeschlossen, nicht «bestanden». Dieselbe Meldung kommt bei SUCCESS, bei FAILED und bei EXPIRED. Wer aus dem blossen Eingang einer Meldung «alt genug» schliesst, gibt bei einer fehlgeschlagenen Prüfung frei. Massgeblich ist status zusammen mit age_ok und min_age: status muss SUCCESS sein, age_ok true, und min_age sagt, gegen welche Grenze das gilt.
created_at ist ein ISO-Zeitpunkt mit Millisekunden — 2026-08-15T09:12:44.000Z, nicht …:44Z. Ein Parser, der auf Sekundengenauigkeit festgenagelt ist, stolpert darüber.
X-EdelVerify-Event ist die Kennung der Zustellung — merken Sie sie sich und verarbeiten Sie dieselbe Kennung nur einmal. Wiederholungen sind normal, doppelte Buchungen nicht.
Signatur prüfen. X-EdelVerify-Signature trägt zwei Werte: t ist der Zeitpunkt in Unix-Sekunden, v1 ein HMAC-SHA256 in Hex über die Zeichenfolge "<t>.<roher Rumpf>", mit Ihrem Geheimnis als Schlüssel.
- Rechnen Sie gegen den rohen Rumpf, so wie er ankam. Wer erst nach JSON wandelt und wieder zurück, bekommt eine andere Zeichenfolge und damit nie eine gültige Signatur.
- Vergleichen Sie zeitkonstant (
hash_equals,crypto.timingSafeEqual), nicht mit==. - Weisen Sie ab, was älter oder neuer als 300 Sekunden ist. Das schliesst die Wiedereinspielung mitgeschnittener Zustellungen aus.
Der Nachweis ist nicht dabei
Im Rumpf steht kein proof, und das bleibt so. Ein Nachweis, der ungefragt an eine Adresse geht, ist ein Nachweis, der abhandenkommen kann. Holen Sie ihn nach der Meldung mit Ihrem sk_-Schlüssel über GET /api/v1/verifications/:id ab.
Und der Webhook bleibt ein Hinweis, kein Riegel. Der Riegel ist und bleibt /api/v1/proofs/verify vor dem Bestellabschluss. Wer eine Bestellung allein aufgrund einer eingegangenen Meldung freigibt, hat die Schranke an die falsche Stelle gehängt.
Die Meldung entsteht beim Abfragen — nicht von allein
Es gibt heute keinen Taktgeber, der Prüfungen im Hintergrund nachschaut. Der Abschluss einer Prüfung wird in dem Augenblick festgestellt, in dem jemand ihren Stand abfragt — über GET /api/v1/verifications/:id. Erst dabei entsteht die Meldung.
Das heisst im Klartext: Schliesst Ihre Kundschaft den Tab, fragt niemand mehr nach. Die Prüfung bleibt offen, und es entsteht gar keine Meldung — auch keine über den Verfall. Ausgerechnet der Fall, für den ein Webhook gedacht ist, ist der, in dem er nicht kommt.
Rechnen Sie deshalb nicht damit, dass eine ausbleibende Meldung «noch offen» bedeutet. Fragen Sie den Stand für eine liegen gebliebene Bestellung einmal serverseitig nach — ein einziger GET mit Ihrem sk_-Schlüssel genügt, und er löst zugleich die Meldung aus, falls sie noch aussteht.
Wiederholungen. Nach 30 Sekunden, 2 Minuten, 10 Minuten, 1 Stunde und 6 Stunden — höchstens sechs Versuche. Als angenommen zählt nur eine 2xx-Antwort; Weiterleitungen werden nicht verfolgt, und nach 10 Sekunden ohne Antwort brechen wir ab. Antworten Sie deshalb sofort mit 200 und arbeiten Sie danach.
Stand je Shop-System
| System | Stand | Weg |
|---|---|---|
| WooCommerce | verfügbar | Plugin mit Einstellungsseite und Verbindungstest. Der Riegel sitzt serverseitig in woocommerce_checkout_process und in der Store-API, greift also auch im Block-Checkout. Läuft im Demo-Shop, den wir selbst betreiben. Warenkorb, Kasse und der Ausweis-Weg sind von aussen nachgemessen — bis zum signierten Anfrageobjekt. Archiv · Anleitung · Prüfplan · Vorführladen |
| Shopware 6 | verfügbar | Plugin mit CartValidator als Riegel — greift damit auch bei direktem Zugriff auf die Store-API. Die Warenkorb-Schublade führt auf die Warenkorbseite, weil Shopware sie per AJAX einsetzt und Skripte darin nicht ausführt. Läuft in einem Shopware 6.6.10.3, das wir selbst betreiben. Nachgemessen sind Warenkorb, Warenkorb-Schublade, Kasse und der Ausweis-Weg bis zum QR-Code. Archiv · Anleitung · Prüfplan · Vorführladen |
| Magento 2 | verfügbar | Modul mit Plugin auf CartManagementInterface::placeOrder — greift für Luma, REST und PWA gleichermassen. Läuft in einem Magento 2.4.8-p5, das wir selbst betreiben. Nachgemessen sind Warenkorb, Kasse und der Ausweis-Weg bis zum QR-Code. Archiv · Anleitung · Prüfplan · Vorführladen |
| Shopify | gebaut, nicht lauffähig | Theme App Extension und Webhook-Prüfung. Die harte Sperre vor Bestellabschluss läuft über eine Cart-and-Checkout-Validation-Function — auf jedem Shopify-Tarif, sobald die App aus dem App Store kommt. Bis dahin wird jede Bestellung nachgelagert geprüft und ohne Nachweis vom Versand angehalten. Die Altersprüfung selbst läuft — im Shopify-Vorführladen, über ein Theme-Schnipsel, der Ausweis-Weg nachgemessen. Was fehlt, ist die App im Shopify App Store; bis sie dort steht, richten wir den Shop für Sie ein. Archiv · Anleitung · Prüfplan · Vorführladen (Passwort: edelverify — Shopify lässt bei Entwicklungs-Shops keine offene Vorführung zu.) |
| Alles andere | sofort | Die Schnittstelle ist plattformneutral. Für jedes System, das eine Zeile JavaScript und einen Serveraufruf erlaubt, brauchen Sie kein Plugin. |
Was «verfügbar» hier heisst — und was nicht
Verfügbar heisst: Das Plugin läuft in einem echten Shop dieser Plattform, den wir selbst betreiben, und die Kette ist von aussen nachgemessen — Warenkorb, Riegel, gestartete Prüfung, beide Prüfwege bis zum QR-Code. Nicht gemessen ist, was Ihr Theme, Ihre Zahlungsart und Ihre Erweiterungen daraus machen. Der erste Shop je Plattform ist ein Pilot, und wir behandeln ihn auch so.
Was das Messen wert ist, zeigt Shopify: Dort fiel beim Nachmessen auf, dass der Stand-Abruf den Nachweis gar nicht erst anforderte und die Gegenstelle deshalb ausnahmslos mit 409 antwortete. Behoben — aber gefunden hat es eine Messung, nicht das Lesen.
Jedes Paket bringt einen Prüfplan mit, der offen auflistet, was offen ist, samt dem Befehl zum Nachprüfen — hier sind alle vier: WooCommerce · Shopware 6 · Magento 2 · Shopify.
Was heute noch nicht geht
Damit Sie es von uns erfahren und nicht nach der Installation:
Die Technik läuft — für die E-ID fehlt Ihrer Kundschaft noch der Nachweis
Die Kette steht: Ein Live-Schlüssel stellt echte Nachweise aus, die Prüfstelle ist angebunden, und im Demo-Shop können Sie den ganzen Ablauf durchspielen.
Was fehlt, ist die andere Seite. Die E-ID-Anbindung ist gebaut und läuft gegen die Testumgebung des Bundes; unser Verifier steht im Vertrauensregister. Für Ihre Kundschaft ist das trotzdem kein Prüfweg, solange der Bund nicht produktiv ausgibt — Termin offen, vom Bund am 30. Juni 2026 verschoben. Deshalb wird der E-ID-Weg gar nicht erst angeboten: Er ist abgeschaltet, die Prüfung startet direkt mit dem Ausweis, und Ihre Kundschaft sieht keinen Knopf, an dem sie scheitern könnte. Zurück kommt er als Schalter, nicht als Umbau — an einem Tag, ohne Änderung an Ihrer Einbindung. Der Chip-Weg trägt heute — die App dafür steht im Play Store, die iPhone-Fassung fehlt noch.
Bauen und prüfen Sie so lange mit Testschlüsseln. Am Tag der Umstellung tauschen Sie zwei Zeichenfolgen aus, sonst nichts.
- Genau zwei Altersstufen. 16 und 18 — die beiden, die das Schweizer Recht kennt. Ein anderer Wert in
min_agewird abgewiesen, nicht gerundet. Brauchen Sie eine weitere Schwelle, sagen Sie es uns. - Die 16er-Stufe ist gebaut, aber noch nicht gegen einen echten Nachweis gemessen. In der Schnittstelle und in allen Paketen ist sie fertig, und im Testbetrieb ist die ganze Kette durchgängig belegt — Prüfung ab 16, Nachweis ab 16, Einlösen ab 16, und die Absage, wenn ein 16er-Nachweis auf Ware ab 18 trifft. Gegen einen echten Nachweis gemessen ist bisher aber nur die 18er-Frage. Ob die E-ID des Bundes das Merkmal
age_over_16überhaupt führt, prüfen wir vor dem ersten 16er-Piloten nach. Bauen Sie ruhig schon dagegen; setzen Sie einen 16er-Livebetrieb erst an, wenn wir das bestätigt haben. - Ein Nachweis gilt bei einem Shop. Wer mehrere Shops betreibt, braucht je Shop ein eigenes Schlüsselpaar; die Kundschaft weist sich in jedem einmal aus. Das ist datenschutzrechtlich sauber, aber es ist eine Entscheidung und kein Versehen — sagen Sie uns, wenn Sie es anders brauchen.
- Die Schweizer Identitätskarte hat keinen Chip — dafür gibt es die dritte Stufe. Für sie liest die App die maschinenlesbaren Zeilen am Rand mit der Kamera (
ausweis_mrz). Diese Stufe belegt weniger als der Chip: Ein Foto der Rückseite genügt ihr. Sie ist deshalb je Konto ab Werk abgeschaltet — Sie schalten sie in den Einstellungen frei, undrequired_methodin jeder Einlösung sagt Ihnen, was gerade gilt. Die biometrische Identitätskarte ist ab 2. November 2026 beantragbar und bleibt neben der chiplosen freiwillig.
Fehlt Ihnen etwas davon dringend? Schreiben Sie uns — die Reihenfolge richtet sich danach, was Shops wirklich blockiert.