VimineServer
import { VimineServer } from '@vimine/sdk/server';const vimineServer = new VimineServer({ clientId: 'vmc_…', clientSecret: process.env.VIMINE_SECRET });For the association’s own systems: a confidential client that authenticates with client_credentials,
reads card statuses and drives its sandbox. Node ≥ 18. The secret must never reach a browser.
Options
Section titled “Options”| Option | Type | Default | |
|---|---|---|---|
clientId |
string |
— | required |
clientSecret |
string |
— | required; vms_… or vms_test_… |
scopes |
Scope[] |
all the registered ones | a subset to ask for |
apiUrl |
string |
https://api.vimine.network |
|
fetch |
typeof fetch |
globalThis.fetch |
Methods
Section titled “Methods”token()
Section titled “token()”A client access token (client_credentials, HTTP Basic), cached until 30 seconds before it expires (1 hour);
a single request even under concurrent calls.
request(path, init?)
Section titled “request(path, init?)”An authenticated call with Authorization: Bearer; JSON in and out; errors as
VimineError. A 401 (rotated or revoked credentials) is retried once with a fresh token.
memberships.status(id)
Section titled “memberships.status(id)”Status of one membership of the association, without personal data (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?)
Section titled “signup(input, opts?)”Creates a Vimine account for a person (identity:signup): they receive the mail to confirm the address and pick
a password. Always answers { status: 'accepted' } — whether the address already had an account is not disclosed
to you (its owner is told, by mail). opts.idempotencyKey (generated when absent).
await vimineServer.signup({ email: 'mario.rossi@example.org', first_name: 'Mario', last_name: 'Rossi', phone: '+39 …' });enroll(input, opts?)
Section titled “enroll(input, opts?)”Submits a membership request for a person (enroll:write): a new address gets an account and a pending request;
the owner of an existing account receives a confirmation link instead (nothing is written until they use it).
accept_statuto (the in-force version) is required; so is privacy_notice when the association
publishes a notice to its members (association(slug).privacy_notice): the person reads it on your site and you pass
the version shown. See Server integrations.
The person is identified by codicefiscale or by dob + birthplace + birth_country — never neither (422,
a required entry on each missing particular). A code that disagrees with the particulars is a
codicefiscale_mismatch entry in err.errors, with mismatches, hints and confirmable: when confirmable is
true and the person confirms, repeat with codicefiscale_confirmed: true. address (MemberAddress) when the
association collects its members’ address (aps.member_address). See
Members without a fiscal code.
// with a fiscal codeawait vimineServer.enroll({ ...person, codicefiscale: 'RSSMRA80A01H501U', accept_statuto: { version: 3 }, privacy_notice: { version: 2 } }, { idempotencyKey: 'order-42' });// without one: date, place and country of birthawait vimineServer.enroll({ ...person, dob: '1985-03-10', birthplace: 'Lyon', birth_country: 'FR', accept_statuto: { version: 3 }, privacy_notice: { version: 2 } });checkins.create(token)
Section titled “checkins.create(token)”Records a door check-in from the token read on the QR (checkins:write). A card answers { kind: 'card', verdict, status, membership_id, valid_until, valid_from, identity_check, checked_in_at } — identity_check: 'pending' is a note to show to whoever staffs the gate, it is not part of verdict and it restricts nothing (guide); an event registration’s QR answers { kind: 'registration', verdict, registration_id, event, first, membership_verdict, … } (see Events and registrations).
events
Section titled “events”events.list(params?) · events.get(slug) — the association’s published events, members-only ones included (any client token).
registrations
Section titled “registrations”registrations.listForEvent(slug, { status?, limit?, cursor? }) |
an event’s registrations: id, status, type, membership, check-in — no personal data (registrations:read, plans with API lists) |
registrations.guest(slug, { email, first_name, last_name, registration_type, note? }, opts?) |
registers a guest without an account for a public event; always { status: 'accepted' }; Idempotency-Key generated (see guests) |
memberships.list(params?)
Section titled “memberships.list(params?)”The association’s memberships (memberships:read, plans with lists): { items: [{ id, status, verdict, membership_type, issued_at, valid_until, updated_at }], next_cursor }; params: status, updated_since, limit, cursor.
sandbox.members() · sandbox.reset()
Section titled “sandbox.members() · sandbox.reset()”Test clients only: the synthetic members of the sandbox and the reset (new shared
password, returned once). A production client gets 403.
public
Section titled “public”The public, credential-less endpoints: see publicApi.
An example middleware
Section titled “An example 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; }});