# Connectors (/en/docs/referencia/conectores)

Base: `https://api.facturia.cl/v1`. Every endpoint in this chapter authenticates with `Authorization: Bearer` unless stated otherwise, and the error envelope is the one in [Errors](/en/docs/errores).

| Method   | Path                                                                        | What it does                                   |
| -------- | --------------------------------------------------------------------------- | ---------------------------------------------- |
| `GET`    | [`/connections`](#get-connections)                                          | List connector connections for this empresa    |
| `POST`   | [`/connections`](#post-connections)                                         | Create a Fintoc bank/card connection           |
| `GET`    | [`/connections/{connection_id}`](#get-connections-connection-id)            | Retrieve a connection                          |
| `DELETE` | [`/connections/{connection_id}`](#delete-connections-connection-id)         | Disconnect (revokes the link, stops ingestion) |
| `POST`   | [`/connections/{connection_id}/sync`](#post-connections-connection-id-sync) | Force a movement sync (async)                  |
| `GET`    | [`/tax/statements`](#get-tax-statements)                                    | List uploaded cartolas                         |
| `POST`   | [`/tax/statements`](#post-tax-statements)                                   | Upload a cartola (CSV/XLSX) to create expenses |

## `GET /connections` [#get-connections]

**List connector connections for this empresa**

Connectors (bank feeds, accounting integrations) linked to the empresa, with each one's last sync and status.

```bash
curl -sS https://api.facturia.cl/v1/connections \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type    | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Facturia-Empresa` | header | —        | string  | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `limit`            | query  | —        | integer |                                                                                                                                                                                                                                                                                                                                                             |
| `cursor`           | query  | —        | string  | Opaque cursor from a previous response's `next_cursor`.                                                                                                                                                                                                                                                                                                     |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body                |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- |
| `200`     | A list of connections.                                                                                                                                                                                                                                                                                  | lista de Connection |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse       |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse       |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse       |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse       |

## `POST /connections` [#post-connections]

**Create a Fintoc bank/card connection**

Returns `status: pending_link` with a `link_url`. Send the user through it once; from then
on each sync keeps the foreign-currency movements, converts them into `expense` objects
(`source: "fintoc"`, `fx_source: "card_rate"`) and lets the tipo-46 detector run.
Credentials stay with Fintoc — Facturia stores a link token, never a bank password.
`connection.linked` fires when the link completes.

IN TEST MODE there is no link to complete, so the connection is born `active`, `link_url`
is `null` and `connection.linked` fires with the `201` — §4.1's "complete in-process
simulation", and the only way the connector surface is exercisable before a real bank is
involved.

```bash
curl -sS -X POST https://api.facturia.cl/v1/connections \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"provider":"fintoc"}'
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `Idempotency-Key`  | header | —        | string | Client-generated key, unique per logical operation, retained 24h and scoped to (account, empresa, endpoint). Replays return the original response with `Facturia-Idempotent-Replay: true`. Same key + different body → `409`.                                                                                                                               |

**Body**

| Field            | Type                          | Required | Notes               |
| ---------------- | ----------------------------- | -------- | ------------------- |
| `provider`       | `fintoc`                      | yes      |                     |
| `account_types`  | `checking` · `credit_card`\[] | —        |                     |
| `sync_frequency` | `daily` · `weekly` · `manual` | —        | Default: `"daily"`. |
| **Responses**    |                               |          |                     |

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `201`     | The connection, awaiting the link flow.                                                                                                                                                                                                                                                                 | Connection    |
| `400`     | Malformed or missing input.                                                                                                                                                                                                                                                                             | ErrorResponse |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |

## `GET /connections/{connection_id}` [#get-connections-connection-id]

**Retrieve a connection**

One connector's configuration and sync history, without its stored credentials.

```bash
curl -sS https://api.facturia.cl/v1/connections/con_01K2RJ7B2W4M \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `connection_id`    | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `200`     | The connection.                                                                                                                                                                                                                                                                                         | Connection    |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `404`     | No such object under this key.                                                                                                                                                                                                                                                                          | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |

## `DELETE /connections/{connection_id}` [#delete-connections-connection-id]

**Disconnect (revokes the link, stops ingestion)**

Expenses already created from this connection are kept.

```bash
curl -sS -X DELETE https://api.facturia.cl/v1/connections/con_01K2RJ7B2W4M \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `connection_id`    | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `204`     | Disconnected.                                                                                                                                                                                                                                                                                           | —             |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |

## `POST /connections/{connection_id}/sync` [#post-connections-connection-id-sync]

**Force a movement sync (async)**

`422 connection_not_linked` on a connection that is not `active`: `tax_bank_sync` only
looks at linked rows, so queueing one would be a job that runs, does nothing, and reports
`succeeded`.

In TEST MODE the job comes back already `succeeded` — there is no bank to call and no
worker to wait for, so a `queued` job would never move (§4.1).

```bash
curl -sS -X POST https://api.facturia.cl/v1/connections/con_01K2RJ7B2W4M/sync \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `connection_id`    | path   | yes      | string |                                                                                                                                                                                                                                                                                                                                                             |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `Idempotency-Key`  | header | —        | string | Client-generated key, unique per logical operation, retained 24h and scoped to (account, empresa, endpoint). Replays return the original response with `Facturia-Idempotent-Replay: true`. Same key + different body → `409`.                                                                                                                               |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body          |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
| `202`     | Sync job accepted — `queued` in live, already `succeeded` in test.                                                                                                                                                                                                                                      | Job           |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse |
| `422`     | Well-formed but violates a domain rule — folios exhausted, acuse window closed.                                                                                                                                                                                                                         | ErrorResponse |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse |

## `GET /tax/statements` [#get-tax-statements]

**List uploaded cartolas**

Bank or card statements imported for the empresa, the raw material `tax:write` imports feed into the expense ledger and its suggestions.

```bash
curl -sS https://api.facturia.cl/v1/tax/statements \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA"
```

**Parameters**

| Parameter          | In     | Required | Type    | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Facturia-Empresa` | header | —        | string  | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `limit`            | query  | —        | integer |                                                                                                                                                                                                                                                                                                                                                             |
| `cursor`           | query  | —        | string  | Opaque cursor from a previous response's `next_cursor`.                                                                                                                                                                                                                                                                                                     |

**Responses**

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body               |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `200`     | A list of statement imports.                                                                                                                                                                                                                                                                            | lista de Statement |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse      |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse      |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse      |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse      |

## `POST /tax/statements` [#post-tax-statements]

**Upload a cartola (CSV/XLSX) to create expenses**

Asynchronous. The returned job's `result` carries `rows_read`, `expenses_created`,
`duplicates_skipped` and per-row `errors[]`. Deduplication is by
(empresa, date, amount\_original, currency, provider) plus `external_id` where present,
so re-uploading an overlapping cartola is safe.

`202` when this upload created the import; `200` with the ORIGINAL job when the exact same
BYTES were uploaded before for this empresa (a `sha256` taken before anything touches
storage) — no second storage object, no second parse. Same body either way.

```bash
curl -sS -X POST https://api.facturia.cl/v1/tax/statements \
  -H "Authorization: Bearer $FACTURIA_KEY" \
  -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)" \
  -F "file=…" \
  -F "format=…"
```

**Parameters**

| Parameter          | In     | Required | Type   | Notes                                                                                                                                                                                                                                                                                                                                                       |
| ------------------ | ------ | -------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Facturia-Empresa` | header | —        | string | Target empresa: canonical RUT (`77928532-4`) or empresa id (`emp_…`). Required on every empresa-scoped call unless the key is an empresa token. This header is the ONLY mechanism: there is no `?empresa=` query parameter and no `empresa` body field. Omitted where required → `400 empresa_required`; outside the allowlist → `403 empresa_not_allowed`. |
| `Idempotency-Key`  | header | —        | string | Client-generated key, unique per logical operation, retained 24h and scoped to (account, empresa, endpoint). Replays return the original response with `Facturia-Idempotent-Replay: true`. Same key + different body → `409`.                                                                                                                               |

**Body (multipart/form-data)**

| Field              | Type                                                                                          | Required | Notes                                            |
| ------------------ | --------------------------------------------------------------------------------------------- | -------- | ------------------------------------------------ |
| `file`             | string                                                                                        | yes      |                                                  |
| `format`           | `auto` · `generic_csv` · `santander` · `bci` · `banco_chile` · `itau` · `scotiabank` · `xlsx` | —        | Default: `"auto"`.                               |
| `default_currency` | string                                                                                        | —        | Applied to rows whose currency column is absent. |
| **Responses**      |                                                                                               |          |                                                  |

| Code      | Meaning                                                                                                                                                                                                                                                                                                 | Body               |
| --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ |
| `200`     | These exact bytes were already uploaded. The ORIGINAL import job.                                                                                                                                                                                                                                       | StatementImportJob |
| `202`     | Import job accepted.                                                                                                                                                                                                                                                                                    | StatementImportJob |
| `400`     | Malformed or missing input.                                                                                                                                                                                                                                                                             | ErrorResponse      |
| `401`     | Missing, malformed or revoked key.                                                                                                                                                                                                                                                                      | ErrorResponse      |
| `403`     | Valid key, not permitted — scope, empresa allowlist, or mode.                                                                                                                                                                                                                                           | ErrorResponse      |
| `429`     | Too many requests.                                                                                                                                                                                                                                                                                      | ErrorResponse      |
| `default` | An error not otherwise enumerated for this operation, in the same §5.5 envelope as every other refusal. Branch on `error.code`, never on the HTTP status alone or on `error.message` — a code this operation has not been seen to throw yet is still safer to route on than a string meant for a human. | ErrorResponse      |
