VitrinaAPI

Feed bancario de la clínica

Los movimientos bancarios de la clínica, desde correo, Fintoc o la API del banco, normalizados a un mismo formato para conciliar la caja.

Beta
Puede cambiar en cualquier momento, con una entrada en el changelog y aviso a quienes la llamaron recientemente — ver versionado.

Descarga la proyección completa de la API pública: openapi.json.

MétodoRutaQué hace
GET/clinic/bank-feed/connectionsConnected bank links
POST/clinic/bank-feed/connections/{id}/disconnectDisconnect a bank link
POST/clinic/bank-feed/connections/{id}/syncSincronizar ahora — enqueue a pull of one bank link
POST/clinic/bank-feed/email/pullRe-read bank e-mails still in the inbox for a window
POST/clinic/bank-feed/fintoc/connectConnect a bank through Fintoc
GET/clinic/bank-feed/sourcesBank feed sources available to this clinic

GET /clinic/bank-feed/connections

Connected bank links

Every bank link this clinic connected through an API source, enabled or not, with masked account numbers and the last sync result. Requires clinic_money:read.

Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.

curl https://api.vitrinadev.com/api/v1/clinic/bank-feed/connections \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": [
    {
      "id": "bf0bf0bf-0000-4000-8000-000000000001",
      "provider": "fintoc",
      "institution_name": "Banco de Chile",
      "holder_name": "Clínica Ejemplo SpA",
      "accounts": [
        {
          "id": "acc_9Xz2Lm",
          "number_masked": "••••4821"
        }
      ],
      "enabled": true,
      "connected_at": "2026-09-20T14:02:11.000Z",
      "disconnected_at": null,
      "last_sync_at": "2026-09-22T09:00:04.000Z",
      "last_sync_status": "ok",
      "last_sync_error": null,
      "sync_cursor": "2026-09-22"
    }
  ]
}

Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429

POST /clinic/bank-feed/connections/{id}/disconnect

Disconnect a bank link

Reversible: the connection survives disabled (its movements stay in the ledger), stops syncing and stops counting as a billed bank from the next period. Requires clinic_money:write.

Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.

ParámetroEnTipoObligatorioRestricciones
idpathuuid
curl -X POST https://api.vitrinadev.com/api/v1/clinic/bank-feed/connections/<id>/disconnect \
  -H "Authorization: Bearer $VITRINA_KEY"

Responde: 204 · 400 · 401 · 403 · 404 · 409 · 429

POST /clinic/bank-feed/connections/{id}/sync

Sincronizar ahora — enqueue a pull of one bank link

Enqueues the SAME job the daily tick uses; the stable per-connection jobId dedups with an in-flight sync. Requires clinic_money:write.

Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.

ParámetroEnTipoObligatorioRestricciones
idpathuuid
curl -X POST https://api.vitrinadev.com/api/v1/clinic/bank-feed/connections/<id>/sync \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (202)

{
  "data": {
    "enqueued": true
  }
}

Responde: 202 · 400 · 401 · 403 · 404 · 409 · 429

POST /clinic/bank-feed/email/pull

Re-read bank e-mails still in the inbox for a window

Runs the e-mail source of the bank feed over [from, to] (Santiago days, ≤ 92 days): bank comprobantes that are still conversations in a connected mailbox become bank_movement rows (provenance backfill — historical, never announced to anyone). Idempotent. Requires clinic_money:write.

Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.

curl -X POST https://api.vitrinadev.com/api/v1/clinic/bank-feed/email/pull \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "2026-09-01",
    "to": "2026-09-22"
  }'

Ejemplo de respuesta (200)

{
  "data": {
    "drafts": 0,
    "inserted": 3,
    "deduped": 1,
    "cross_source_twins": 1
  }
}

Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429

POST /clinic/bank-feed/fintoc/connect

Connect a bank through Fintoc

Send the exchange_token Fintoc's widget returns (or a link_token). The server swaps it for the long-lived link token, stores it encrypted, and queues the first pull. Requires the bank_feed_fintoc add-on — without it the answer is 402 ENTITLEMENT_NOT_ACTIVE (the upsell). Reconnecting the same bank updates its connection. Requires clinic_money:write.

Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.

curl -X POST https://api.vitrinadev.com/api/v1/clinic/bank-feed/fintoc/connect \
  -H "Authorization: Bearer $VITRINA_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "exchange_token": "exch_7f3a9b2c1d"
  }'

Ejemplo de respuesta (201)

{
  "data": {
    "id": "bf0bf0bf-0000-4000-8000-000000000001",
    "provider": "fintoc",
    "institution_name": "Banco de Chile",
    "holder_name": "Clínica Ejemplo SpA",
    "accounts": [
      {
        "id": "acc_9Xz2Lm",
        "number_masked": "••••4821"
      }
    ],
    "enabled": true,
    "connected_at": "2026-09-20T14:02:11.000Z",
    "disconnected_at": null,
    "last_sync_at": "2026-09-22T09:00:04.000Z",
    "last_sync_status": "ok",
    "last_sync_error": null,
    "sync_cursor": "2026-09-22"
  }
}

Responde: 201 · 400 · 401 · 403 · 404 · 409 · 429

GET /clinic/bank-feed/sources

Bank feed sources available to this clinic

The e-mail rail (free, always on), Fintoc (optional add-on bank_feed_fintoc, billed per connected bank per month at the provider's list price — price_clp_per_bank_month is null until it is set) and BCI API Market (not configured until the partner approval lands). Requires clinic_money:read.

Connected apps: every patient and contact in the response is a Seudónimo de paciente — initials plus a stable number, "M.F. · #1001" — unless the clinic allowed patient names, with RUT, phone and email masked in free text and meta.patient_privacy saying so. Clinical alerts (flags) are withheld in both modes, and a non-JSON body (an export, a file) is refused with 403 CONNECTED_APP_SENSITIVE_DATA.

curl https://api.vitrinadev.com/api/v1/clinic/bank-feed/sources \
  -H "Authorization: Bearer $VITRINA_KEY"

Ejemplo de respuesta (200)

{
  "data": {
    "email": {
      "available": true,
      "billed": false
    },
    "fintoc": {
      "configured": true,
      "entitled": true,
      "feature": "bank_feed_fintoc",
      "price_clp_per_bank_month": null,
      "connected_banks": 1
    },
    "bci_api_market": {
      "configured": false,
      "reason": "BCI API Market production access is pending partner approval."
    }
  }
}

Responde: 200 · 400 · 401 · 403 · 404 · 409 · 429

En esta página