Skip to main content

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 en GET /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

Usa persons: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:
Envía un objeto JSON sin envoltura. El campo 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_date cuando exista una fecha exacta, en formato YYYY-MM-DD.
  • Usa age cuando solo exista una edad aproximada.
Para menores de edad (age < 18) son obligatorios:
  • contact_person_relationship
  • is_guardian_verified: true
Esta validación de creación se activa por el campo age. Valores de contact_person_relationship:

Actualizar una persona

Usa:
El cuerpo es un objeto JSON parcial y rechaza campos desconocidos. Responde 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:
Si la persona es menor de edad, 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:
Para registrar una persona en un refugio, envía shelter con un handle oficial y shelter_status. Hospital y refugio no deben coexistir. Valores de shelter_status:
Los campos verified_at y verified_by son de solo lectura. Los escribe el equipo interno cuando verifica un registro.

Eliminar una persona

La eliminación es lógica y responde 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:
Este endpoint busca una persona existente por la fuente asociada a la llave y el 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:
Envía el campo 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:
La eliminación responde 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.