Foreign digital services and tipo 46
The three-step cycle — enter the charge, read the suggestion, confirm — and where the charges come from if you don't have them.
Since Ley 21.210, when a Chilean IVA (value-added tax) taxpayer buys digital services from a foreign provider, the buyer becomes the taxable party: the provider charges no IVA, the buyer self-issues a factura de compra (tipo 46) with the IVA fully withheld — a purchase invoice it raises in the supplier's name — and takes that IVA as an input credit.
On a million pesos a month of advertising spend, that is CLP 190.000 a month recovered. Almost nobody does it, because it means noticing every foreign charge and issuing a document for each one.
The API models it as a three-step cycle.
1. Enter the charge
curl -sS https://api.facturia.cl/v1/tax/expenses \
-H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" -H "Content-Type: application/json" \
-d '{
"provider": { "name": "Google Ads", "country": "IE" },
"description": "Google Ads — julio 2026",
"amount_original": 1050.00,
"currency": "USD",
"date": "2026-07-31",
"fx_rate": 952.4,
"fx_source": "card_rate",
"external_id": "card-txn-99381"
}'Trap
You supply the exchange rate
fx_rate is required every time currency is not CLP. Omit it and the call fails with
400 fx_rate_required.
We don't invent an exchange rate, because that figure sets the peso base of a tax document, and guessing it would make us the authors of your tax position.
Which fx_source to use
- Recommended:
card_rate— the settlement rate your card issuer actually applied, that is, the pesos that really left the account. It is the figure you can defend with a cartola (a bank statement), and it is the one this documentation recommends. sii_observado(the dólar observado published for that date) andcustomare accepted too, and are stored verbatim on the expense and on the resulting document.
A documented caveat
Which exchange rate is definitively correct for a tipo 46 over foreign digital services is not settled by any ruling we are willing to cite. Our recommendation is a practitioner's, not tax advice, and it is under review with an accountant. If that review changes the guidance, we will say so in the changelog instead of quietly changing the default.
What you send is what we use, and it stays visible on the document forever — which is the property that matters if the criterion is ever questioned.
2. Read the suggestion
curl -G https://api.facturia.cl/v1/tax/suggestions \
-H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
-d type=emit_46 -d status=open{
"id": "sug_01K2RE2X7Q9V",
"object": "suggestion",
"type": "emit_46",
"status": "open",
"period": "2026-07",
"confidence": 0.96,
"reason": "Cargo en moneda extranjera de un proveedor de servicios digitales sin IVA. Corresponde emitir factura de compra (46) con IVA totalmente retenido.",
"estimated_benefit": { "iva_credit": 190000 },
"source": { "object": "expense", "id": "exp_01K2RE1M4T8P" },
"proposed_document": {
"tipo_dte": 46,
"receptor": { "rut": "55555555-5", "legal_name": "Google Ads", "foreign": true },
"items": [{ "description": "Google Ads — julio 2026", "quantity": 1, "unit_price": 1000000 }],
"withholding": { "iva": "total" }
},
"f29_effect": [ { "code": 39, "value": 190000 }, { "code": 519, "value": 190000 } ],
"created_at": "2026-08-01T03:12:00Z"
}f29_effect is the useful part: it tells you up front which codes on the F29 (the monthly IVA
return) the document will land in if you confirm it.
3. Confirm or dismiss
# Confirmar — emite el tipo 46 y devuelve el documento
curl -X POST https://api.facturia.cl/v1/tax/suggestions/sug_01K2RE2X7Q9V/confirm \
-H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)"
# …o descartarla (con un motivo del que aprendemos)
curl -X POST https://api.facturia.cl/v1/tax/suggestions/sug_01K2RE2X7Q9V/dismiss \
-H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
-H "Content-Type: application/json" -d '{"reason":"not_digital_service"}'With auto_emit_46: true on the empresa, step 3 happens on its own for suggestions under the
configured cap (auto_emit_46_max_amount), and you find out through document.created plus
tax.suggestion.auto_confirmed. Above the cap, it stays a suggestion.
The suggestion catalogue
type | Detects |
|---|---|
emit_46 | Foreign digital services that ought to be self-invoiced |
missing_characterization | Entries in the RCV (the purchase-and-sales register) that are going to distort the F29 |
folios_low | A document type about to run out of folios (its pre-authorised numbers) |
unclaimed_credit | A received document still in PENDIENTE past the close of the period |
Events: tax.suggestion.created, tax.suggestion.auto_confirmed.
Where the charges come from if you don't have them
POST /v1/tax/expenses assumes you already have the charge's data. Two first-party connectors take
that assumption away, and both feed exactly the same expense ledger — an expense created by a
connector is indistinguishable from one you posted yourself, except for its source.
Fintoc — bank and card transactions
curl -sS 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","account_types":["checking","credit_card"],"sync_frequency":"daily"}'{
"id": "con_01K2RJ7B2W4M",
"object": "connection",
"provider": "fintoc",
"status": "pending_link",
"link_url": "https://facturia.cl/connect/con_01K2RJ7B2W4M",
"accounts": [],
"sync_frequency": "daily",
"last_synced_at": null,
"created_at": "2026-08-14T15:02:11Z"
}You send the person through link_url once and transactions start arriving. Each sync keeps the
foreign-currency transactions — that is all we look at: this is a tax function, not a bank-feed
product — turns them into an expense with source: "fintoc" and the settlement rate the issuer
reported as fx_rate / fx_source: card_rate, and lets the normal detector run.
The credentials live at Fintoc; Facturia stores a link token, never a bank password.
Events: connection.linked, connection.sync_succeeded, connection.sync_failed,
connection.requires_relink.
`connection.requires_relink` is not optional
It is the near-universal failure mode of bank feeds. We publish it as an event precisely so an assistant can ask the person to reconnect, instead of the feed going quiet and nobody noticing that expenses stopped appearing.
Cartola — CSV/XLSX upload
For the banks Fintoc doesn't cover, and for the accountant who already has the cartola in a spreadsheet.
curl -sS https://api.facturia.cl/v1/tax/statements \
-H "Authorization: Bearer $FACTURIA_KEY" -H "Facturia-Empresa: $EMPRESA" \
-H "Idempotency-Key: $(uuidgen)" \
-F "[email protected]" \
-F "format=auto" \
-F "default_currency=USD"The import is asynchronous and returns a job whose result reports rows_read, expenses_created,
duplicates_skipped and per-row errors[]. format=auto sniffs the common Chilean bank layouts;
pass an explicit format when it gets one wrong.
Deduplication is on (empresa, date, amount_original, currency, provider) plus your external_id
when there is one, so re-uploading an overlapping cartola is safe — which is how people normally use
statement files, and an importer that duplicates on the overlap is worse than no importer at all.
What is not in v1
Pulling the invoices straight from Meta Ads, Google Ads and company is the obvious next step and is
explicitly out of scope for v1. Every platform is a different OAuth surface with its own
billing-export quirks, and Fintoc plus statement upload already catch the same charges from the
paying side. In the meantime, use POST /v1/tax/expenses for the platform charges you want to record
in more detail than a card line allows.