Personas
Las personas son el recurso principal del registro.Visibilidad publica
El registro distingue entre personas del directorio publico y personas privadas. Las consultas de personas exponen las publicas: una persona privada no aparece enGET /persons, y GET /persons/{person_id} responde 404, igual que sus
endpoints de foto, informacion de comunidad y reportes. El detalle de una
revision de duplicados que contiene una persona privada tambien responde 404.
Una actualizacion que vuelve privada a una persona devuelve el resultado una vez;
las consultas posteriores ya no permiten acceder a ella.
Las personas privadas son, en la practica, destinatarias de ayuda registradas
por el equipo de coordinacion. No son casos de busqueda y no se publican.
El estado not_missing identifica a una persona que nunca fue reportada como
desaparecida. Toda persona con ese estado es privada. El filtro status de
GET /persons admite missing, found o all; not_missing responde 422.
Un PATCH que establece not_missing puede devolver ese estado en su respuesta
antes de que el registro deje de ser accesible.
Lectura y datos sensibles
Usapersons:read para consultar y persons:write para crear, actualizar,
eliminar o gestionar fotos. GET /persons lista personas publicas de todas las
fuentes. El detalle y las operaciones por person_id exigen que la persona
pertenezca a la fuente de la llave; en caso contrario responden 404.
Las respuestas de lectura (GET /persons y GET /persons/{person_id}) estan
minimizadas por defecto. La API no devuelve documentos completos: cuando existe
una cedula, document_id se devuelve enmascarado con solo los
ultimos 4 digitos. Para menores de
edad, la API tampoco devuelve foto, edad exacta, ubicacion precisa, datos de
contacto, autores/contactos de informacion de comunidad, fuentes crudas ni
detalles clinicos. La informacion de comunidad puede devolverse con mensaje y
fecha, pero sin telefono y con autor generico.
Los detalles sensibles quedan reservados para gestion interna o acceso
verificado separado. La lectura sensible no se concede automaticamente con
persons:read.
Si la llave tiene persons:sensitive:read, las respuestas de personas incluyen
el documento completo, edad, foto, ubicacion, descripcion, datos del reportante,
telefono de quien localizo, hospital, fuentes y telefonos de informacion de
comunidad. Esta lectura sensible tambien aplica a respuestas que contienen
personas dentro de duplicados, upserts y fotos.
Crear una persona
Usa:source no se envía: la API lo
infiere desde la llave. Los campos desconocidos se rechazan con 422.
Una creación correcta responde 201 con { "data": { ...persona } }.
Son obligatorios first_name y last_name, con al menos dos caracteres. También
debes proporcionar contact_person_first_name, contact_person_phone y
contact_person_email. contact_person_last_name es opcional.
Usa location para la ubicación y document_type + document_id para documentos.
Los campos anteriores reporter_*, national_id y last_seen_location se
rechazan con 422 y ya no aparecen en respuestas de personas.
Fecha de nacimiento y edad:
- Usa
birth_datecuando exista una fecha exacta, en formatoYYYY-MM-DD. - Usa
agecuando solo exista una edad aproximada.
age < 18) son obligatorios:
contact_person_relationshipis_guardian_verified: true
age.
Valores de contact_person_relationship:
Actualizar una persona
Usa:200 con la persona actualizada. El cuerpo vacío {} también se acepta y puede
cambiar updated_at aunque no incluya campos de la persona.
Los teléfonos aceptan formatos nacionales o internacionales comunes y se
guardan como texto E.164, por ejemplo +584263105662. Cada campo admite un solo
número; valores vacíos o placeholders como N/A no reemplazan un número válido.
Las actualizaciones respetan estados terminales: una persona found no vuelve
a missing ni a not_missing. deceased es un valor de hospital_status, no
de status, y se conserva una vez establecido. Hospital y refugio son
mutuamente excluyentes y cualquiera de los dos implica found.
Si la persona es menor de edad o tiene condiciones/notas de salud, actualizarla,
eliminarla o cambiar su foto requiere persons:sensitive:read ademas de
persons:write.
No envíes campos internos de la web como photo_key, verified_at,
verified_by o deleted_at. La foto se gestiona con el endpoint de fotos.
is_public sí se puede actualizar: al establecerlo en false, la respuesta
devuelve el registro modificado, pero las siguientes consultas y modificaciones
por ID responden 404. Establecer status: "not_missing" también lo vuelve privado.
Para marcar como localizada:
found_state y found_city son obligatorios.
Si se envía hospital_status, también debe enviarse hospital. Si se envía
shelter_status, también debe enviarse shelter. No combines esos datos con
status: "missing".
Valores de hospital_status:
shelter con un handle oficial
y shelter_status. Hospital y refugio no deben coexistir.
Valores de shelter_status:
verified_at y verified_by son de solo lectura. Los escribe el
equipo interno cuando verifica un registro.
Eliminar una persona
204 sin cuerpo. Eliminar una persona
canónica con registros fusionados dependientes responde 409. Se aplican las
mismas restricciones de fuente, visibilidad y acceso sensible que en PATCH.
Upsert por fuente externa
Usa:source_id de la ruta. Si existe, actualiza la persona. Si no existe, crea una
nueva persona. Responde 200 al actualizar o 201 al crear, con
{ "data": { ...persona } }.
Ambos casos exigen el cuerpo completo de creación, incluidos los contactos y
las reglas de menores. No es un PATCH: no admite status, hospital,
found_* ni photo_key. Los campos permitidos son los definidos en
CreatePersonRequest. El cuerpo se valida antes de
buscar el registro; un cuerpo inválido responde 422 aunque el registro no sea
accesible. Si el registro existente es privado, un cuerpo válido responde 404.
El source_id del cuerpo se ignora para decidir el upsert. El identificador
externo correcto es siempre el de la ruta. source_notes se utiliza al crear;
no reemplaza las notas de fuente de un registro existente.
Este endpoint requiere persons:write. A diferencia de PATCH, no exige
persons:sensitive:read para actualizar un registro sensible existente. Ese
permiso sigue controlando qué datos sensibles aparecen en la respuesta.
Información de comunidad y reportes
Las rutas/v1/persons/{person_id}/tips y
/v1/persons/{person_id}/reports aceptan GET y POST. Para un registro
individual, agrega /{tip_id} o /{report_id}; esas rutas aceptan GET,
PATCH y DELETE.
La llave necesita tips:read o reports:read para consultar y tips:write
o reports:write para crear, actualizar o eliminar. La persona debe ser pública
y pertenecer a la fuente de la llave; de lo contrario, se responde 404.
Para crear información de comunidad, envía sender_name y message.
sender_phone es opcional y acepta un único teléfono válido. Se normaliza a
E.164. El teléfono solo aparece con persons:sensitive:read; sin ese permiso,
los menores muestran un autor genérico y ningún teléfono. Estas reglas también
se aplican a las respuestas de creación y actualización.
Para crear un reporte, envía reason, reporter_name y reporter_email.
details es opcional. Los motivos permitidos son duplicate, inappropriate,
incorrect_info, already_found y other.
Los reportes nuevos quedan en pending. PATCH permite cambiar el estado a
completed. La lista y las operaciones individuales solo encuentran reportes
activos pendientes: después de completarlo, su consulta, actualización o
eliminación por esta API responde 404. DELETE realiza una eliminación
lógica y responde 204 sin cuerpo.
Envía cuerpos JSON sin envoltura tip o report. POST rechaza campos
desconocidos; PATCH los descarta y requiere al menos un campo reconocido.
Fotos
Para subir o reemplazar una foto:file como archivo WebP con tipo image/webp y tamaño máximo
de 5 MiB (5 242 880 bytes). La API no convierte otros formatos. Un archivo
ausente, un tipo diferente o un tamaño mayor responde 422.
Una carga correcta responde 201 con
{ "data": { "person": { ...persona }, "photo": { "key": "...", "url": "..." } } }.
Para quitar la foto:
200 con { "data": { ...persona } }, también si la
persona ya no tiene foto. Las dos operaciones requieren persons:write y, para
un registro sensible, persons:sensitive:read.
Una respuesta 500 de escritura puede ocurrir después de guardar un cambio.
Consulta el registro antes de reintentar una creación, modificación o carga.
El photo_url de las respuestas apunta a /media/photos/.... Esa ruta tiene
límite de peticiones por IP y responde con una caché corta más ETag: guarda
el ETag y revalida con If-None-Match en vez de descargar la imagen cada vez.
La caché usa public, max-age=60, must-revalidate. Una revalidación vigente
responde 304 sin cuerpo. Una foto eliminada responde 404, incluso al enviar
su ETag anterior. El límite de lectura es de 600 peticiones por minuto por IP;
una respuesta 429 incluye Retry-After: 60.
El listado de reportes admite únicamente limit (50 por defecto, máximo 100) y
cursor. Devuelve reportes pendientes activos por created_at desc; el cursor
queda vinculado a la persona. Los filtros, el orden y los cursores inválidos
responden 422.
