# Lista 69-B del SAT y proveedores sancionados en LatAm (`opendata-cr/latam-sanctions-screening`) Actor

Revise RFC, CNPJ, NIT y cédulas jurídicas en listas oficiales de empresas sancionadas: lista 69-B del SAT (México), CEIS y CNEP (Brasil), SECOP (Colombia), SICOP (Costa Rica) y BID. También busca por nombre con coincidencia aproximada. Debida diligencia de proveedores en lote.

- **URL**: https://apify.com/opendata-cr/latam-sanctions-screening.md
- **Developed by:** [Tornwar](https://apify.com/opendata-cr) (community)
- **Categories:** Business, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 coincidencias

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## LatAm Sanctioned Suppliers Screening

Revise NIT, CNPJ, RFC, cédulas jurídicas y nombres de empresa contra las listas oficiales de proveedores sancionados e inhabilitados de Colombia, Brasil, México, Costa Rica y el Banco Interamericano de Desarrollo (BID).

Solo empresas. Las personas físicas no entran al índice ni al dataset.

Aviso: este resultado sirve para debida diligencia. No es una determinación de inhabilidad ni un dictamen legal. Confirme cada acto en la fuente oficial antes de tomar una decisión.

[English version below](#english)

### Fuentes

| País | Lista | Qué se indexa | Licencia |
| --- | --- | --- | --- |
| Colombia | SECOP II (`it5q-hg94`) y SECOP I Multas y Sanciones (`4n4q-k399`), datos.gov.co | Sanciones a empresas. Se descartan filas de prueba. | CC BY-SA 4.0 |
| Brasil | CEIS y CNEP, Portal da Transparência (CGU) | Empresas con CNPJ de 14 dígitos. | Publicación oficial (Lei nº 12.846/2013) |
| México | SAT, artículo 69-B, listado completo | RFC de empresa (12 caracteres) en todas las situaciones: Definitivo, Presunto, Desvirtuado y Sentencia Favorable. | Publicación oficial del SAT |
| Regional | BID, firmas sancionadas | Solo `Entity = Firm`. | CC BY 4.0 |
| Costa Rica | SICOP, archivo `SancionProveedores` del Observatorio de Compra Pública | Cédulas jurídicas de los últimos 36 meses, sin duplicados. | Datos abiertos, Decreto Ejecutivo 40199-MP |

Al 4 de octubre de 2026 el índice tiene 29.922 sanciones a empresas: 1.581 de Colombia, 16.376 de Brasil, 10.970 de México, 802 del BID y 193 de Costa Rica.

Atribución Colombia: Agencia Nacional de Contratación Pública - Colombia Compra Eficiente. Datos abiertos en datos.gov.co, licencia CC BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0/).

Atribución BID: Inter-American Development Bank (Banco Interamericano de Desarrollo). Sanctioned firms, licencia CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/).

Cada resultado de Colombia y del BID incluye los campos `license` y `attribution`.

No se incluyen la lista de inhabilitados del Banco Mundial, el SIRI de la Procuraduría (Colombia) ni listas de Perú.

### Entrada

```json
{
  "taxIds": ["900593921-7", "19.182.685/0001-62", "AAA080808HL8", "3-101-849778"],
  "names": ["Consultora Tecnodinamica"],
  "fuzzyNameMatch": true,
  "fuzzyThreshold": 92,
  "maxResults": 25,
  "includeUnmatched": true
}
```

| Campo | Valor por defecto | Descripción |
| --- | --- | --- |
| `taxIds` | | NIT, CNPJ, RFC o cédula jurídica. Se ignoran puntos, guiones y la barra del CNPJ. |
| `names` | | Nombre de la empresa. Se busca por aproximación si `fuzzyNameMatch` está activo. |
| `queries` | `[]` | Objetos `{taxId, name, country}` para limitar un nombre a un país, o textos sueltos. |
| `countries` | todos | Códigos ISO (CO, BR, MX, CR). Vacío revisa todas las listas. El BID siempre se consulta y se filtra por el país de la firma. |
| `fuzzyNameMatch` | `true` | Comparación aproximada de nombres. Las coincidencias exactas por identificación no dependen de esto. |
| `fuzzyThreshold` | `92` | De 0 a 100. Con 92 pasa un nombre casi completo y no pasa una sola palabra genérica. |
| `maxResults` | `500` | Tope de coincidencias cobradas. El formulario propone 25. |
| `maxMatchesPerQuery` | `100` | Una empresa puede tener varias sanciones; cada una es una fila. |
| `useCache` / `refreshCache` / `cacheTtlHours` | sí / no / 24 | Caché del índice en un almacén (Key-Value Store) con nombre. |
| `cacheStoreName` | `latam-sanctions-index` | Nombre de ese almacén. |
| `includeUnmatched` | `true` | Guarda las consultas sin coincidencia en el registro `NO_MATCHES`. |

Las consultas en blanco se descartan y no se cobran. Más de 5000 consultas se rechazan antes de descargar las listas.

Un NIT de 9 dígitos coincide con el mismo NIT con dígito de verificación de la DIAN solo si ese dígito es correcto. El RFC conserva sus letras. La cédula jurídica de Costa Rica tiene 10 dígitos y empieza por 2, 3, 4 o 9 (por ejemplo, `3-101-849778`).

### Resultado

Un registro del dataset por coincidencia:

```json
{
  "query": "900593921-7",
  "matchType": "exact_id",
  "score": 100,
  "taxId": "9005939217",
  "taxIdFormatted": "900.593.921-7",
  "name": "JL INGENIEROS OBRAS Y SUMINISTROS LTDA",
  "country": "CO",
  "list": "SECOP I Multas y Sanciones",
  "sanctionType": "Multa / sanción",
  "startDate": "2015-02-20",
  "endDate": null,
  "status": null,
  "sourceUrl": "https://www.contratos.gov.co/consultas/detalleProcesoAACS.do?numProcAACS=26182024",
  "source": "Colombia Compra Eficiente, SECOP I",
  "license": "CC BY-SA 4.0",
  "attribution": "Agencia Nacional de Contratación Pública - Colombia Compra Eficiente. Datos abiertos en datos.gov.co, licencia CC BY-SA 4.0 (https://creativecommons.org/licenses/by-sa/4.0/)."
}
```

`matchType` es `exact_id` o `fuzzy_name`. Las sanciones históricas se mantienen en el índice. En Brasil, `status` es `Vigente` si no hay fecha de fin o si todavía no llegó, y `Finalizada` en otro caso.

Registros del Key-Value Store por defecto:

- `OUTPUT`: totales, eventos cobrados, aviso legal y resumen por fuente.
- `SOURCES_STATUS`: estado de cada fuente (`ok`, filas leídas, empresas, personas excluidas, error).
- `NO_MATCHES`: consultas sin coincidencia. No se cobran como coincidencia.

Si una fuente no responde, las demás siguen. Esa fuente aparece con `ok: false` y el texto del error, y la ejecución termina con éxito si el resto respondió.

### Precios

Pago por evento:

| Evento | Precio | Cuándo se cobra |
| --- | --- | --- |
| `actor-start` | US$0,05 | Una vez por ejecución, con una entrada válida. |
| `id-checked` | US$0,01 | Por cada empresa consultada, tenga o no coincidencia. |
| `match-found` | US$0,02 | Por cada coincidencia escrita en el dataset. |

No hay cargo por registro del dataset aparte de `match-found`. La entrada de ejemplo (5 consultas, 8 coincidencias) cuesta US$0,05 + 5 × US$0,01 + 8 × US$0,02 = US$0,26.

Para terminar una consulta con una coincidencia hace falta un tope de al menos US$0,08005: US$0,00005 de inicio de la plataforma, más US$0,05, US$0,01 y US$0,02. Si el tope es menor, la ejecución se detiene, conserva lo que ya se cobró y termina con éxito, con el mensaje `Se alcanzó el máximo a cobrar de la ejecución; se detuvo después de N resultados.` En ese caso `OUTPUT.stoppedBySpendingLimit` es `true`.

### Caché

El índice se guarda en el Key-Value Store `latam-sanctions-index` (o el nombre en `cacheStoreName`) durante `cacheTtlHours` horas, 24 por defecto. Solo se guarda cuando todas las fuentes seleccionadas respondieron. Con `refreshCache` se vuelve a descargar todo.

### Solo empresas

- Brasil: tipo de persona `F` o CPF de 11 dígitos es persona física. CNPJ de 14 dígitos con tipo `J` o vacío es empresa.
- México: RFC de 13 caracteres es persona física y se excluye. RFC de 12 caracteres es empresa.
- Costa Rica: se indexan solo cédulas jurídicas. Cédulas físicas, extranjeros y DIMEX se excluyen.
- BID: `Entity = Individual` se excluye.
- Colombia: una fila se trata como persona solo si el nombre parece de persona y el número no es un NIT de empresa válido. Marcas como `SAS`, `S.A.` o `LTDA` mantienen la fila.

### Limitaciones

- En SECOP II el código del proveedor muchas veces es un código interno de 8 dígitos y no un NIT. Esas filas se encuentran por nombre, no por NIT exacto.
- Costa Rica cubre las sanciones registradas en los últimos 36 meses. Algunas filas de SICOP traen las fechas vacías y un valor tipo fecha en `status`; se publican tal como vienen.
- La lista del SAT es el listado completo vigente en el sitio del SAT al momento de la ejecución.
- Brasil no publica el archivo todos los días. Se usa el más reciente de los últimos 10 días.
- Las fechas con barra se leen como día/mes/año.

<a id="english"></a>

### English

Screen company tax IDs (NIT, CNPJ, RFC, cédula jurídica) and company names against official debarment and sanctions lists from Colombia, Brazil, Mexico, Costa Rica, and the Inter-American Development Bank (IDB). Companies only: natural persons are excluded from the index and the dataset.

Disclaimer: for due diligence only. This is not a legal finding or a determination of debarment. Confirm each record in the official source before you rely on it.

Sources:

- Colombia: SECOP II and SECOP I fines and sanctions (datos.gov.co). CC BY-SA 4.0. Attribution: Agencia Nacional de Contratación Pública - Colombia Compra Eficiente, datos.gov.co (https://creativecommons.org/licenses/by-sa/4.0/).
- Brazil: CEIS and CNEP (Portal da Transparência, CGU). Official publication.
- Mexico: SAT article 69-B full list. Official publication.
- IDB: Sanctioned firms, Inter-American Development Bank. CC BY 4.0 (https://creativecommons.org/licenses/by/4.0/).
- Costa Rica: SICOP supplier sanctions, last 36 months (Observatorio de Compra Pública). Open data, Decreto Ejecutivo 40199-MP.

Every Colombia and IDB item carries `license` and `attribution` fields.

Input: `taxIds` and/or `names`, optional `countries` filter, fuzzy name matching with a default threshold of 92, and `maxResults` to cap charged matches. See the Spanish section above for the full field list.

Output: one dataset item per match with the query, match type (`exact_id` or `fuzzy_name`), score, tax ID, company name, country, list, sanction type, status, start and end dates, and source URL. The default key-value store holds `OUTPUT` (run summary), `SOURCES_STATUS` (per-source status), and `NO_MATCHES` (queries with no hit). If one source is down, the run continues with the others and reports that source as `ok: false`.

Pricing (pay per event):

| Event | Price | When |
| --- | --- | --- |
| `actor-start` | US$0.05 | Once per run, after the input is validated. |
| `id-checked` | US$0.01 | Per company screened, with or without a match. |
| `match-found` | US$0.02 | Per match written to the dataset. |

The sample input above (5 queries, 8 matches) costs US$0.05 + 5 × US$0.01 + 8 × US$0.02 = US$0.26. One query with one match needs a max charge of at least US$0.08005 (platform start fee US$0.00005 + US$0.05 + US$0.01 + US$0.02). A lower limit stops the run, keeps what was already charged, and finishes as succeeded. The status message is in Spanish: `Se alcanzó el máximo a cobrar de la ejecución; se detuvo después de N resultados.`

# Actor input Schema

## `taxIds` (type: `array`):

NIT, CNPJ, RFC o cédula jurídica. Se aceptan puntos, guiones y la barra del CNPJ. Un NIT de 9 dígitos coincide con el mismo NIT con dígito de verificación. Tax IDs. Punctuation is ignored.

## `names` (type: `array`):

Se buscan por aproximación si la coincidencia aproximada de nombre está activa. No distingue mayúsculas ni tildes. Fuzzy name search. Case and accents are ignored.

## `queries` (type: `array`):

Objetos {"taxId", "name", "country"} cuando un nombre debe limitarse a un país. Un texto suelto se trata como identificación si parece un ID y como nombre si no. Objects tie an ID and a name to one country. A plain string is an ID or a name.

## `countries` (type: `array`):

Códigos ISO. Vacío revisa todas las fuentes. CO, BR, MX y CR limitan la lista de ese país. El BID se incluye siempre y se filtra por el país de la firma. Empty searches every source. IDB firms are filtered by the firm's country.

## `fuzzyNameMatch` (type: `boolean`):

Compara nombres de forma aproximada. Las coincidencias exactas por identificación no dependen de esto. Fuzzy name matching. Exact tax-ID matches do not use it.

## `fuzzyThreshold` (type: `integer`):

De 0 a 100. Con 92 pasa un nombre casi completo y no pasa una sola palabra genérica. 0 to 100.

## `maxResults` (type: `integer`):

Tope de coincidencias cobradas. El formulario propone 25. Cada coincidencia cuesta US$0,02. Si se omite el campo, el tope es 500. Cap on charged matches. The form suggests 25. Each match costs US$0.02. If omitted, the cap is 500.

## `maxMatchesPerQuery` (type: `integer`):

Una empresa puede tener varias sanciones. Cada fila es una coincidencia. One company can have several sanctions. Each row is a match.

## `useCache` (type: `boolean`):

Guarda el índice de empresas en un Key-Value Store con nombre. Mientras la caché no haya vencido, las siguientes ejecuciones no vuelven a descargar las listas. Stores the company index in a named Key-Value Store.

## `refreshCache` (type: `boolean`):

Ignora la caché y vuelve a descargar las listas. Ignore the cache and download the lists again.

## `cacheTtlHours` (type: `integer`):

Pasado este plazo, el índice se reconstruye. After this the index is rebuilt.

## `cacheStoreName` (type: `string`):

Key-Value Store con nombre. No es el dataset de resultados. Named Key-Value Store. It is not the results dataset.

## `includeUnmatched` (type: `boolean`):

Se guardan en el registro NO_MATCHES del Key-Value Store. No se cobran como coincidencia. Written to the NO_MATCHES key-value record. Not charged.

## Actor input object example

```json
{
  "taxIds": [
    "900593921-7",
    "19.182.685/0001-62",
    "AAA080808HL8",
    "3-101-849778"
  ],
  "names": [
    "Consultora Tecnodinamica"
  ],
  "queries": [],
  "countries": [],
  "fuzzyNameMatch": true,
  "fuzzyThreshold": 92,
  "maxResults": 25,
  "maxMatchesPerQuery": 100,
  "useCache": true,
  "refreshCache": false,
  "cacheTtlHours": 24,
  "cacheStoreName": "latam-sanctions-index",
  "includeUnmatched": true
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (type: `string`):

No description

## `sources` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "taxIds": [
        "900593921-7",
        "19.182.685/0001-62",
        "AAA080808HL8",
        "3-101-849778"
    ],
    "names": [
        "Consultora Tecnodinamica"
    ],
    "queries": [],
    "countries": [],
    "fuzzyNameMatch": true,
    "fuzzyThreshold": 92,
    "maxResults": 25,
    "useCache": true,
    "includeUnmatched": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("opendata-cr/latam-sanctions-screening").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "taxIds": [
        "900593921-7",
        "19.182.685/0001-62",
        "AAA080808HL8",
        "3-101-849778",
    ],
    "names": ["Consultora Tecnodinamica"],
    "queries": [],
    "countries": [],
    "fuzzyNameMatch": True,
    "fuzzyThreshold": 92,
    "maxResults": 25,
    "useCache": True,
    "includeUnmatched": True,
}

# Run the Actor and wait for it to finish
run = client.actor("opendata-cr/latam-sanctions-screening").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "taxIds": [
    "900593921-7",
    "19.182.685/0001-62",
    "AAA080808HL8",
    "3-101-849778"
  ],
  "names": [
    "Consultora Tecnodinamica"
  ],
  "queries": [],
  "countries": [],
  "fuzzyNameMatch": true,
  "fuzzyThreshold": 92,
  "maxResults": 25,
  "useCache": true,
  "includeUnmatched": true
}' |
apify call opendata-cr/latam-sanctions-screening --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,opendata-cr/latam-sanctions-screening"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3OwRVWIrxTWpPpSNQ/builds/adn2k4vNDQmIryXNJ/openapi.json
