Ir al contenido

Socios sin código fiscal

Ver como Markdown

Para inscribirse en una asociación no hace falta un código fiscal italiano (codice fiscale). Lo que hace falta es que la persona esté identificada, y en Vimine lo está de una de estas dos formas:

  • con un código fiscal, o
  • con sus datos de nacimiento: dob + birthplace + birth_country (ISO 3166-1 alpha-2).

Nunca sin ninguno de los dos. El resto de esta guía es lo que cambia, campo por campo, para una integración que inscribe a personas — estudiantes de intercambio, voluntarios recién llegados, socios que viven en el extranjero.

POST /v1/enroll y POST /v1/signup aceptan los mismos campos:

Campo
codicefiscale opcional. Cuando está presente, se valida y se coteja con el nombre, los apellidos, la fecha y el lugar de nacimiento
dob fecha de nacimiento, YYYY-MM-DD
birthplace el comune (el municipio) para quien nació en Italia; la ciudad, como texto libre, para quien nació en el extranjero
birth_country país de nacimiento, dos letras (IT, FR, SN…)
gender solo demográfico: ya no se coteja con el código
// Sin código fiscal: fecha, lugar y país de nacimiento
await 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 }
});

En /v1/enroll, sin código, cada dato de nacimiento que falte es un 422 validation_failed con una entrada en errors[]:

{ "code": "validation_failed", "errors": [{ "field": "birth_country", "code": "required" }] }

/v1/signup solo crea la cuenta: ahí los datos de nacimiento siguen siendo opcionales, y harán falta cuando la persona solicite un carné.

Nacidos en el extranjero: envía birth_country

Sección titulada «Nacidos en el extranjero: envía birth_country»

El código fiscal de una persona nacida en Italia contiene el comune de nacimiento; el de una persona nacida en el extranjero contiene solo el país. Por eso, para estas personas el cotejo compara birth_country y trata birthplace — la ciudad — como texto libre. Enviar birth_country es lo que permite que una persona nacida en el extranjero con un código válido pase la comprobación: sin él, «Lyon» se buscaría entre los comuni italianos y el código resultaría incoherente. (Un formulario que hasta ahora enviaba el nombre italiano del país como lugar de nacimiento — birthplace: 'Francia' — sigue pasando; birth_country es la forma preferible.)

Lo mismo vale para la comprobación pública, que ahora dice también lo que contiene el código:

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 y birth_country se leen del propio código: puedes usarlos para rellenar el formulario de antemano. Este endpoint sigue comparando gender, cuando lo envías; la inscripción y el perfil no.

Un código que no coincide, y la confirmación

Sección titulada «Un código que no coincide, y la confirmación»

Un código mal escrito (estructura o carácter de control) es invalid_codicefiscale: hay que corregirlo, nunca se puede confirmar. En cambio, un código bien formado que no coincide con los datos introducidos responde 422 con una entrada más completa:

{
"code": "validation_failed",
"errors": [{
"field": "codicefiscale",
"code": "codicefiscale_mismatch",
"mismatches": ["place"],
"hints": [],
"confirmable": true
}]
}
  • mismatches — lo que no coincide: lastName, firstName, date, place;
  • hints — names_swapped cuando el código coincide al intercambiar apellidos y nombre: ofrecer el intercambio suele bastar;
  • confirmable — si la persona puede confirmar que ese es el código de su tarjeta sanitaria. Ocurre: comuni que ya no existen, transliteraciones, nombres registrados en otro orden.

Cuando confirmable es true, pregunta a la persona y repite la solicitud con codicefiscale_confirmed: true. Cuando no coinciden ni el nombre, ni los apellidos, ni la fecha, ya nada vincula ese código con esa persona: confirmable es false y la única salida es corregirlo.

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 });
}
}

No envíes codicefiscale_confirmed por iniciativa propia: es una declaración de la persona, y se registra como tal.

Quien se inscribió sin código puede añadirlo cuando lo tenga, desde su propio perfil:

const me = await vimine.me.update({ codicefiscale: 'DPNMRA85C50Z110U' });
me.codicefiscale_check; // 'matched'

PATCH /v1/me acepta birth_country y codicefiscale_confirmed, que es solo de escritura; codicefiscale también puede volver a ponerse a null. GET /v1/me dice cómo está identificada la persona:

codicefiscale_check
matched un código fiscal que coincide con los datos de nacimiento de la persona
mismatch_confirmed un código que no coincide, confirmado por la persona
absent ningún código: la identifican la fecha, el lugar y el país de nacimiento
null todavía no identificada: no puede solicitar un carné

matched significa coherente, no verificado en el registro tributario: un código fiscal sigue siendo un dato declarado.

Una cuenta puede existir sin estar identificada — por ejemplo, alguien que se registró solo para iniciar sesión. Cuando esa persona solicita un carné, la API lo dice e indica lo que falta:

  • POST /v1/me/membership → 422 identification_required, con errors[] = los datos de nacimiento que faltan ({ field: 'birthplace', code: 'required' }…). Envía a la persona a completar su perfil con PATCH /v1/me (permiso profile:write) y repite la solicitud.
  • POST /v1/enroll/confirm — el enlace «confirma tu solicitud» que recibe el titular de una cuenta existente → 409 identification_required, con el mismo errors[]. Pide los datos de nacimiento en la página y vuelve a enviar el token con identification:
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? } }

Los datos de nacimiento viajan en el cuerpo de la petición, nunca en el enlace: en el enlace nunca hay nada personal. identification solo completa los campos vacíos del perfil, no sobrescribe lo que ya hay; si los datos no cuadran, la respuesta es un 422 validation_failed como el de arriba.

La admisión no cambia: los pending_reasons son los que diga el modelo de admisión de la asociación, para todo el mundo (consulta Admisión y activación).

En la entrada: la comprobación de identidad

Sección titulada «En la entrada: la comprobación de identidad»

Un código fiscal que coincide con los datos de nacimiento se puede contrastar con ellos; los datos de nacimiento solos, o un código confirmado por la persona, no. Para estos socios, la asociación mira un documento una vez, la primera vez que la persona se presenta. Quien integra un escáner lo ve en POST /v1/checkins (permiso checkins:write), en las respuestas para un carné:

const r = await vimineServer.checkins.create('vmt_…');
// { kind: 'card', verdict: 'valid', …, identity_check: 'pending' }
if (r.identity_check === 'pending') show('Primera entrada: pide un documento');
identity_check
pending el socio no tiene un código fiscal comprobable y nadie de la asociación ha mirado todavía un documento: muéstralo a quien atiende la entrada
verified alguien de la asociación ha mirado un documento
flagged alguien lo ha mirado y no coincidía: se encarga la secretaría
null nada que comprobar

Es una nota, no forma parte de verdict y no restringe nada: un carné valid con identity_check: 'pending' entra. El resultado se registra desde la consola de la asociación, no desde la API. La verificación pública GET /v1/verify/{card_token} nunca la incluye: quien comprueba un carné desde fuera solo ve el estado y la caducidad.

Algunas asociaciones guardan la dirección de sus socios en su libro de socios, otras no. La decisión es de la asociación y vale para todos los socios o para ninguno; el perfil público la declara:

GET https://api.vimine.network/v1/aps/{slug}
→ { "aps": { …, "member_address": "optional" } }
member_address
none no la pidas: un address enviado de todas formas no se guarda
optional pídela, sin hacerla obligatoria
required sin address, la inscripción responde 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 y city son obligatorios dentro de address; kind es residence (el valor por defecto) o domicile, cuando difiere de la residencia; country es IT si se omite; province solo afecta a las direcciones italianas. /v1/signup no tiene address: la dirección pertenece a la inscripción, no a la cuenta.

No existe la opción «código fiscal obligatorio». Una asociación no puede exigir un código fiscal a todos los solicitantes: quien no lo tiene se identifica con sus datos de nacimiento, en todas partes. Si tu formulario lo hace obligatorio, es una decisión de tu formulario — y deja fuera a personas que la asociación podría acoger.

Todo es aditivo: un formulario que siempre envía un código fiscal sigue funcionando sin cambios. Lo que una integración existente puede notar:

  • codicefiscale ya no es obligatorio en POST /v1/enroll; sin código, hacen falta dob, birthplace y birth_country (422 required por cada uno que falte);
  • nuevos campos opcionales birth_country, codicefiscale_confirmed (enroll, signup, PATCH /v1/me) y address (enroll);
  • gender ya no se coteja con el código: ya no llega un 422 solo por el sexo;
  • un código que no coincide sigue respondiendo codicefiscale_mismatch, ahora con hints y confirmable junto a mismatches; un código mal formado sigue siendo invalid_codicefiscale;
  • GET/PATCH /v1/me tienen ahora un esquema declarado (Me), con birth_country y codicefiscale_check;
  • un error nuevo, identification_required: 422 en POST /v1/me/membership, 409 en POST /v1/enroll/confirm (que acepta identification en el cuerpo);
  • POST /v1/validate/fiscal-code acepta country y responde también hints, birth_date, birth_country; error es invalid, mismatch o null;
  • POST /v1/checkins añade identity_check a las respuestas para un carné; GET /v1/verify/{card_token} sigue igual;
  • el perfil público añade aps.member_address.