# F29 — proposal and filing (/en/docs/impuestos/f29)

## The proposal [#the-proposal]

```bash
curl https://api.facturia.cl/v1/tax/f29/proposals/2026-07 \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA"
```

```json
{
  "id": "f29_01K2RC4T8V2M",
  "object": "f29_proposal",
  "period": "2026-07",
  "status": "ready",
  "computed_at": "2026-08-14T06:15:00Z",
  "based_on": { "rcv_synced_at": "2026-08-14T06:12:03Z", "purchases": 42, "sales": 118 },
  "summary": {
    "iva_debito": 3210000,
    "iva_credito": 1985000,
    "iva_retenido": 190000,
    "remanente_anterior": 0,
    "ppm": 148000,
    "total_payable": 1373000,
    "due_date": "2026-08-20"
  },
  "codes": [
    { "code": 538, "label": "Total débitos",                          "value": 3210000 },
    { "code": 537, "label": "Total créditos",                         "value": 1985000 },
    { "code": 39,  "label": "IVA total retenido (facturas de compra)","value": 190000 },
    { "code": 519, "label": "Crédito IVA por facturas de compra",     "value": 190000 },
    { "code": 520, "label": "Crédito IVA — documentos electrónicos",  "value": 1795000 },
    { "code": 77,  "label": "Remanente crédito fiscal período siguiente", "value": 0 },
    { "code": 62,  "label": "PPM neto determinado",                   "value": 148000 },
    { "code": 91,  "label": "Total a pagar dentro del plazo",         "value": 1373000 }
  ],
  "observations": [
    { "code": "rcv_pendientes", "severity": "warning", "message": "3 documentos de compra están en estado PENDIENTE y no fueron considerados.", "entry_ids": ["rcv_...", "rcv_...", "rcv_..."] }
  ],
  "upload_file_url": "https://api.facturia.cl/v1/tax/f29/proposals/2026-07/upload_file",
  "filing_id": null
}
```

Two things worth being clear about:

**Facturia computes this proposal** from your synced RCV — the purchase-and-sales register the SII,
Chile's tax authority, keeps for you — plus your own PPM (monthly provisional income tax) and
remanente (credit carried forward) parameters. The SII prefills its own F29, the monthly IVA return,
for its own portal, but publishes no API for it. Where the two differ, our `observations` normally
tell you why (unregistered purchases, pending entries, characterization gaps) — and you can always
compare against the SII's screen before you file.

**The `codes` list is what the upload file will carry**, code by code. Nothing gets filed that you
can't read here first.

## The upload file [#the-upload-file]

```bash
curl -L https://api.facturia.cl/v1/tax/f29/proposals/2026-07/upload_file \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" -o f29-202607.txt
```

It is the SII's fixed-format `.txt`, ready to upload by hand if you'd rather do it yourself.

## Recompute and override codes [#recompute-and-override-codes]

```bash
curl -X POST https://api.facturia.cl/v1/tax/f29/proposals/2026-07/recompute \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
  -H "Content-Type: application/json" \
  -d '{"overrides":[{"code":62,"value":150000,"reason":"PPM ajustado por tasa variable"}]}'
```

### Code 048 is an external input [#code-048-is-an-external-input]

> **Trap — Facturia does not sync the payroll ledger**
>
> Code **048** (withholding of employees' *impuesto único*, the tax on employment income, art. 74 N°1)
> comes out of payroll, not out of the RCV. Facturia has no access to that information, so it cannot
> compute it.
>
> If your company has employees, you supply that code yourself with `overrides` on `recompute` before
> you file. An F29 filed with 048 at zero when it should carry a value is an incorrect return, and it
> is not an error the API can catch for you.

```bash
curl -X POST https://api.facturia.cl/v1/tax/f29/proposals/2026-07/recompute \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
  -H "Content-Type: application/json" \
  -d '{"overrides":[{"code":48,"value":656814,"reason":"Retención art. 74 N°1 — libro de remuneraciones julio"}]}'
```

Every `override` is stored with its `reason`, which is what matters the day someone has to explain
where a figure came from.

## Filing [#filing]

> **Trap — There is no SII web service for filing an F29**
>
> The only non-manual channel is the SII's *Upload* flow: a fixed-format `.txt` sent through an
> authenticated browser session. Facturia automates exactly that — a certificate-authenticated session
> driving the real upload — and models it as an async job with honest states, because that is what it
> is.
>
> If the SII changes that form, the job fails and we tell you. There is no stable API underneath to
> protect us.

```bash
curl -sS https://api.facturia.cl/v1/tax/f29/filings \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
  -H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" \
  -d '{"period":"2026-07","proposal_id":"f29_01K2RC4T8V2M","confirm_total_payable":1373000}'
```

```json
{
  "id": "f29fil_01K2RD9K3M8T",
  "object": "f29_filing",
  "period": "2026-07",
  "status": "queued",
  "declared": { "total_payable": 1373000 },
  "attempts": 0,
  "folio": null,
  "receipt_url": null,
  "created_at": "2026-08-14T14:30:02Z"
}
```

### The guardrails [#the-guardrails]

**`confirm_total_payable` is required** and must equal the figure in the proposal, or you get
`422 f29_amount_confirmation_mismatch`. Filing a tax return is not something an API should let you do
by accident.

That field does two things at once: it forces you to read the proposal before filing, and it forces
the figure to appear explicitly in your own code — which means it appears explicitly on whatever
screen or message your system shows before the button gets pressed.

### The job states [#the-job-states]

| `status`    | Meaning                                                                    |
| ----------- | -------------------------------------------------------------------------- |
| `queued`    | Accepted; waiting for a filing worker                                      |
| `preparing` | Generating and validating the upload file                                  |
| `uploading` | Authenticated session open at the SII, sending                             |
| `submitted` | Uploaded; waiting for the SII's acknowledgement                            |
| `accepted`  | Filed. `folio` and `receipt_url` are populated                             |
| `rejected`  | The SII rejected the return; `errors[]` explains                           |
| `failed`    | We couldn't complete the submission (SII down, session refused). Retriable |

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

curl -G https://api.facturia.cl/v1/tax/f29/filings \
  -H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" -d "period[gte]=2026-01"
```

Events: `tax.f29.filing.submitted`, `tax.f29.filing.succeeded`, `tax.f29.filing.rejected`,
`tax.f29.filing.failed`.

A filing supports neither `PATCH` nor `DELETE`. A filed F29 is corrected with a *rectificatoria*, an
amended return, which is out of scope for v1.

## Automatic filing [#automatic-filing]

`auto_file_f29` ships **off**, like every automation.

| Setting                     | Default | Effect                                                                        |
| --------------------------- | ------- | ----------------------------------------------------------------------------- |
| `auto_file_f29`             | `false` | Files the period's F29 on `auto_file_f29_day`                                 |
| `auto_file_f29_day`         | `18`    | The day of the month it files on                                              |
| `auto_file_f29_max_payable` | `0`     | Only files on its own if the computed `total_payable` is at or below this cap |

With the cap at 0 — the factory value — only a zero or in-your-favour position files itself, and any
month where you actually owe IVA waits for you. Raise the cap deliberately, empresa by empresa.

> **Trap — A proposal with observations never files itself**
>
> If there are `observations` with `severity: error`, automatic filing is suppressed and
> `tax.f29.review_required` fires. Filing an F29 is a legally binding declaration: we ship the
> capability because a small company that wants it shouldn't have to log into the SII on the 18th, but
> it is opt-in per empresa, capped, and it publishes `tax.f29.filing.succeeded` / `.failed` so you can
> supervise it.
