Personas

El vault guarda identidades ya verificadas y su PII cifrada. La escritura es directa; la lectura en claro nunca lo es: cada revelado deja una entrada en la bitácora, consume presupuesto y exige el scope persons:read_pii.

La PII es write-only en las respuestas normales. Para verla en claro se pasa por decrypt, que audita; fields te dice qué campos existen sin descifrar ninguno.

Los derechos ARCO están cubiertos por API: acceso (export), rectificación (PATCH) y cancelación (forget).

createPerson hace upsert por (application, externalRef): reintentar con el mismo externalRef no crea un duplicado.

Crear una persona

POST /v1/persons

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Da de alta una identidad en el vault. Si mandas externalRef, la operación es un upsert por (aplicación, externalRef): llamarla dos veces con el mismo identificador de tu sistema actualiza, no duplica. La PII se escribe cifrada y no vuelve en la respuesta.

Parámetros

Belfort-Version header
Idempotency-Key header

Cuerpo de la petición

application/json · schema PersonWriteRequest

CampoRequeridoTipoDescripción
applicationId no string | null Opaque application id.
environment no live | test | null
externalRef no string | null UID interno de tu sistema para este solicitante (p.ej. el id de tu tabla de usuarios). No-PII por contrato: nunca un email, teléfono, CURP ni nombre. A diferencia de los campos de pii, éste se almacena SIN cifrar y se indexa, así que NO recibe el tratamiento de vault (cifrado at-rest, auditoría de acceso, crypto-shred al vencer la retención). Es un namespace por Application: dos Applications del mismo tenant pueden usar el mismo valor y resuelven a Persons distintas.
metadata no object | null
pii no PiiInput | null

Respuestas

201 Successful Response — PersonWriteResponse

CampoRequeridoTipoDescripción
addressProvided sí boolean
birthDateProvided sí boolean
claveElectorProvided sí boolean
createdAt sí string (date-time)
curpProvided sí boolean
documentNumberProvided sí boolean
emailProvided sí boolean
emisionProvided sí boolean
environment sí live | test
fullNameProvided sí boolean
givenNameProvided sí boolean
id sí string
nationalityProvided sí boolean
object no "person"
phoneProvided sí boolean
piiVersion sí integer
rfcProvided sí boolean
seccionProvided sí boolean
sexProvided sí boolean
stateProvided sí boolean
status sí active | merged | redacted
surnameProvided sí boolean
updatedAt sí string (date-time)
vigenciaProvided sí boolean

Errores posibles (problem+json): 400 405 422 500

Listar personas

GET /v1/persons

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Página por cursor. Para buscar por atributos, usa la búsqueda estructurada en vez de filtrar en tu lado.

Parámetros

environment query
created[gte] query
created[lte] query
forgetRequested query
limit query Tamaño de página (1–100).
startingAfter query nextCursor de la página anterior. Excluyente con endingBefore.
endingBefore query previousCursor de la página actual. Excluyente con startingAfter.
includeTotal query Calcula totalCount. Cuesta un COUNT(*) sobre el filtro entero, así que está apagado por defecto: pídelo solo cuando vayas a enseñar el total.
application query
Belfort-Version header

Respuestas

200 Successful Response — ListEnvelope_PersonListItem_

CampoRequeridoTipoDescripción
data sí PersonListItem[]
hasMore sí boolean true si quedan resultados después de esta página.
limit sí integer El límite realmente aplicado (puede ser menor al pedido).
nextCursor no string | null Pásalo como startingAfter para la siguiente página.
object no "list"
previousCursor no string | null Pásalo como endingBefore para la página anterior.
totalCount no integer | null Total de coincidencias. Solo se calcula si pides includeTotal=true — es un COUNT(*) sobre el filtro entero y no se cobra a quien no lo necesita.

Errores posibles (problem+json): 400 405 422 500

Buscar personas

POST /v1/persons/search

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Búsqueda estructurada: declaras contra qué campo buscas en vez de mandar un texto libre y esperar que el servidor adivine. Va por POST porque los criterios pueden contener datos personales, y una query string acaba en los registros de todos los intermediarios.

Parámetros

Belfort-Version header

Cuerpo de la petición

application/json · schema PersonSearchRequest

CampoRequeridoTipoDescripción
cursor no string | null
environment no live | test | null
field sí curp | rfc | email | phone | name
limit no integer
value sí string

Respuestas

200 Successful Response — PersonSearchResults

CampoRequeridoTipoDescripción
data sí PersonListItem[]
hasMore sí boolean
nextCursor no string | null
object no "list"
totalCount sí integer
totalIsEstimate sí boolean

Errores posibles (problem+json): 400 405 422 500

Consultar una persona

GET /v1/persons/{person_id}

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Enmascarada por defecto: no descifra nada, no audita y no consume presupuesto de revelado. Para ver un campo en claro tienes que pedirlo explícitamente.

Parámetros

person_id path · requerido string
expand query
Belfort-Reason header
Belfort-Version header

Respuestas

200 Successful Response — PersonDetailMasked

CampoRequeridoTipoDescripción
addressProvided sí boolean
birthDateProvided sí boolean
claveElectorProvided sí boolean
createdAt sí string (date-time)
curpProvided sí boolean
documentNumberProvided sí boolean
emailProvided sí boolean
emisionProvided sí boolean
environment sí live | test
externalRefs sí PersonExternalRefItem[]
forgetRequested sí boolean
fullNameProvided sí boolean
givenNameProvided sí boolean
id sí string
metadata sí object
nationalityProvided sí boolean
object no "person"
phoneProvided sí boolean
pii sí object
piiProvenance sí object
piiVersion sí integer
rfcProvided sí boolean
seccionProvided sí boolean
sexProvided sí boolean
stateProvided sí boolean
status sí active | merged | redacted
surnameProvided sí boolean
updatedAt sí string (date-time)
verificationSummary sí PersonVerificationSummary
vigenciaProvided sí boolean

Errores posibles (problem+json): 400 405 422 500

Rectificar una persona

PATCH /v1/persons/{person_id}

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

El derecho de rectificación de ARCO. La PII sigue siendo de solo escritura, y cualquier cambio sobre ella queda registrado como una revisión.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema PersonPatchRequest

CampoRequeridoTipoDescripción
metadata no object | null
pii no PiiInput | null

Respuestas

200 Successful Response — PersonWriteResponse

CampoRequeridoTipoDescripción
addressProvided sí boolean
birthDateProvided sí boolean
claveElectorProvided sí boolean
createdAt sí string (date-time)
curpProvided sí boolean
documentNumberProvided sí boolean
emailProvided sí boolean
emisionProvided sí boolean
environment sí live | test
fullNameProvided sí boolean
givenNameProvided sí boolean
id sí string
nationalityProvided sí boolean
object no "person"
phoneProvided sí boolean
piiVersion sí integer
rfcProvided sí boolean
seccionProvided sí boolean
sexProvided sí boolean
stateProvided sí boolean
status sí active | merged | redacted
surnameProvided sí boolean
updatedAt sí string (date-time)
vigenciaProvided sí boolean

Errores posibles (problem+json): 400 405 422 500

Ver qué campos existen

GET /v1/persons/{person_id}/fields

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Responde "¿ya tengo la CURP de esta persona?" sin descifrar nada. Es la forma correcta de decidir si hace falta pedir un dato más: preguntar por presencia no es acceder a PII.

Parámetros

person_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response — PersonFieldsResponse

CampoRequeridoTipoDescripción
fields sí object
id sí string
object no "person.fields"

Errores posibles (problem+json): 400 405 422 500

Revelar PII en claro

POST /v1/persons/{person_id}/decrypt

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read_pii.

El revelado canónico servidor a servidor. Exige declarar la finalidad, escribe una entrada en la bitácora de accesos y consume presupuesto diario. No es idempotente a propósito: reintentar tiene que dejar su propia huella, porque la ley pide constancia de cada acceso, no de cada intención.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema DecryptRequest

CampoRequeridoTipoDescripción
fields sí string[]
purpose sí string
reason sí string

Respuestas

200 Successful Response — DecryptResponse

CampoRequeridoTipoDescripción
fields sí object
object no "person.decrypt"
personId sí string

Errores posibles (problem+json): 400 405 422 500

Revelar PII en lote

POST /v1/persons/batch-decrypt

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read_pii.

El mismo revelado para hasta 100 personas de una vez. Audita una entrada por persona, igual que si las hubieras pedido una a una.

Parámetros

Belfort-Version header

Cuerpo de la petición

application/json · schema BatchDecryptRequest

CampoRequeridoTipoDescripción
fields sí string[]
personIds sí string[]
purpose sí string
reason sí string

Respuestas

200 Successful Response — BatchDecryptResponse

CampoRequeridoTipoDescripción
data sí BatchDecryptItem[]
errors sí BatchDecryptErrorEntry[]
object no "list"

Errores posibles (problem+json): 400 405 422 500

Emitir un client-token

POST /v1/persons/{person_id}/client-token

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read_pii.

Crea una credencial efímera para que un navegador revele campos concretos, sin que tu clave secreta salga de tu servidor. Declaras qué campos autoriza; el token no puede pedir más.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema ClientTokenCreateRequest

CampoRequeridoTipoDescripción
fields sí string[]
purpose no string | null
reason sí string
scope no "decrypt"
ttlSeconds no integer | null

Respuestas

201 Successful Response — ClientTokenIssueResponse

CampoRequeridoTipoDescripción
createdAt sí string (date-time)
expiresAt sí string (date-time)
fields sí string[]
id sí string
object no "person.client_token"
personId sí string
purpose sí string | null
scope sí string
token sí string

Errores posibles (problem+json): 400 405 422 500

Revocar un client-token

POST /v1/persons/{person_id}/client-token/{token_id}/revoke

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Invalida el token antes de que expire. Idempotente: revocar dos veces devuelve el mismo momento de revocación, no un error.

Parámetros

person_id path · requerido string
token_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response — ClientTokenRevokeResponse

CampoRequeridoTipoDescripción
id sí string
object no "person.client_token"
personId sí string
revokedAt sí string (date-time) | null

Errores posibles (problem+json): 400 405 422 500

Listar consentimientos

GET /v1/persons/{person_id}/consents

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Los consentimientos vigentes y revocados de la persona. La evidencia del consentimiento nunca viaja en esta lista: es de solo escritura.

Parámetros

person_id path · requerido string
limit query Tamaño de página (1–100).
startingAfter query nextCursor de la página anterior. Excluyente con endingBefore.
endingBefore query previousCursor de la página actual. Excluyente con startingAfter.
includeTotal query Calcula totalCount. Cuesta un COUNT(*) sobre el filtro entero, así que está apagado por defecto: pídelo solo cuando vayas a enseñar el total.
Belfort-Version header

Respuestas

200 Successful Response — ListEnvelope_ConsentItem_

CampoRequeridoTipoDescripción
data sí ConsentItem[]
hasMore sí boolean true si quedan resultados después de esta página.
limit sí integer El límite realmente aplicado (puede ser menor al pedido).
nextCursor no string | null Pásalo como startingAfter para la siguiente página.
object no "list"
previousCursor no string | null Pásalo como endingBefore para la página anterior.
totalCount no integer | null Total de coincidencias. Solo se calcula si pides includeTotal=true — es un COUNT(*) sobre el filtro entero y no se cobra a quien no lo necesita.

Errores posibles (problem+json): 400 405 422 500

Registrar un consentimiento

POST /v1/persons/{person_id}/consents

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Asocia un consentimiento a una finalidad concreta. La finalidad tiene que existir en el catálogo: aceptar una inventada sería registrar un consentimiento que no significa nada.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema ConsentGrantRequest

CampoRequeridoTipoDescripción
attestedBy no applicant | integrator | null
evidence no ConsentEvidenceInput | null
expiresAt no string (date-time) | null
mechanism sí firma_electronica | autenticacion
policyVersion sí string
purpose sí string

Respuestas

201 Successful Response — ConsentItem

CampoRequeridoTipoDescripción
attestedBy sí string
createdAt sí string (date-time)
expiresAt sí string (date-time) | null
grantedAt sí string (date-time)
id sí string
mechanism sí string
object no "person.consent"
policyVersion sí string
purpose sí string
revokedAt sí string (date-time) | null

Errores posibles (problem+json): 400 405 422 500

Revocar un consentimiento

POST /v1/persons/{person_id}/consents/{consent_id}/revoke

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Idempotente: la fecha de revocación es la de la primera vez, no la de la última llamada.

Parámetros

person_id path · requerido string
consent_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response — ConsentItem

CampoRequeridoTipoDescripción
attestedBy sí string
createdAt sí string (date-time)
expiresAt sí string (date-time) | null
grantedAt sí string (date-time)
id sí string
mechanism sí string
object no "person.consent"
policyVersion sí string
purpose sí string
revokedAt sí string (date-time) | null

Errores posibles (problem+json): 400 405 422 500

Listar cesiones

GET /v1/persons/{person_id}/grants

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Qué aplicaciones tuyas pueden ver a esta persona. Es el control de acceso entre tus propios productos.

Parámetros

person_id path · requerido string
limit query Tamaño de página (1–100).
startingAfter query nextCursor de la página anterior. Excluyente con endingBefore.
endingBefore query previousCursor de la página actual. Excluyente con startingAfter.
includeTotal query Calcula totalCount. Cuesta un COUNT(*) sobre el filtro entero, así que está apagado por defecto: pídelo solo cuando vayas a enseñar el total.
Belfort-Version header

Respuestas

200 Successful Response — ListEnvelope_GrantItem_

CampoRequeridoTipoDescripción
data sí GrantItem[]
hasMore sí boolean true si quedan resultados después de esta página.
limit sí integer El límite realmente aplicado (puede ser menor al pedido).
nextCursor no string | null Pásalo como startingAfter para la siguiente página.
object no "list"
previousCursor no string | null Pásalo como endingBefore para la página anterior.
totalCount no integer | null Total de coincidencias. Solo se calcula si pides includeTotal=true — es un COUNT(*) sobre el filtro entero y no se cobra a quien no lo necesita.

Errores posibles (problem+json): 400 405 422 500

Conceder acceso a una aplicación

POST /v1/persons/{person_id}/grants

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Crea o reemplaza la cesión para una aplicación. Repetirla no acumula cesiones: sustituye la anterior.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema GrantCreateRequest

CampoRequeridoTipoDescripción
allowedFields sí string[]
allowedPurposes sí string[]
applicationId sí string Opaque application id.
defaultRedaction no plain | masked | redacted
expiresAt no string (date-time) | null

Respuestas

201 Successful Response — GrantItem

CampoRequeridoTipoDescripción
allowedFields sí string[]
allowedPurposes sí string[]
applicationId sí string Opaque application id.
createdAt sí string (date-time)
createdVia sí string
defaultRedaction sí string
expiresAt sí string (date-time) | null
id sí string
object no "person.grant"
revokedAt sí string (date-time) | null

Errores posibles (problem+json): 400 405 422 500

Revocar una cesión

POST /v1/persons/{person_id}/grants/{grant_id}/revoke

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Idempotente, como el resto de revocaciones del vault.

Parámetros

person_id path · requerido string
grant_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response — GrantItem

CampoRequeridoTipoDescripción
allowedFields sí string[]
allowedPurposes sí string[]
applicationId sí string Opaque application id.
createdAt sí string (date-time)
createdVia sí string
defaultRedaction sí string
expiresAt sí string (date-time) | null
id sí string
object no "person.grant"
revokedAt sí string (date-time) | null

Errores posibles (problem+json): 400 405 422 500

Listar documentos de la persona

GET /v1/persons/{person_id}/documents

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Solo metadatos: qué archivos existen, de qué tipo y de cuándo. Para verlos hay que emitir un enlace firmado, que es una operación distinta y auditada.

Parámetros

person_id path · requerido string
limit query Tamaño de página (1–100).
startingAfter query nextCursor de la página anterior. Excluyente con endingBefore.
endingBefore query previousCursor de la página actual. Excluyente con startingAfter.
includeTotal query Calcula totalCount. Cuesta un COUNT(*) sobre el filtro entero, así que está apagado por defecto: pídelo solo cuando vayas a enseñar el total.
Belfort-Version header

Respuestas

200 Successful Response — ListEnvelope_PersonDocumentItem_

CampoRequeridoTipoDescripción
data sí PersonDocumentItem[]
hasMore sí boolean true si quedan resultados después de esta página.
limit sí integer El límite realmente aplicado (puede ser menor al pedido).
nextCursor no string | null Pásalo como startingAfter para la siguiente página.
object no "list"
previousCursor no string | null Pásalo como endingBefore para la página anterior.
totalCount no integer | null Total de coincidencias. Solo se calcula si pides includeTotal=true — es un COUNT(*) sobre el filtro entero y no se cobra a quien no lo necesita.

Errores posibles (problem+json): 400 405 422 500

Listar verificaciones de la persona

GET /v1/persons/{person_id}/verification-sessions

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Todas las veces que esta persona ha pasado por el motor de identidad, de la más reciente a la más antigua.

Parámetros

person_id path · requerido string
limit query Tamaño de página (1–100).
startingAfter query nextCursor de la página anterior. Excluyente con endingBefore.
endingBefore query previousCursor de la página actual. Excluyente con startingAfter.
includeTotal query Calcula totalCount. Cuesta un COUNT(*) sobre el filtro entero, así que está apagado por defecto: pídelo solo cuando vayas a enseñar el total.
Belfort-Version header

Respuestas

200 Successful Response — ListEnvelope_PersonVerificationSessionItem_

CampoRequeridoTipoDescripción
data sí PersonVerificationSessionItem[]
hasMore sí boolean true si quedan resultados después de esta página.
limit sí integer El límite realmente aplicado (puede ser menor al pedido).
nextCursor no string | null Pásalo como startingAfter para la siguiente página.
object no "list"
previousCursor no string | null Pásalo como endingBefore para la página anterior.
totalCount no integer | null Total de coincidencias. Solo se calcula si pides includeTotal=true — es un COUNT(*) sobre el filtro entero y no se cobra a quien no lo necesita.

Errores posibles (problem+json): 400 405 422 500

Re-autenticar por rostro

POST /v1/persons/{person_id}/reauth-face

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read_pii.

Cotejo uno a uno contra el rostro ya verificado de la persona. Sirve para confirmar que quien vuelve es la misma persona, sin repetir la verificación documental completa.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema ReauthFaceRequest

CampoRequeridoTipoDescripción
mime no string
selfieBase64 sí string

Respuestas

200 Successful Response — ReauthFaceResult

CampoRequeridoTipoDescripción
decision sí match | inconclusive | no_match
deepfakeGenuineConfidence no number | null
livenessPassed no boolean | null
match sí boolean
object no "person.reauth_face"
presentationAttack no boolean
reasonCodes no string[]
referenceCapturedAt sí string (date-time)
score sí number | null
threshold sí number | null

Errores posibles (problem+json): 400 405 422 500

Buscar duplicados

GET /v1/persons/{person_id}/duplicates

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Candidatos a ser la misma persona, por coincidencia de CURP o correo. Sugiere; no fusiona nada.

Parámetros

person_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response — DuplicatesResponse

CampoRequeridoTipoDescripción
data sí DuplicateItem[]
object no "list"

Errores posibles (problem+json): 400 405 422 500

Consolidar duplicados

POST /v1/persons/{person_id}/consolidate

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Fusiona una o varias personas dentro de esta, que es la que sobrevive. Es asíncrono: responde de inmediato con un identificador que puedes consultar.

Parámetros

person_id path · requerido string
Belfort-Version header
Idempotency-Key header

Cuerpo de la petición

application/json · schema ConsolidateRequest

CampoRequeridoTipoDescripción
fieldResolutions no object
sourcePersonIds sí string[]

Respuestas

202 Successful Response — ConsolidationEnvelope

CampoRequeridoTipoDescripción
consolidationId sí string
merges sí ConsolidateMergeRef[]
object no "person.consolidation"
status sí string
survivorId sí string

Errores posibles (problem+json): 400 405 422 500

Consultar una consolidación

GET /v1/persons/{person_id}/consolidations/{consolidation_id}

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Solo aparece como terminada cuando TODAS las fuentes se fusionaron. Una consolidación a medias no se reporta como hecha.

Parámetros

person_id path · requerido string
consolidation_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response — ConsolidationStatusResponse

CampoRequeridoTipoDescripción
consolidationId sí string
createdAt sí string (date-time)
merges sí ConsolidationMergeStatusItem[]
object no "person.consolidation"
status sí string
survivorId sí string

Errores posibles (problem+json): 400 405 422 500

Comprobar la integridad de un campo

POST /v1/persons/{person_id}/integrity

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read_pii.

Le mandas el hash que tú calculaste de un dato y te dice si coincide con el que hay guardado, sin descifrar nada ni revelarte el valor. Sirve para confirmar que tu copia y la nuestra siguen siendo la misma.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema IntegrityRequest

CampoRequeridoTipoDescripción
fields sí object
reason no string | null
signingKey sí string

Respuestas

200 Successful Response — IntegrityResponse

CampoRequeridoTipoDescripción
id sí string
object no "person.integrity"
results sí object

Errores posibles (problem+json): 400 405 422 500

Exportar los datos de una persona

POST /v1/persons/{person_id}/export

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read_pii.

El derecho de acceso de ARCO: todo lo que Belfort guarda sobre esa persona, en un formato que puedes entregarle. Cuenta como revelado y queda auditado.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json

CampoRequeridoTipoDescripción
reason no string | null

Respuestas

200 Successful Response — PersonExportBundle

CampoRequeridoTipoDescripción
generatedAt sí string (date-time)
media sí ExportMediaItem[]
object no "person.export"
personId sí string
pii sí object
piiProvenance sí object
verificationSessions sí ExportSessionItem[]

Errores posibles (problem+json): 400 405 422 500

Bloquear o suprimir una persona

POST /v1/persons/{person_id}/forget

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:redact.

El derecho de cancelación. block deja los datos inaccesibles pero conservados —que es lo que exige el periodo de bloqueo previo a la supresión— y purge los destruye. Va por POST y con el motivo en el cuerpo: el motivo es un dato personal y no puede acabar en la URL de todos los registros por los que pasa la petición.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json

CampoRequeridoTipoDescripción
mode no string
reason no string | null

Respuestas

200 Successful Response — PersonForgetResponse

CampoRequeridoTipoDescripción
mode sí string
object no "person.forget"
personId sí string
purgeDueAt sí string (date-time)

Errores posibles (problem+json): 400 405 422 500

Obtener el certificado de supresión

GET /v1/persons/{person_id}/deletion-certificate

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

La constancia de que una persona fue purgada de verdad. Determinista: la misma supresión produce siempre el mismo certificado, así que sirve como prueba.

Parámetros

person_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response — PersonDeletionCertificate

CampoRequeridoTipoDescripción
contentHash sí string
environment sí string
object no "person.deletion_certificate"
personId sí string
purgedAt sí string (date-time)
signature sí string
tenantId sí string Opaque tenant id.

Errores posibles (problem+json): 400 405 422 500

POST /v1/persons/{person_id}/legal-hold

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Congela a la persona frente a cualquier supresión, incluida una solicitud ARCO, mientras dure un requerimiento de autoridad. Renueva si ya había una vigente.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema LegalHoldSetRequest

CampoRequeridoTipoDescripción
expiresAt no string (date-time) | null
legalBasis sí string
reason sí string

Respuestas

201 Successful Response — LegalHoldItem

CampoRequeridoTipoDescripción
action sí string
createdAt sí string (date-time)
expiresAt sí string (date-time) | null
id sí string
legalBasis sí string | null
object no "person.legal_hold"
personId sí string
reason sí string

Errores posibles (problem+json): 400 405 422 500

POST /v1/persons/{person_id}/legal-hold/release

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Devuelve a la persona al régimen normal de conservación.

Parámetros

person_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema LegalHoldReleaseRequest

CampoRequeridoTipoDescripción
legalBasis no string | null
reason sí string

Respuestas

200 Successful Response — LegalHoldItem

CampoRequeridoTipoDescripción
action sí string
createdAt sí string (date-time)
expiresAt sí string (date-time) | null
id sí string
legalBasis sí string | null
object no "person.legal_hold"
personId sí string
reason sí string

Errores posibles (problem+json): 400 405 422 500

Historial de retenciones legales

GET /v1/persons/{person_id}/legal-holds

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Append-only y en orden descendente: una retención levantada no se borra del historial, porque el historial es justo lo que se exhibe ante la autoridad.

Parámetros

person_id path · requerido string
limit query Tamaño de página (1–100).
startingAfter query nextCursor de la página anterior. Excluyente con endingBefore.
endingBefore query previousCursor de la página actual. Excluyente con startingAfter.
includeTotal query Calcula totalCount. Cuesta un COUNT(*) sobre el filtro entero, así que está apagado por defecto: pídelo solo cuando vayas a enseñar el total.
Belfort-Version header

Respuestas

200 Successful Response — ListEnvelope_LegalHoldItem_

CampoRequeridoTipoDescripción
data sí LegalHoldItem[]
hasMore sí boolean true si quedan resultados después de esta página.
limit sí integer El límite realmente aplicado (puede ser menor al pedido).
nextCursor no string | null Pásalo como startingAfter para la siguiente página.
object no "list"
previousCursor no string | null Pásalo como endingBefore para la página anterior.
totalCount no integer | null Total de coincidencias. Solo se calcula si pides includeTotal=true — es un COUNT(*) sobre el filtro entero y no se cobra a quien no lo necesita.

Errores posibles (problem+json): 400 405 422 500

POST /v1/persons/{person_id}/documents/{asset_id}/legal-hold

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Bloquea un asset de media concreto: mientras el hold esté vigente, ni el barrido de retención ni el derecho al olvido lo eliminan, aunque su fecha de retención ya haya vencido. reason y legalBasis son obligatorios. Cada llamada agrega una fila nueva al historial append-only, aunque el hold ya estuviera puesto. Requiere scope persons:write.

Parámetros

person_id path · requerido string
asset_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema MediaAssetLegalHoldSetRequest

CampoRequeridoTipoDescripción
expiresAt no string (date-time) | null
legalBasis sí string
reason sí string

Respuestas

201 Successful Response — MediaAssetLegalHoldItem

CampoRequeridoTipoDescripción
action sí string
assetId sí string
createdAt sí string (date-time)
expiresAt sí string (date-time) | null
id sí string
legalBasis sí string | null
object no "media_asset.legal_hold"
personId sí string
reason sí string

Errores posibles (problem+json): 400 405 422 500

POST /v1/persons/{person_id}/documents/{asset_id}/legal-hold/release

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Libera un asset de media: vuelve a quedar sujeto al TTL normal de retención, así que si su retentionUntil ya venció lo elimina el siguiente barrido. reason es obligatorio; legalBasis, opcional. Siempre inserta una fila release nueva en el historial append-only. Requiere scope persons:write.

Parámetros

person_id path · requerido string
asset_id path · requerido string
Belfort-Version header

Cuerpo de la petición

application/json · schema MediaAssetLegalHoldReleaseRequest

CampoRequeridoTipoDescripción
legalBasis no string | null
reason sí string

Respuestas

200 Successful Response — MediaAssetLegalHoldItem

CampoRequeridoTipoDescripción
action sí string
assetId sí string
createdAt sí string (date-time)
expiresAt sí string (date-time) | null
id sí string
legalBasis sí string | null
object no "media_asset.legal_hold"
personId sí string
reason sí string

Errores posibles (problem+json): 400 405 422 500

GET /v1/persons/{person_id}/documents/{asset_id}/legal-holds

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Cursor list del historial append-only de un asset, en orden descendente por createdAt. El estado vigente lo dice data[0]: un action='set' sin un release posterior más reciente significa que el documento sigue bloqueado. Requiere scope persons:read.

Parámetros

person_id path · requerido string
asset_id path · requerido string
limit query Tamaño de página (1–100).
startingAfter query nextCursor de la página anterior. Excluyente con endingBefore.
endingBefore query previousCursor de la página actual. Excluyente con startingAfter.
includeTotal query Calcula totalCount. Cuesta un COUNT(*) sobre el filtro entero, así que está apagado por defecto: pídelo solo cuando vayas a enseñar el total.
Belfort-Version header

Respuestas

200 Successful Response — ListEnvelope_MediaAssetLegalHoldItem_

CampoRequeridoTipoDescripción
data sí MediaAssetLegalHoldItem[]
hasMore sí boolean true si quedan resultados después de esta página.
limit sí integer El límite realmente aplicado (puede ser menor al pedido).
nextCursor no string | null Pásalo como startingAfter para la siguiente página.
object no "list"
previousCursor no string | null Pásalo como endingBefore para la página anterior.
totalCount no integer | null Total de coincidencias. Solo se calcula si pides includeTotal=true — es un COUNT(*) sobre el filtro entero y no se cobra a quien no lo necesita.

Errores posibles (problem+json): 400 405 422 500

Importar personas en lote

POST /v1/persons/import

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:write.

Recibe NDJSON —una persona por línea— y responde con un trabajo que puedes consultar. El entorno lo fija la key: una clave de prueba no puede escribir en producción.

Parámetros

applicationId query
Belfort-Version header
Idempotency-Key header

Respuestas

202 Successful Response — PersonImportJobEnvelope

CampoRequeridoTipoDescripción
createdAt sí string (date-time)
errors sí PersonImportRowError[]
failed sí integer
id sí string
object no "person.import_job"
status sí string
succeeded sí integer
total sí integer

Errores posibles (problem+json): 400 405 422 500

Consultar una importación

GET /v1/persons/import/{job_id}

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Progreso y errores por fila del trabajo de importación.

Parámetros

job_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response — PersonImportJobEnvelope

CampoRequeridoTipoDescripción
createdAt sí string (date-time)
errors sí PersonImportRowError[]
failed sí integer
id sí string
object no "person.import_job"
status sí string
succeeded sí integer
total sí integer

Errores posibles (problem+json): 400 405 422 500

Exportar personas en lote

POST /v1/persons/export-bulk

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read_pii.

Encola la exportación y responde de inmediato. Genera un archivo cifrado que se descarga aparte.

Parámetros

applicationId query
Belfort-Version header
Idempotency-Key header

Cuerpo de la petición

application/json

CampoRequeridoTipoDescripción
reason no string | null

Respuestas

202 Successful Response — PersonExportBulkJobEnvelope

CampoRequeridoTipoDescripción
createdAt sí string (date-time)
errors sí PersonExportBulkRowError[]
expiresAt no string (date-time) | null
failed sí integer
id sí string
object no "person.export_job"
status sí string
succeeded sí integer
total sí integer

Errores posibles (problem+json): 400 405 422 500

Consultar una exportación

GET /v1/persons/export-bulk/{job_id}

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read.

Estado del trabajo de exportación.

Parámetros

job_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response — PersonExportBulkJobEnvelope

CampoRequeridoTipoDescripción
createdAt sí string (date-time)
errors sí PersonExportBulkRowError[]
expiresAt no string (date-time) | null
failed sí integer
id sí string
object no "person.export_job"
status sí string
succeeded sí integer
total sí integer

Errores posibles (problem+json): 400 405 422 500

Descargar una exportación

GET /v1/persons/export-bulk/{job_id}/download

Requiere una API key secreta (belfort_{env}_sk_…) con scope persons:read_pii.

Descifra y sirve el archivo completo. Exige el mismo permiso que crearlo: descargar es revelar, y se audita igual.

Parámetros

job_id path · requerido string
Belfort-Version header

Respuestas

200 Successful Response

Errores posibles (problem+json): 400 405 422 500