VimineServer
import { VimineServer } from '@vimine/sdk/server';const vimineServer = new VimineServer({ clientId: 'vmc_…', clientSecret: process.env.VIMINE_SECRET });Für die eigenen Systeme des Vereins: ein vertraulicher Client, der sich mit client_credentials authentifiziert,
Ausweisstatus liest und seine Sandbox steuert. Node ≥ 18. Das Secret darf nie in einen Browser gelangen.
Optionen
Abschnitt betitelt „Optionen“| Option | Typ | Standard | |
|---|---|---|---|
clientId |
string |
— | Pflicht |
clientSecret |
string |
— | Pflicht; vms_… oder vms_test_… |
scopes |
Scope[] |
alle registrierten | eine anzufordernde Teilmenge |
apiUrl |
string |
https://api.vimine.network |
|
fetch |
typeof fetch |
globalThis.fetch |
Methoden
Abschnitt betitelt „Methoden“token()
Abschnitt betitelt „token()“Ein Client-Access-Token (client_credentials, HTTP Basic), zwischengespeichert bis 30 Sekunden vor seinem Ablauf (1 Stunde);
eine einzige Anfrage, auch bei gleichzeitigen Aufrufen.
request(path, init?)
Abschnitt betitelt „request(path, init?)“Ein authentifizierter Aufruf mit Authorization: Bearer; JSON hin und zurück; Fehler als
VimineError. Ein 401 (rotierte oder widerrufene Zugangsdaten) wird einmal mit einem frischen Token wiederholt.
memberships.status(id)
Abschnitt betitelt „memberships.status(id)“Status einer Mitgliedschaft des Vereins, ohne personenbezogene Daten (memberships:read):
const s = await vimineServer.memberships.status('membership-uuid');// { id, status: 'active', verdict: 'valid', valid_until: '2027-03-31T22:59:59.000Z', membership_type: { cod: 'ORD' } }signup(input, opts?)
Abschnitt betitelt „signup(input, opts?)“Legt ein Vimine-Konto für eine Person an (identity:signup): Sie erhält die E-Mail, um die Adresse zu bestätigen und ein
Passwort zu wählen. Antwortet immer { status: 'accepted' } — ob die Adresse schon ein Konto hatte, wird Ihnen nicht verraten
(ihr Inhaber erfährt es, per E-Mail). opts.idempotencyKey (wird erzeugt, wenn er fehlt).
await vimineServer.signup({ email: 'mario.rossi@example.org', first_name: 'Mario', last_name: 'Rossi', phone: '+39 …' });enroll(input, opts?)
Abschnitt betitelt „enroll(input, opts?)“Stellt einen Beitrittsantrag für eine Person (enroll:write): Eine neue Adresse erhält ein Konto und einen ausstehenden Antrag;
der Inhaber eines bestehenden Kontos erhält stattdessen einen Bestätigungslink (nichts wird geschrieben, bis er ihn verwendet).
accept_statuto (die geltende Version) ist Pflicht; ebenso privacy_notice, wenn der Verein
Datenschutzhinweise für seine Mitglieder veröffentlicht (association(slug).privacy_notice): Die Person liest sie auf Ihrer Website, und Sie übergeben
die gezeigte Version. Siehe Server-Integrationen.
Die Person wird über codicefiscale oder über dob + birthplace + birth_country identifiziert — nie über keins von beidem (422,
ein Eintrag required für jede fehlende Geburtsangabe). Eine Steuernummer, die nicht zu den Geburtsdaten passt, ist ein
Eintrag codicefiscale_mismatch in err.errors, mit mismatches, hints und confirmable: Ist confirmable gleich
true und bestätigt die Person, wiederholen Sie mit codicefiscale_confirmed: true. address (MemberAddress), wenn der
Verein die Adresse seiner Mitglieder erfasst (aps.member_address). Siehe
Mitglieder ohne Steuernummer.
// mit einer Steuernummerawait vimineServer.enroll({ ...person, codicefiscale: 'RSSMRA80A01H501U', accept_statuto: { version: 3 }, privacy_notice: { version: 2 } }, { idempotencyKey: 'order-42' });// ohne: Geburtsdatum, Geburtsort und Geburtslandawait vimineServer.enroll({ ...person, dob: '1985-03-10', birthplace: 'Lyon', birth_country: 'FR', accept_statuto: { version: 3 }, privacy_notice: { version: 2 } });checkins.create(token)
Abschnitt betitelt „checkins.create(token)“Erfasst einen Check-in am Einlass aus dem vom QR-Code gelesenen Token (checkins:write). Ein Ausweis antwortet { kind: 'card', verdict, status, membership_id, valid_until, valid_from, identity_check, checked_in_at } — identity_check: 'pending' ist ein Hinweis für die Person am Einlass, nicht Teil von verdict, und schränkt nichts ein (Anleitung); der QR-Code einer Veranstaltungsanmeldung antwortet { kind: 'registration', verdict, registration_id, event, first, membership_verdict, … } (siehe Veranstaltungen und Anmeldungen).
events.list(params?) · events.get(slug) — die veröffentlichten Veranstaltungen des Vereins, einschließlich derer nur für Mitglieder (jedes Client-Token).
registrations
Abschnitt betitelt „registrations“registrations.listForEvent(slug, { status?, limit?, cursor? }) |
die Anmeldungen einer Veranstaltung: ID, Status, Art, Mitgliedschaft, Check-in — keine personenbezogenen Daten (registrations:read, Tarife mit API-Listen) |
registrations.guest(slug, { email, first_name, last_name, registration_type, note? }, opts?) |
meldet einen Gast ohne Konto zu einer öffentlichen Veranstaltung an; immer { status: 'accepted' }; Idempotency-Key wird erzeugt (siehe Gäste) |
memberships.list(params?)
Abschnitt betitelt „memberships.list(params?)“Die Mitgliedschaften des Vereins (memberships:read, Tarife mit Listen): { items: [{ id, status, verdict, membership_type, issued_at, valid_until, updated_at }], next_cursor }; params: status, updated_since, limit, cursor.
sandbox.members() · sandbox.reset()
Abschnitt betitelt „sandbox.members() · sandbox.reset()“Nur für Test-Clients: die synthetischen Mitglieder der Sandbox und das Zurücksetzen (neues gemeinsames
Passwort, einmal zurückgegeben). Ein Production-Client erhält 403.
Die öffentlichen Endpunkte ohne Zugangsdaten: siehe publicApi.
Ein Beispiel-Middleware
Abschnitt betitelt „Ein Beispiel-Middleware“import express from 'express';import { VimineServer, VimineError } from '@vimine/sdk/server';
const vimineServer = new VimineServer({ clientId: process.env.VIMINE_CLIENT_ID, clientSecret: process.env.VIMINE_SECRET });const app = express();
app.get('/cards/:id/status', async (req, res) => { try { const { status, verdict, valid_until } = await vimineServer.memberships.status(req.params.id); res.json({ status, verdict, valid_until }); } catch (err) { if (err instanceof VimineError && err.code === 'not_found') return res.status(404).end(); throw err; }});