Soci senza codice fiscale
Per diventare socio di un’associazione non serve un codice fiscale italiano. Quello che serve è che la persona sia identificata, e su Vimine lo è in uno di due modi:
- con un codice fiscale, oppure
- con i suoi dati di nascita:
dob+birthplace+birth_country(ISO 3166-1 alpha-2).
Mai nessuno dei due. Il resto di questa guida è che cosa cambia, campo per campo, per un’integrazione che iscrive persone — studenti in scambio, volontari arrivati da poco, soci che vivono all’estero.
Identificare una persona
Sezione intitolata “Identificare una persona”POST /v1/enroll e POST /v1/signup accettano gli stessi campi:
| Campo | |
|---|---|
codicefiscale |
facoltativo. Se c’è, viene validato e confrontato con nome, cognome, data e luogo di nascita |
dob |
data di nascita, YYYY-MM-DD |
birthplace |
il comune per chi è nato in Italia; la città, a testo libero, per chi è nato all’estero |
birth_country |
Stato di nascita, due lettere (IT, FR, SN…) |
gender |
solo statistico: non viene più confrontato con il codice |
// Senza codice fiscale: data, luogo e Stato di nascitaawait vimineServer.enroll({ email: 'marie.dupont@example.org', first_name: 'Marie', last_name: 'Dupont', dob: '1985-03-10', birthplace: 'Lyon', birth_country: 'FR', accept_statuto: { version: statuto.version, sha256: statuto.sha256 }});Su /v1/enroll, senza codice, ogni dato che manca è un 422 validation_failed con una voce in errors[]:
{ "code": "validation_failed", "errors": [{ "field": "birth_country", "code": "required" }] }/v1/signup crea solo l’account: lì i dati di nascita restano facoltativi, e serviranno quando la persona chiederà
una tessera.
Nati all’estero: invia birth_country
Sezione intitolata “Nati all’estero: invia birth_country”Il codice fiscale di chi è nato in Italia contiene il comune di nascita; quello di chi è nato all’estero contiene
solo lo Stato. Per questo il confronto, per loro, guarda birth_country e tratta birthplace — la città — come
testo libero. Inviare birth_country è ciò che fa passare una persona nata all’estero con un codice valido: senza,
«Lyon» verrebbe cercata tra i comuni italiani e il codice risulterebbe incoerente. (Un modulo che finora inviava il
nome dello Stato come luogo di nascita — birthplace: 'Francia' — continua a passare; birth_country è la forma da
preferire.)
Lo stesso vale per il controllo pubblico, che ora dice anche che cosa il codice contiene:
const r = await publicApi().validateFiscalCode({ code: 'DPNMRA85C50Z110U', first_name: 'Marie', last_name: 'Dupont', date: '1985-03-10', place: 'Lyon', country: 'FR'});// { valid: true, error: null, mismatches: [], hints: [], birth_date: '1985-03-10', birth_country: 'FR' }birth_date e birth_country sono letti dal codice stesso: puoi usarli per precompilare il modulo. Questo endpoint
confronta ancora gender, se lo invii; l’iscrizione e il profilo no.
Un codice che non torna, e la conferma
Sezione intitolata “Un codice che non torna, e la conferma”Un codice scritto male (struttura o carattere di controllo) è invalid_codicefiscale: va corretto, non si può
confermare. Un codice ben formato che non concorda con i dati inseriti risponde invece 422 con una voce più
ricca:
{ "code": "validation_failed", "errors": [{ "field": "codicefiscale", "code": "codicefiscale_mismatch", "mismatches": ["place"], "hints": [], "confirmable": true }]}mismatches— che cosa non concorda:lastName,firstName,date,place;hints—names_swappedquando il codice torna scambiando nome e cognome: di solito basta proporre lo scambio;confirmable— se la persona può confermare che quello è il codice della sua tessera sanitaria. Succede davvero: comuni soppressi, traslitterazioni, nomi registrati in un altro ordine.
Quando confirmable è true, chiedilo alla persona e ripeti la richiesta con codicefiscale_confirmed: true.
Quando nome, cognome e data non concordano tutti insieme, nulla lega più quel codice a quella persona:
confirmable è false e l’unica strada è correggere.
import { VimineError } from '@vimine/sdk/server';
try { await vimineServer.enroll(input);} catch (err) { const entry = err instanceof VimineError && err.errors?.find((e) => e.code === 'codicefiscale_mismatch'); if (!entry) throw err; if (entry.confirmable && (await askThePerson(entry.mismatches, entry.hints))) { await vimineServer.enroll({ ...input, codicefiscale_confirmed: true }); }}Non inviare codicefiscale_confirmed di tua iniziativa: è una dichiarazione della persona, e viene registrata come
tale.
Aggiungere il codice più tardi
Sezione intitolata “Aggiungere il codice più tardi”Chi si è iscritto senza codice può aggiungerlo quando lo ottiene, dal proprio profilo:
const me = await vimine.me.update({ codicefiscale: 'DPNMRA85C50Z110U' });me.codicefiscale_check; // 'matched'PATCH /v1/me accetta birth_country e, solo in scrittura, codicefiscale_confirmed; codicefiscale si può anche
riportare a null. GET /v1/me dice come la persona è identificata:
codicefiscale_check |
|
|---|---|
matched |
un codice fiscale che concorda con i dati della persona |
mismatch_confirmed |
un codice che non concorda, confermato dalla persona |
absent |
nessun codice: la identificano data, luogo e Stato di nascita |
null |
non ancora identificata: non può chiedere una tessera |
matched vuol dire coerente, non verificato presso l’anagrafe tributaria: il codice fiscale resta un dato
dichiarato.
identification_required
Sezione intitolata “identification_required”Un account può esistere senza essere identificato — chi si è registrato solo per accedere, per esempio. Quando una persona così chiede una tessera, l’API lo dice e nomina che cosa manca:
POST /v1/me/membership→422 identification_required, conerrors[]= i dati mancanti ({ field: 'birthplace', code: 'required' }…). Manda la persona a completare il profilo conPATCH /v1/me(permessoprofile:write) e ripeti la richiesta.POST /v1/enroll/confirm— il link «conferma la richiesta» che riceve il titolare di un account esistente →409 identification_required, stessoerrors[]. Chiedi i dati nella pagina e invia di nuovo il token conidentification:
await publicApi().confirmEnrollment(token, { dob: '1985-03-10', birthplace: 'Lyon', birth_country: 'FR' });// POST /v1/enroll/confirm { token, identification: { dob, birthplace, birth_country, codicefiscale?, codicefiscale_confirmed? } }I dati viaggiano nel corpo della richiesta, mai nel link: nel link non c’è nulla di personale. identification
completa solo i campi vuoti del profilo, non sovrascrive quelli che ci sono; se non regge, la risposta è un
422 validation_failed come sopra.
L’ammissione non cambia: pending_reasons resta quello che dice il modello di ammissione dell’associazione, per
chiunque (vedi Ammissione e attivazione).
All’ingresso: il controllo d’identità
Sezione intitolata “All’ingresso: il controllo d’identità”Un codice fiscale che concorda con i dati si può riscontrare; i dati di nascita da soli, o un codice confermato dalla
persona, no. Per questi soci l’associazione guarda un documento una volta, la prima volta che la persona è
presente. Chi integra uno scanner lo vede in POST /v1/checkins (permesso checkins:write), nelle risposte per una
tessera:
const r = await vimineServer.checkins.create('vmt_…');// { kind: 'card', verdict: 'valid', …, identity_check: 'pending' }if (r.identity_check === 'pending') show('Primo ingresso: chiedi un documento');identity_check |
|
|---|---|
pending |
il socio non ha un codice fiscale verificabile e nessuno dell’associazione ha ancora visto un documento: mostralo a chi è all’ingresso |
verified |
qualcuno dell’associazione ha visto un documento |
flagged |
qualcuno l’ha visto e non corrispondeva: se ne occupa la segreteria |
null |
niente da controllare |
È una nota, non fa parte di verdict e non limita nulla: una tessera valid con identity_check: 'pending'
entra. L’esito si registra dalla console dell’associazione, non dall’API. La verifica pubblica
GET /v1/verify/{card_token} non lo riporta mai: chi controlla una tessera da fuori vede solo stato e scadenza.
L’indirizzo
Sezione intitolata “L’indirizzo”Alcune associazioni tengono l’indirizzo dei soci nel proprio libro, altre no. La scelta è dell’associazione e vale per tutti i soci o per nessuno; il profilo pubblico la dichiara:
GET https://api.vimine.network/v1/aps/{slug}→ { "aps": { …, "member_address": "optional" } }member_address |
|
|---|---|
none |
non chiederlo: un address inviato comunque non viene conservato |
optional |
chiedilo, senza obbligo |
required |
senza address l’iscrizione risponde 422 con { field: 'address', code: 'required' } |
await vimineServer.enroll({ …, address: { kind: 'residence', line: 'Via Roma 1', postal_code: '20121', city: 'Milano', province: 'MI', country: 'IT' }});line e city sono obbligatori dentro address; kind vale residence (predefinito) o domicile, quando è
diverso dalla residenza; country è IT se omesso; province riguarda solo gli indirizzi italiani. /v1/signup
non ha address: l’indirizzo appartiene all’adesione, non all’account.
Un’associazione non può pretendere il codice
Sezione intitolata “Un’associazione non può pretendere il codice”Non esiste un’impostazione «codice fiscale obbligatorio». Un’associazione non può chiedere il codice fiscale a ogni persona che fa domanda: chi non ce l’ha si identifica con i dati di nascita, ovunque. Se il tuo modulo lo rende obbligatorio, è una scelta del tuo modulo — e lascia fuori persone che l’associazione potrebbe accogliere.
Cosa è cambiato (versione 2026-09-19)
Sezione intitolata “Cosa è cambiato (versione 2026-09-19)”Tutto additivo: un modulo che invia sempre un codice fiscale continua a funzionare senza toccare nulla. Quello che un’integrazione esistente può notare:
codicefiscalenon è più obbligatorio inPOST /v1/enroll; senza codice servonodob,birthplaceebirth_country(422requiredsu ciascuno che manca);- nuovi campi facoltativi
birth_country,codicefiscale_confirmed(enroll, signup,PATCH /v1/me) eaddress(enroll); gendernon viene più confrontato con il codice: un422per il solo sesso non arriva più;- un codice che non concorda risponde sempre
codicefiscale_mismatch, ora conhintseconfirmableaccanto amismatches; un codice malformato restainvalid_codicefiscale; GET/PATCH /v1/mehanno ora uno schema dichiarato (Me), conbirth_countryecodicefiscale_check;- nuovo errore
identification_required:422suPOST /v1/me/membership,409suPOST /v1/enroll/confirm(che accettaidentificationnel corpo); POST /v1/validate/fiscal-codeaccettacountrye risponde anchehints,birth_date,birth_country;errorvaleinvalid,mismatchonull;POST /v1/checkinsaggiungeidentity_checkalle risposte per una tessera;GET /v1/verify/{card_token}resta com’era;- il profilo pubblico aggiunge
aps.member_address.