> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usecroma.com/llms.txt
> Use this file to discover all available pages before exploring further.

# DIAN

> Validate a Colombian electronic invoice by CUFE and NIT against DIAN's registry, and search DIAN's published tax doctrine of oficios and conceptos by text.

Resolves records published by DIAN (Dirección de Impuestos y Aduanas
Nacionales): the electronic-invoice registry, and the compilation of tax
doctrine (oficios, conceptos) with the norms and rulings compiled alongside it.

## Electronic document

`POST /co/dian/electronic-document/v1`

| Field | Type | Notes |
| - | - | - |
| `cufe` | string | **Required.** The document's CUFE/CUDE or UUID (30-100 chars). |
| `document_number` | string | **Required.** NIT of the emisor or receptor (4-15 digits, no verification digit). |
| `include_pdf` | boolean | Optional. When `true`, the response includes `pdf_url`, the URL of the official PDF representation of the document. Default `false`. |
| `cache` | boolean | Optional. `false` skips the stored result for this document and reads the registry again; the fresh answer replaces the stored one. Default `true`. |

```bash theme={"dark"}
curl https://api.croma.run/co/dian/electronic-document/v1 \
  -H "Authorization: Bearer $CROMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "cufe": "0123456789abcdef...0123456789abcdef", "document_number": "900123456" }'
```

The response returns the document's parties, totals, current legitimate holder,
validations, and events:

| Field | Notes |
| - | - |
| `found` | `true` when the CUFE resolves and the NIT matches the emisor or the receptor; `false` when the document is not registered or the NIT matches neither party. |
| `document_type` | Document class label, e.g. "Factura electrónica". |
| `issuer` / `recipient` | `{ nit, name }` of the emisor and receptor. |
| `total` / `taxes` | Document total and tax lines, in COP, as the registry publishes them: whole pesos, with centavos rounded by the source. The exact amounts are on the official PDF (`include_pdf`). |
| `legitimate_holder` | Current legitimate holder (tenedor legítimo) in the registry. |
| `pdf_url` | Official PDF representation of the document. `null` unless `include_pdf` was `true` and the document was found. The issuer may protect it with a password; try, in order: the issuer's NIT without check digit (`issuer.nit`), the recipient's document number without check digit (`recipient.nit`), and the recipient's NIT with its check digit. If none works, paste the CUFE into [DIAN's public catalog](https://catalogo-vpfe.dian.gov.co/User/SearchDocument) to download DIAN's own graphical representation. |
| `validations` | Document validations: `name`, `result` and `detail`. |
| `events` | The electronic-invoice event history, one row each: `code` (`030` acuse de recibo, `032` recibo del bien o servicio, `033` aceptación expresa, `036`, `037`...), `name`, `date`, the event's `issuer` and `recipient` (`{ nit, name }`), its `cude`, and `description`, the whole row as one string. |

```json theme={"dark"}
{
  "code": "032",
  "name": "Recibo del bien o prestación del servicio",
  "date": "2026-02-05",
  "issuer": { "nit": "900123456", "name": "ACME SAS" },
  "recipient": { "nit": "800654321", "name": "BANCO XYZ" },
  "cude": "6fc8dbca25dffe01f9da...",
  "description": "032 · Recibo del bien o prestación del servicio · 2026-02-05 · 900123456 · ACME SAS · 800654321 · BANCO XYZ · Ver detalle"
}
```

<Note>
  A result is reused for **24 hours** per `cufe`, `document_number` and
  `include_pdf` (`X-Cache: HIT`), so an event filed after the first lookup does
  not show until the window ends. When you know the record changed, send
  `"cache": false` to read the registry again: the answer is `X-Cache: MISS`,
  it is charged as a new request, and it replaces the stored one.
</Note>

<Note>
  This lookup can take longer than a typical request. It's an
  [async job](/async-jobs). By default the request waits inline and returns
  `{ data }`, or you can poll / use a `callback_url`.
</Note>

## Doctrine search

`POST /co/dian/doctrina-search/v1`

Full-text search over DIAN's published doctrine and the legal compilation kept
with it: oficios, conceptos, decretos, resoluciones, leyes, and high-court
rulings.

| Field | Type | Notes |
| - | - | - |
| `query` | string | **Required.** Search terms (2-300 characters). |
| `document_type` | string | Optional. Filter by type, e.g. `Oficios`, `Conceptos`, `Decretos`. |
| `year` | string | Optional. Filter by year of issue (`yyyy`). |
| `page` | number | Optional. 1-based page (default 1). |
| `per_page` | number | Optional. Results per page, 1-100 (default 20). |

```bash theme={"dark"}
curl https://api.croma.run/co/dian/doctrina-search/v1 \
  -H "Authorization: Bearer $CROMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "query": "dividendos", "document_type": "Conceptos" }'
```

| Field | Notes |
| - | - |
| `query`, `document_type`, `year` | The terms and filters applied. |
| `page`, `per_page` | The page returned and its size. |
| `total` | Matches after filters. |
| `count` | Results on this page. |
| `capped` | `true` when the source returned more matches than are retrievable; narrow the query. |
| `results` | Matching documents, each with `document_id`, `title`, `document_type`, `number`, `year`, `issuer`, `summary`, `excerpt`, and `url`. |

Pass a result's `document_id` to the lookup below to read the full text. The id
is the document's own identifier and does not always match its visible label, so
always take it from a search result rather than composing it.

## Doctrine document

`POST /co/dian/doctrina/v1`

| Field | Type | Notes |
| - | - | - |
| `document_id` | string | **Required.** The `document_id` from a search result, e.g. `oficio_dian_18075_2023`. |
| `offset` | number | Optional. First character to return (default 0). |
| `limit` | number | Optional. Characters to return, 1000 to 1000000 (default 200000). |

```bash theme={"dark"}
curl https://api.croma.run/co/dian/doctrina/v1 \
  -H "Authorization: Bearer $CROMA_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "document_id": "oficio_dian_18075_2023" }'
```

| Field | Notes |
| - | - |
| `found` | `false` when no document carries that id; `content` is then `null`. |
| `document_id` | The id queried. |
| `title` | Official title, e.g. "Concepto 18075 de 2023". |
| `content` | The requested range: `text`, `offset`, `total_length`, `has_more`, `next_offset`. |
| `url` | Public URL of the document. |

Most oficios and conceptos fit in a single response. Compiled norms run to
millions of characters, so the body comes back in ranges: read
`content.total_length` for the full size, and while `content.has_more` is `true`
request the next range with `offset` set to `content.next_offset`.

<Card title="Full reference" icon="code" href="/api-reference/overview">
  Full schema and an interactive playground.
</Card>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.