Saltar al contenido

Flujo de integración

Esta página describe el orden recomendado de llamadas para abrir un legajo end-to-end desde un sistema integrador.

Diagrama de alto nivel

1. POST /v1/accounts                       ← crear el legajo COMPLETO en una sola llamada
                                             (datos, direcciones, FATCA, SoF, cuestionario,
                                              cotitulares, beneficiarios, CBUs, etc.)
2. POST /v1/accounts/{id}/documents        ← subir documentos requeridos
3. GET  /v1/accounts/{id}/checklist        ← verificar completitud
4a. POST /v1/accounts/{id}/submit          ← enviar por API (la entrega la define el flujo)
4b. POST /v1/accounts/{id}/hosted-flow/link ← entregar el cierre al consumidor en el portal

La pieza central de la API es el bulk POST: una sola llamada crea el legajo con todas sus secciones anidadas. No hay sub-endpoints por sección — el legajo se crea en una sola operación y, si hay errores, la API responde 422 con un detalle por campo en dot-notation.

1. Crear el legajo (bulk POST)

bash
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "type": 1,
    "denomination": "Pérez, Juan",
    "onboarding_flow": "apertura-estandar",
    "human": {
      "name": "Juan",
      "surname": "Pérez",
      "email": "juan.perez@example.com",
      "phone": "+541112345678",
      "birth_date": "1985-04-12",
      "nationality": 11,
      "tax_id_type": "CUIL",
      "tax_id_number": "20123456789",
      "id_type": 1,
      "id_number": "12345678",
      "residential_address": {
        "street_name": "Av. Corrientes",
        "street_number": "1234",
        "floor": "3",
        "apartment": "B",
        "city": "CABA",
        "provincia_id": 1,
        "postal_code": "C1043",
        "country_id": 11
      },
      "work_address": { /* opcional, mismas keys */ },
      "spouse": { /* opcional, requerido si marital_status=married según la configuración */ },
      "fatca": { /* opcional */ },
      "source_of_funds": { /* opcional */ },
      "investor_questionnaire": {
        "responses": [
          { "question_id": "uuid-1", "option_id": "uuid-opt-1" },
          { "question_id": "uuid-2", "option_id": "uuid-opt-2" }
        ]
      }
    },
    "cbus": [
      { "cbu_cvu": "0170099220000067797370", "currency_id": 1 }
    ],
    "related_humans": [
      { /* cotitulares / apoderados — cada uno con su propio bloque de human fields */ }
    ]
  }' \
  https://compliance.quantian.ar/api/v1/accounts

Respuesta (201 Created):

jsonc
{
  "data": {
    "id": "01962b4c-...",
    "type": 1,
    "type_label": "persona_humana",
    "status": "draft",
    "denomination": "Pérez, Juan",
    "created_via": "api",
    "risk_level": null,
    "submitted_at": null,
    "opened_at": null,
    "created_at": "2026-05-26T14:00:00+00:00",
    "updated_at": "2026-05-26T14:00:00+00:00",
    "links": { "self": "https://compliance.quantian.ar/api/v1/accounts/01962b4c-..." }
  }
}

Estructura del payload

El payload del bulk POST tiene dos formas, una por cada tipo de legajo:

Persona humana (type: 1)

jsonc
{
  "type": 1,
  "denomination": "Pérez, Juan",        // opcional, se autocompleta con name+surname si falta
  "onboarding_flow": "apertura-estandar", // opcional, slug del flujo; si se omite usa el default. Ver GET /v1/onboarding-flows.
  "human": {
    // campos top-level del titular (name, surname, tax_id_*, birth_date, marital_status, ...)
    "residential_address": { /* ... */ },
    "work_address": { /* ... */ },       // opcional
    "spouse": { /* ... */ },             // opcional, según marital_status
    "fatca": { /* ... */ },              // opcional
    "source_of_funds": { /* ... */ },
    "investor_questionnaire": { "responses": [ /* {question_id, option_id} */ ] }
  },
  "cbus": [ /* array de {cbu_cvu, currency_id} */ ],
  "related_humans": [ /* cotitulares — cada uno con la misma forma que "human" */ ]
}

Persona jurídica (type: 2)

jsonc
{
  "type": 2,
  "denomination": "Acme S.A.",
  "onboarding_flow": "apertura-estandar",
  "company": {
    // campos top-level de la empresa (name, tax_id_number, tipo_societario_id, cnv_entity_type_id, ...)
    "fiscal_address": { /* ... */ },
    "real_address": { /* ... */ },       // opcional si coincide con la fiscal
    "fatca": { /* ... */ },
    "source_of_funds": { /* ... */ },
    "investor_questionnaire": { "responses": [ /* {question_id, option_id} */ ] }
  },
  "beneficial_ownership": [ /* array de UBOs */ ],
  "cbus": [ /* ... */ ],
  "related_humans": [ /* apoderados, firmantes — cada uno con la forma de "human" */ ]
}

Reglas de validación

Las reglas de cada sección se construyen en runtime a partir de Campos configurables más los catálogos globales (países, condiciones IVA / Ganancias, tipos societarios, tipos de entidad CNV). Esto significa que:

  • Lo que es requerido depende de la organización.
  • Los enums (ej. nationality, tipo_societario_id) toman valores del catálogo global; los valores válidos están en GET /v1/catalogs/{catalog}.
  • Si un campo no figura en la superficie de la API (no está habilitado en el portal de onboarding), la API lo ignora silenciosamente.

Para conocer la lista exacta de campos requeridos, revisar con el área de cumplimiento qué tienen configurado en Configuración → Campos configurables.

Validá el payload localmente

GET /v1/payload-schema/{ph|pj} devuelve el contrato de campos como JSON Schema Draft 2020-12. Bajalo y validá el payload del bulk POST antes de enviarlo para reducir round-trips de 422. Ver Contrato de campos.

2. Subir documentos

El catálogo de documentos requeridos depende de la matriz de Requerimientos documentales. Para subir un documento:

bash
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -F "file=@dni_frente.jpg" \
  -F "target=human" \
  -F "document_classification_id={uuid-de-la-clasificación}" \
  -F "description=DNI - frente" \
  https://compliance.quantian.ar/api/v1/accounts/{id}/documents

Campos del multipart:

  • file (requerido) — el archivo. Tipos aceptados: pdf, png, jpg, jpeg, gif, bmp, tiff. Tamaño máximo: 50 MB.
  • target (opcional)human o company. Si no se pasa, se infiere por el tipo del legajo (company para PJ, human para PH).
  • document_classification_id (opcional) — UUID del tipo de documento. Debe pertenecer a su organización (la API verifica la pertenencia automáticamente).
  • description (opcional) — texto libre, máx. 500 caracteres.
  • expiration_date (opcional) — fecha de vencimiento del documento (ISO 8601).

La API valida tanto el MIME declarado como los magic-bytes del archivo: un PDF con cuerpo HTML disfrazado se rechaza con 422.

Documentos que requieren presencia del consumidor

Selfie, prueba de vida y otros documentos biométricos no se cargan por API — esos llegan en el hosted flow, cuando el consumidor abre el magic-link en su navegador.

3. Verificar completitud

Antes de cerrar el legajo, consultá el checklist:

bash
curl -H "Authorization: Bearer $TOKEN" \
  https://compliance.quantian.ar/api/v1/accounts/{id}/checklist

Devuelve los grupos de campos / documentos del legajo y cuáles están completos vs faltantes. Es el mismo checklist que ve el operador en el backoffice — útil para confirmar antes de avanzar al cierre.

4. Envío del legajo

Una vez cargados todos los datos requeridos, enviá el legajo:

http
POST /api/v1/accounts/{id}/submit
Authorization: Bearer <TOKEN>

El body es vacío. El comportamiento depende de la entrega de firma del flujo del legajo — ver Entrega de la firma. Si algún sujeto del legajo no tiene perfil de inversor cargado, el submit dispara automáticamente un magic-link para que el cliente lo complete — ver Perfil de Inversor.

Respuesta 200 OK — modo email:

jsonc
{
  "data": { /* AccountResource completo */ },
  "signature": { "mode": "email", "status": "dispatched" },
  "investor_profile_renewal": null
}

Respuesta 200 OK — modo api_link:

jsonc
{
  "data": { /* AccountResource completo */ },
  "signature": {
    "mode": "api_link",
    "urls": [
      { "signer_id": "uuid", "signer_name": "Ana López", "url": "https://firma.ejemplo.com/s/abc123" }
    ]
  },
  "investor_profile_renewal": null
}

Respuesta 200 OK — modo none:

jsonc
{
  "data": { /* AccountResource completo */ },
  "signature": { "mode": "none" },
  "investor_profile_renewal": null
}

Idempotencia del submit

Si el legajo ya está en estado pending_signature o más avanzado (por un submit previo), la llamada devuelve 200 con el estado actual sin volver a disparar la firma. Seguro de reintentar ante timeouts de red.

4b. Entrega del cierre al consumidor en el portal

Si el flujo requiere biometría o faltan datos que solo el cliente puede completar, obtené el magic-link y entregáselo al cliente:

bash
curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"email": "juan.perez@example.com", "expires_in_hours": 24}' \
  https://compliance.quantian.ar/api/v1/accounts/{id}/hosted-flow/link

Respuesta (201 Created):

jsonc
{
  "data": {
    "url": "https://tu-broker.quantian.ar/auth/verify#token=mLk_a7c3...d4e9",
    "expires_at": "2026-05-27T14:00:00+00:00"
  }
}

Su sistema entrega ese enlace al cliente (por email, SMS, WhatsApp, in-app), y el cliente termina los pasos navegables desde el navegador. Más detalle en Hosted flow.

Si el flujo no requiere biometría y ya cargaste todos los datos por API, podés usar POST /v1/accounts/{id}/submit directamente — consultá Entrega de la firma.

Los campos denomination y onboarding_flow se definen al crear el legajo en el bulk POST y no se modifican por API una vez creado. La entrega de la firma y la biometría las define el flujo elegido.

Cambios sobre datos del titular post-bulk

La modificación granular de campos del human / company / direcciones / sub-secciones después del bulk POST inicial no está expuesta en esta versión de la API. Si el legajo todavía está en draft y necesita corregir un dato cargado mal, la opción inmediata es usar el hosted flow para que el consumidor lo edite, o bien coordinar la corrección desde el backoffice.

Particularidades

  • Una sola llamada de creación: no hay endpoints por sección. Esto reduce la cantidad de round-trips pero implica que si el payload tiene errores, el 422 reporta todos los errores juntos. Recomendamos validar el payload localmente contra el schema de GET /v1/payload-schema/{ph|pj} antes de enviar a producción.
  • Bulk crea todo o nada: si falla la validación, no se crea el legajo. Si pasa la validación, el legajo y todas las sub-entidades se persisten en una transacción.
  • Idempotencia: el bulk POST no es idempotente por defecto. Vea Idempotencia y reintentos para evitar duplicados ante fallas de red.