# Business Validation Tools MCP Server (Tax ID, VAT, IBAN, LEI) (`hexadatalabs/business-validation-tools-mcp`) Actor

Deterministic validation tools for AI agents: tax IDs of 15 countries (RFC, NIF, CUIT, RUT, CNPJ, UK VAT, EIN, SIREN, ABN, GSTIN), EU VAT (VIES), IBAN, CLABE/BIC, LEI, postal codes, phones, FX rates, business days, HS codes, VAT rates, SAT CFDI catalogs, Mexican payroll. MCP + batch, pay per call.

- **URL**: https://apify.com/hexadatalabs/business-validation-tools-mcp.md
- **Developed by:** [Hexadata](https://apify.com/hexadatalabs) (community)
- **Categories:** AI, Developer tools
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event + usage

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

## Business Validation Tools MCP Server (Tax ID, VAT, IBAN, LEI, HS Codes, Business Days)

Business validation tools MCP server for AI agents and automations: 15 deterministic tools that validate tax IDs from 15 countries (Mexican RFC, Spanish NIF/CIF, Argentine CUIT, Chilean RUT, Colombian NIT, Brazilian CNPJ/CPF, UK VAT number, US EIN, Italian Partita IVA / Codice Fiscale, French SIREN/SIRET/TVA, German USt-IdNr / Steuer-ID, Peruvian RUC, Canadian Business Number, Australian ABN/ACN, Indian GSTIN), check EU VAT numbers in VIES, validate IBANs and bank account identifiers (Mexican CLABE, US ABA routing numbers, SWIFT/BIC), look up Legal Entity Identifiers in GLEIF, resolve postal codes in 120+ countries, normalize phone numbers to E.164, check e-mail domains (MX, disposable), get official exchange rates (ECB, Banxico FIX), add business days and list public holidays in 200+ countries, look up industry codes (NAICS, NACE, CPV, SCIAN), customs tariff codes (US HTS, EU CN), VAT/GST rates for 35 countries, the Mexican SAT CFDI 4.0 catalogs and Mexican payroll (ISR, subsidy, IMSS, Infonavit). Every answer is a JSON object with the result, its official source and its date, and you pay per call: **$0.005 per single-item call, $0.002 per item in batches**, nothing for invalid input. No LLM inside: the same input always gives the same answer, nothing is stored.

![The 15 Hexadata Tools: validate, look up, calculate](https://raw.githubusercontent.com/4robot/hexadata-tools-mcp/main/infographic.png)

### What you get

One JSON object per item, with the same envelope for every tool:

- `tool` (string) — the tool that answered.
- `ok` (boolean) — `true` when the item was answered; `false` with `error.code` and `error.message` otherwise (never charged).
- The tool's own fields (listed per tool below): booleans such as `valid` or `found`, normalized strings such as `normalized`, `e164` or `code`, numbers such as `rate`, `isr` or `standard`, arrays such as `matches[]`, `holidays[]` or `parents[]`, and a `reason` code when something is wrong with the value.
- `source` (string), `sourceUrl` (string) — the official or open source behind the answer.
- `sourceDate` (ISO 8601) for live sources (VIES, GLEIF, ECB) or `tableVersion` (string) for shipped tables (IBAN registry, SAT workbook date, payroll tables year, VAT rates snapshot).
- `attribution` (string) where the licence requires it (GeoNames, INEGI).
- `scrapedAt` (ISO 8601) — when the item was answered.

#### Tools

| Tool | Use this when… | Input | Output | Source |
| --- | --- | --- | --- | --- |
| `validate_tax_id` | you need to check the format and check digit of a company/taxpayer ID before invoicing or onboarding a supplier | `country` (MX, ES, AR, CL, CO, BR, GB, US, IT, FR, DE, PE, CA, AU, IN), `taxId` | `valid`, `normalized`, `formatted`, `type` (company/person), `idType` (RFC, NIF/CIF/NIE, CUIT, RUT, NIT, CNPJ/CPF, VAT, EIN, PARTITA_IVA/CODICE_FISCALE, SIREN/SIRET/TVA, USTIDNR/STEUER_ID, RUC, BN, ABN/ACN, GSTIN), `reason` | Official check-digit algorithms (SAT, AEAT, AFIP/ARCA, SII, DIAN, Receita Federal, HMRC, IRS, Agenzia delle Entrate, INSEE/DGFiP, BZSt, SUNAT, CRA, ATO/ASIC, GSTN) |
| `validate_vat_eu` | you need to confirm an EU VAT number is registered (B2B invoicing, reverse charge) | `countryCode` (EU-27 + XI), `vatNumber` | `valid`, `registered`, `name`, `address`, `requestDate`, `consultationNumber` | VIES, European Commission (live) |
| `validate_iban` | you need to validate an IBAN and extract bank/branch/account before a payment | `iban` | `valid`, `formatted`, `country`, `sepa`, `bankCode`, `branchCode`, `accountNumber`, `reason` | ISO 13616 + IBAN registry structures (`ibantools`, MIT) |
| `lookup_lei` | you need the legal entity behind an LEI, or the LEI of a company name (KYC, 200+ jurisdictions) | `lei` or `legalName` (+ `country`) | `found`, `record` (legal name, addresses, status, registration dates) / `records[]` | GLEIF API (CC0, live) |
| `lookup_postal_code` | you need city/region/coordinates for a postal code, or the codes of a place; Mexico adds colonia/municipio/estado | `country`, `postalCode` or `query` | `found`, `matches[]` (`postalCode`, `placeName`, `admin1`, `admin2`, `lat`, `lon`) | GeoNames postal codes (CC BY 4.0) |
| `validate_bank_account` | you need to verify a bank account identifier before a transfer: Mexican CLABE, US ABA routing number or SWIFT/BIC | `type` (clabe, aba, bic), `value` | `valid`, `checkDigitOk`, `reason`; CLABE: `bankCode`, `bankName`, `plazaCode`, `accountNumber`; ABA: `prefixType`, `federalReserveDistrict`; BIC: `country`, `bankCode`, `locationCode`, `branchCode`, `testBic` | CLABE 3-7-1 algorithm + Banxico SPEI participant list; ABA checksum rules; ISO 9362 (offline) |
| `normalize_phone` | you need a phone number in E.164 with its country and line type before storing or dialing | `phone`, `defaultCountry` | `valid`, `e164`, `country`, `countryCallingCode`, `type`, `national`, `international`, `extension`, `reason` | `libphonenumber-js` / Google libphonenumber metadata (offline, all countries) |
| `validate_email_domain` | you need to know whether an e-mail address is well-formed and its domain can receive mail (no message is sent) | `email`; params `checkMx` | `valid`, `syntaxOk`, `normalized`, `domain`, `hasMx`, `mxHosts[]`, `disposable`, `freeProvider`, `reason` | RFC 5322 syntax + DNS MX + disposable-email-domains blocklist (CC0) |
| `get_fx_rate` | you need an official exchange rate for a date (invoicing, reports), with cross rates via EUR | `from`, `to`, `date`, `amount`; params `source` (ecb, banxico), `exactDate` | `found`, `rate`, `inverse`, `rateDate`, `exactDate`, `converted`, `rateSource` | ECB euro reference rates (30+ currencies, since 1999, cached); Banxico FIX USD/MXN (series SF43718, needs `BANXICO_TOKEN`) |
| `business_days` | you need to add business days to a date (SLAs, due dates), count business days between two dates, check a date or list the public holidays of a year, in 200+ countries | `country`, `date` + `days` or `endDate`, or `year`; optional `region` (ISO 3166-2); params `weekend`, `holidayTypes` | `resultDate`, `businessDaysBetween`, `isBusinessDay`, `nextBusinessDay`, `holidays[]` / `holidaysSkipped[]`, `weekendDays`, `weekend` | Nager.Date (MIT; cached offline for MX, US, ES, AR, CL, CO, BR, GB, DE, FR, IT, CA, AU, PE, live for the rest); Mexico: Ley Federal del Trabajo art. 74 computed |
| `lookup_industry_code` | you need the industry/procurement code for an activity, or the title and hierarchy of a code (supplier classification, KYC, tenders) | `system` (naics, nace, cpv, scian), `code` or `query`; params `maxResults` | `found`, `code`, `title`, `level`, `parents[]`, `children[]` / `matches[]` ranked by matched words | NAICS 2022 (US Census Bureau), NACE Rev. 2.1 (Eurostat; ISIC-compatible via NACE), CPV 2008 (Publications Office of the EU), SCIAN 2023 (INEGI) |
| `lookup_hs_code` | you need the customs tariff code for a product, or the description, hierarchy, unit and US duty rate of a code (imports, exports, landed cost) | `schedule` (us, eu), `code` or `query`; params `maxResults` | `found`, `code`, `hs6`, `description`, `fullDescription`, `parents[]`, `children[]`, `unit`, `dutyGeneral`/`dutySpecial`/`dutyOther` (US) / `matches[]` | USITC Harmonized Tariff Schedule (current revision, 10 digits); EU Combined Nomenclature 2026 (CN8, Eurostat) |
| `get_vat_rates` | you need the standard and reduced VAT/GST/IVA rates of a country for invoicing or pricing | `country`, `date`, `amount` | `taxType`, `standard`, `reduced[]`, `superReduced`, `parking`, `zeroRated`, `regional[]`, `validFrom`, `validForDate`, `standardVat`, `gross` | European Commission TEDB (EU-27) + national VAT laws (MX, AR, CL, CO, PE, GB, CA, AU); versioned table |
| `lookup_sat_catalog` | you need a value of the Mexican CFDI 4.0 catalogs to issue or validate an electronic invoice: product/service key, unit, CFDI use, tax regime, payment form/method, currency, country… | `catalog` (c_ClaveProdServ, c_ClaveUnidad, c_UsoCFDI, c_RegimenFiscal, c_FormaPago, c_MetodoPago, c_Moneda, c_Pais, c_Exportacion, c_ObjetoImp, c_TipoDeComprobante, c_TipoRelacion, c_Impuesto, c_Periodicidad, c_Meses), `key` or `query`; params `maxResults`, `includeInactive`, `date` | `found`, `key`, `description`, `validFrom`, `validTo`, `active`, catalog columns (`naturalPerson`/`legalEntity`, `receiverRegimes[]`, `bankTransaction`, `includeIva`, `similarWords`, `symbol`…), `level`, `parents[]` / `matches[]`, `suggestions[]` | SAT, catálogos del CFDI 4.0 (Anexo 20 RMF, official workbook; offline, `tableVersion` = workbook date) |
| `calc_payroll_mx` | you need Mexican payroll withholding and employer cost for a salary: ISR, employment subsidy, IMSS per branch, Infonavit, net pay | `monthlyGross` or `dailySalary`; `riskClass` (I–V), `year`, `month`, `periodicity` (monthly, biweekly, weekly), `integrationFactor`, `northernBorder`, `includeInfonavit` | `isr`, `subsidio`, `isrBracket`, `sbc`, `sbcCapped`, `imssEmployee{…, total}`, `imssEmployer{…, total}`, `infonavit`, `net`, `employerCost`, `uma`, `minimumWage` | DOF (Anexo 8 RMF tariff, subsidy decree, minimum wage), INEGI (UMA), Ley del Seguro Social (rates, CEAV ramp), Ley del Infonavit; versioned table |

Every result carries `ok`, `source`, `sourceDate` or `tableVersion` and `scrapedAt`. Items that cannot be answered come back with `ok: false` and an `error.code` of `INVALID_INPUT`, `UNSUPPORTED_COUNTRY` or `SOURCE_UNAVAILABLE`, and are **never charged**.

### Use cases

- **Accounts-payable and invoicing agents** validate the supplier's tax ID, IBAN or CLABE and the EU VAT registration before a bill is approved or a payment file is built.
- **KYC and supplier-onboarding teams** resolve an LEI, confirm the postal address, normalize the phone and e-mail and classify the company with NAICS, NACE or SCIAN in one pass.
- **Customs brokers and e-commerce operations** find the HS/HTS/CN code and the US duty rate of a product and the VAT/GST rate of the destination country for landed-cost estimates.
- **Mexican e-invoicing (CFDI 4.0) and payroll providers** pick the right SAT product/service key, unit, CFDI use and tax regime, and compute ISR, subsidy, IMSS and Infonavit for a salary.
- **n8n, Make and Zapier builders** add a deterministic validation step (tax ID, IBAN, phone, e-mail domain, business days for SLAs) to CRM, ERP and ticketing flows without writing regexes.

#### Mexico & Latin America pack

Mexico is covered end to end for invoicing and payroll agents: RFC check digits (with the generic RFCs), CLABE with the bank name from Banxico's SPEI list, postal codes with colonia/municipio/estado, the Banxico FIX rate, the statutory rest days of LFT art. 74, SCIAN 2023, IVA rates with the border regime, the complete SAT CFDI 4.0 catalogs (52k product/service keys with hierarchy and similar words, units, CFDI uses with the receiver regimes allowed, tax regimes for natural persons and legal entities, payment forms and methods) and a payroll calculator with the current ISR tariff, employment subsidy, UMA, minimum wage, IMSS quotas per branch (including the 2026 employer CEAV ramp and the 25-UMA cap) and Infonavit. Latin America adds CUIT, RUT, NIT, CNPJ/CPF and RUC check digits, postal codes, holidays and VAT rates for AR, CL, CO, BR and PE.

Example prompt: *"Which SAT product key and unit should I use to invoice software development services in Mexico, and what will a 20,000 MXN monthly salary cost the employer in 2026?"*

### Input

**MCP mode** (recommended for agents): each tool is exposed with its own JSON schema. Pass one item through the top-level fields (`country`, `taxId`, `iban`, …) or several items in `items` (1–500); optional parameters go next to them (`maxResults`, `weekend`, `checkMx`, …).

**Batch mode** (Apify Console, API, n8n, Make, Zapier): run the Actor with this input.

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `tool` | string (enum) | `validate_tax_id` | Which of the 15 tools to run: `validate_tax_id`, `validate_vat_eu`, `validate_iban`, `lookup_lei`, `lookup_postal_code`, `validate_bank_account`, `normalize_phone`, `validate_email_domain`, `get_fx_rate`, `business_days`, `lookup_industry_code`, `lookup_hs_code`, `get_vat_rates`, `lookup_sat_catalog`, `calc_payroll_mx`. |
| `items` | array of objects (1–500) | 3 tax IDs (MX, ES, BR) | One object per item with the fields of the chosen tool (see the table above). The prefill costs ≈ $0.006. |
| `params` | object | `{}` | Optional parameters applied to every item, e.g. `{"maxResults": 10}` for the lookup tools, `{"weekend": [6, 7], "holidayTypes": ["Public"]}` for `business_days`, `{"requesterCountryCode": "ES", "requesterVatNumber": "B12345674"}` for a VIES consultation number. |

Every item is validated before any work is done: a malformed item comes back as `ok: false, error.code: "INVALID_INPUT"` with a message that says which field is wrong, and is not charged.

### Output example

Two real items. First, the MX RFC of the prefill input in `validate_tax_id`:

```json
{
  "tool": "validate_tax_id",
  "ok": true,
  "country": "MX",
  "valid": true,
  "idType": "RFC",
  "normalized": "EKU9003173C9",
  "formatted": "EKU9003173C9",
  "type": "company",
  "reason": null,
  "registryCheckAvailable": false,
  "registryCheckTool": null,
  "source": "Official check-digit algorithms (SAT, AEAT, AFIP/ARCA, SII, DIAN, Receita Federal, HMRC, IRS, Agenzia delle Entrate, INSEE/DGFiP, BZSt, SUNAT, CRA, ATO/ASIC, GSTN)",
  "sourceUrl": "https://apify.com/hexadatalabs/business-validation-tools-mcp#sources",
  "scrapedAt": "2026-10-29T14:52:16.961Z"
}
```

Second, an IBAN with a wrong check digit in `validate_iban`. It is still answered (and charged) because the answer is the validation itself:

```json
{
  "tool": "validate_iban",
  "ok": true,
  "valid": false,
  "iban": "DE89370400440532013001",
  "formatted": null,
  "country": "DE",
  "countryInRegistry": true,
  "sepa": true,
  "checkDigitsOk": false,
  "bban": null,
  "bankCode": null,
  "branchCode": null,
  "accountNumber": null,
  "reason": "INVALID_CHECK_DIGITS",
  "reasons": ["INVALID_CHECK_DIGITS"],
  "source": "ISO 13616 + IBAN registry structures (ibantools, MIT)",
  "sourceUrl": "https://github.com/Simplify/ibantools",
  "tableVersion": "ibantools@4.5.4",
  "scrapedAt": "2026-10-29T14:52:30.644Z"
}
```

### Pricing & cost examples

Pay per event, with the Apify credit you already have:

| Event | When | Price |
| --- | --- | --- |
| `tool-call` | one answered call with a single item (MCP or batch mode) | **$0.005** ($5 per 1,000 calls) |
| `batch-item` | each answered item when a call carries more than one item | **$0.002** ($2 per 1,000 items) |

Items that come back with `ok: false` (`INVALID_INPUT`, `UNSUPPORTED_COUNTRY`, `SOURCE_UNAVAILABLE`) are never charged. In Standby (MCP) mode the Apify platform usage of the 256 MB server run is billed on top, as for any Actor (≈ 0.25 compute units per hour while it is receiving requests; it stops 60 seconds after the last one).

- **1,000 IBAN checks** sent in batches of 100 ≈ **$2**.
- **5,000 supplier tax IDs across 12 countries** in batches ≈ **$10**.
- **100 Mexican payroll calculations** in one batch ≈ **$0.20**; **one HS-code lookup inside an agent** ≈ **$0.005**.
- An agent that makes **200 single validations a day** ≈ $1/day, ≈ $30/month.

### Use with AI agents (MCP)

The Actor runs as a Streamable HTTP MCP server in Standby mode. The server URL is:

```
https://hexadatalabs--business-validation-tools-mcp.apify.actor/mcp
```

Send your Apify token as `Authorization: Bearer <APIFY_TOKEN>`. Client configuration (Claude Desktop, Cursor, VS Code and any MCP client that supports remote servers):

```json
{
  "mcpServers": {
    "hexadata-validation": {
      "url": "https://hexadatalabs--business-validation-tools-mcp.apify.actor/mcp",
      "headers": { "Authorization": "Bearer <APIFY_TOKEN>" }
    }
  }
}
```

Or load it through the Apify MCP server together with any other Actor: `https://mcp.apify.com?tools=hexadatalabs/business-validation-tools-mcp` (the tools appear as `hexadatalabs--business-validation-tools-mcp--<tool>`).

Every tool description starts with "Use this when…" so the agent picks the right one. Each tool accepts a single item through its top-level fields, or up to 500 items in `items`. Example prompt: *"Validate these supplier tax IDs: MX EKU9003173C9, ES B12345674 and BR 11.222.333/0001-81, and tell me which are malformed."*

#### Pay with USDC (x402, no account needed)

AI agents can pay for this Actor directly with USDC through Apify's x402 support, with no Apify account: the agent buys a prepaid token from Apify AGI with a [Coinbase Agentic Wallet](https://docs.cdp.coinbase.com/agentic-wallet/cli/welcome) (USDC on Base, minimum $1) and uses that token as a normal API token, both for the MCP server and for batch runs. This Actor runs with **limited permissions**, which is what makes it eligible. Current steps are in [Apify's x402 guide](https://docs.apify.com/integrations/x402):

```bash
npx -y awal auth login <email> && npx awal auth verify <code>   # one-time wallet setup; then fund it with USDC and a little ETH on Base
TOKEN=$(npx awal x402 pay 'https://agi.apify.com/protocols/x402/prepaid-tokens?amount=1&currency=usd' --max-amount 1000000 --json | jq -r .token)
curl -s -X POST "https://api.apify.com/v2/acts/hexadatalabs~business-validation-tools-mcp/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"tool":"validate_iban","items":[{"iban":"DE89 3704 0044 0532 0130 00"},{"iban":"GB82 WEST 1234 5698 7654 32"}]}'
```

Cost: **$1 USDC ≈ 200 single calls or 500 batch items** at this Actor's price; the token balance is a hard spending cap, and the token expires 14 days after purchase.

### API & integrations

Batch mode returns one dataset row per item; `run-sync-get-dataset-items` gives you the rows in the same HTTP call.

```bash
curl -s -X POST "https://api.apify.com/v2/acts/hexadatalabs~business-validation-tools-mcp/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"tool":"validate_tax_id","items":[{"country":"MX","taxId":"EKU9003173C9"},{"country":"ES","taxId":"B12345674"}]}'
```

```python
from apify_client import ApifyClient

client = ApifyClient("<APIFY_TOKEN>")
run = client.actor("hexadatalabs/business-validation-tools-mcp").call(run_input={
    "tool": "validate_vat_eu",
    "items": [{"countryCode": "IE", "vatNumber": "6388047V"}, {"countryCode": "DE", "vatNumber": "123456789"}],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["countryCode"], item.get("valid"), item.get("name"))
```

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

const client = new ApifyClient({ token: '<APIFY_TOKEN>' });
const run = await client.actor('hexadatalabs/business-validation-tools-mcp').call({
    tool: 'calc_payroll_mx',
    items: [{ monthlyGross: 20000, riskClass: 'I', year: 2026 }],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].isr, items[0].net, items[0].employerCost);
```

- **n8n, Make, Zapier:** use the Apify node/module with "Run an Actor and get dataset items", the input above and `tool` set to the validation you need; map the dataset columns to your CRM or ERP fields.
- **Schedules and webhooks:** batch jobs (e.g. nightly re-validation of a supplier list) run from Apify Schedules; add a webhook on `ACTOR.RUN.SUCCEEDED` to push the dataset to your system.
- **Direct MCP from code:** any MCP client library can POST JSON-RPC (`initialize`, `tools/list`, `tools/call`) to the server URL above with the `Authorization` header.

### Limitations & legal

#### Sources

- Sources are official or open: tax authority algorithms (offline), VIES and GLEIF (live, one request per item, 10 s timeout), `ibantools` (MIT), GeoNames postal codes (CC BY 4.0 — postal data © GeoNames, https://www.geonames.org), Nager.Date (MIT), U.S. Census Bureau and USITC (public domain), Eurostat and the Publications Office of the EU (reuse with attribution, CC BY 4.0), INEGI (Fuente: INEGI, SCIAN México 2023). GeoNames ships only the outward part of the code for GB, CA, NL, IE, MT, CL, CN and AR; such matches are flagged `partialMatch: true`.
- `validate_tax_id` checks format and check digits only; it does not query registries. GB VAT numbers are not covered by VIES (use XI for Northern Ireland).
- `validate_bank_account` returns the bank name for CLABE only (Banxico's public SPEI participant list). ABA routing numbers and BICs are validated structurally without a bank name: the Federal Reserve E-Payments Routing Directory and the SWIFT BIC directory do not allow commercial redistribution.
- `validate_email_domain` queries DNS MX records only; it never connects to the mail server and cannot tell whether a mailbox exists.
- `get_fx_rate` returns ECB reference rates (published around 16:00 CET on TARGET business days, for information only) and, on request, the Banxico FIX. Weekends and holidays return the last published rate (`rateDate`) unless `exactDate` is true. The Banxico FIX is disabled (`SOURCE_UNAVAILABLE`, free) until the operator sets a free SIE token.
- `business_days` counts `Public` holidays by default (`holidayTypes` can add `Bank`, `School`, `Authorities`, `Optional`, `Observance`); regional holidays are included only when a `region` is given, except days that cover every subdivision of the country (e.g. New Year's Day in GB). Mexico lists the statutory rest days of LFT art. 74 (including the federal election Sunday and the six-year presidential transition day), not Holy Week or bank holidays. India has no calendar in Nager.Date and returns `UNSUPPORTED_COUNTRY`.
- `lookup_industry_code` ships NAICS 2022, NACE Rev. 2.1, CPV 2008 (codes without the check digit) and SCIAN 2023 (Spanish titles, INEGI credit required). ISIC is not redistributed (UN terms of use); NACE Rev. 2.1 coincides with ISIC Rev. 5 at the division and group levels. Text search is a deterministic word-match ranking, not semantic search.
- `lookup_hs_code` uses the US HTS (public domain) and the EU Combined Nomenclature (CC BY 4.0). The WCO Harmonized System nomenclature itself is not redistributed; the first 6 digits of either schedule are the HS code. EU duty rates are not included (consult TARIC); US general/special/column-2 rates are those printed in the HTS.
- `get_vat_rates` is a dated snapshot (`tableVersion`) transcribed from TEDB and national laws, reviewed every six months; `validFrom` is the date of the latest known change and `validForDate` tells whether the snapshot already applied on the requested date. Regional regimes (Canary Islands, Azores/Madeira, Canadian provinces, Mexican border) are listed as notes or `regional[]`.
- `lookup_sat_catalog` ships the SAT workbook linked from the Anexo 20 page (`tableVersion` is its date; refreshed when the SAT publishes a new one). The workbook contains classes and commodities of c_ClaveProdServ only (no segment/family rows); c_CodigoPostal, c_Colonia, c_Localidad, c_Municipio, c_Estado and the foreign-trade catalogs are not included (use `lookup_postal_code` for postal codes). Text search is a deterministic word-match ranking in Spanish, not semantic search.
- `calc_payroll_mx` treats the whole salary as taxable (exempt items such as prima vacacional, aguinaldo, PTU or food vouchers and other deductions are not modelled), uses 30.4 days for a month and the average work-risk premium of the class (art. 73 LSS) unless the company premium is known. Tables are shipped per year (2026) and refreshed every January; other years return `INVALID_INPUT` without charge. It is a calculation aid, not tax advice.
- Stateless: inputs are validated and forgotten; logs contain counts and error codes only.

### Changelog

- 0.4 (latest, 2026-10-29) — Store release: `latest` build with all 15 tools, README with cost examples and x402 payment, SEO metadata.
- 0.4.0 (beta) — `lookup_sat_catalog` (SAT CFDI 4.0 catalogs), `calc_payroll_mx` (ISR, subsidy, IMSS, Infonavit, 2026 tables) and seven more countries in `validate_tax_id` (IT, FR, DE, PE, CA, AU, IN).
- 0.3.0 (beta) — `business_days` (Nager.Date + LFT art. 74), `lookup_industry_code` (NAICS, NACE, CPV, SCIAN), `lookup_hs_code` (US HTS, EU CN 2026), `get_vat_rates` (35 countries).
- 0.2.0 (beta) — `validate_bank_account` (CLABE, ABA, BIC), `normalize_phone`, `validate_email_domain`, `get_fx_rate` (ECB + Banxico FIX).
- 0.1.0 (beta) — first five tools: `validate_tax_id`, `validate_vat_eu`, `validate_iban`, `lookup_lei`, `lookup_postal_code`.

### Support

Open an issue in the Issues tab; we answer within 24 hours. Missing a country, catalog or code system? Open an issue with the official source and we add it.

# Actor input Schema

## `tool` (type: `string`):

Which tool to run on every item. Use this when you need the same check for a list of values. validate_tax_id: format + check digit (MX, ES, AR, CL, CO, BR, GB, US, IT, FR, DE, PE, CA, AU, IN). validate_vat_eu: VIES registration. validate_iban: ISO 13616. lookup_lei: GLEIF. lookup_postal_code: GeoNames, 120+ countries.

## `items` (type: `array`):

1–500 items, one object per value with the fields of the chosen tool. validate_tax_id: {country, taxId}. validate_vat_eu: {countryCode, vatNumber}. validate_iban: {iban}. lookup_lei: {lei} or {legalName, country?}. lookup_postal_code: {country, postalCode} or {country, query}. business_days: {country, date, days} / {country, date, endDate} / {country, year}. lookup_industry_code: {system, code} or {system, query}. lookup_hs_code: {schedule, code} or {schedule, query}. get_vat_rates: {country, date?, amount?}. lookup_sat_catalog: {catalog, key} or {catalog, query}. calc_payroll_mx: {monthlyGross} or {dailySalary} (+ riskClass, year, month, periodicity). Each answered item is one dataset row; items that cannot be answered (bad input, unsupported country, source down) are written with ok:false and are not charged.

## `params` (type: `object`):

Optional parameters that apply to every item. lookup_lei / lookup_postal_code / lookup_industry_code / lookup_hs_code / lookup_sat_catalog: {"maxResults": 10}. business_days: {"weekend": \[6, 7], "holidayTypes": \["Public"]}. validate_vat_eu: {"requesterCountryCode": "ES", "requesterVatNumber": "B12345674"} to get a VIES consultation number. Leave empty for the defaults.

## Actor input object example

```json
{
  "tool": "validate_tax_id",
  "items": [
    {
      "country": "MX",
      "taxId": "EKU9003173C9"
    },
    {
      "country": "ES",
      "taxId": "B12345674"
    },
    {
      "country": "BR",
      "taxId": "11.222.333/0001-81"
    }
  ],
  "params": {}
}
```

# Actor output Schema

## `results` (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 = {
    "items": [
        {
            "country": "MX",
            "taxId": "EKU9003173C9"
        },
        {
            "country": "ES",
            "taxId": "B12345674"
        },
        {
            "country": "BR",
            "taxId": "11.222.333/0001-81"
        }
    ],
    "params": {}
};

// Run the Actor and wait for it to finish
const run = await client.actor("hexadatalabs/business-validation-tools-mcp").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 = {
    "items": [
        {
            "country": "MX",
            "taxId": "EKU9003173C9",
        },
        {
            "country": "ES",
            "taxId": "B12345674",
        },
        {
            "country": "BR",
            "taxId": "11.222.333/0001-81",
        },
    ],
    "params": {},
}

# Run the Actor and wait for it to finish
run = client.actor("hexadatalabs/business-validation-tools-mcp").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 '{
  "items": [
    {
      "country": "MX",
      "taxId": "EKU9003173C9"
    },
    {
      "country": "ES",
      "taxId": "B12345674"
    },
    {
      "country": "BR",
      "taxId": "11.222.333/0001-81"
    }
  ],
  "params": {}
}' |
apify call hexadatalabs/business-validation-tools-mcp --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hexadatalabs/business-validation-tools-mcp"
        }
    }
}
```

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/kKbnuL4B1ehbXi0xP/builds/eeBXaUOEBbcKEt4aA/openapi.json
