How to Verify a Company and Get a Proof Code via API (POST /v1/verifications)

One API call checks a French or Spanish company against its register and returns an outcome, reasons and a proof code anyone can check. Real answers inside.

· By the Fuentio team · 6 min read

Share image: "How to Verify a Company and Get a Proof Code via API" on Fuentio's paper background, with the Tutorial label.

A lookup tells you what the register says. A verification turns that into a decision you can act on and defend later: an outcome, the reasons behind it, the checks that ran, and a proof code that anyone you share it with can check, without a key. This tutorial shows the call, two real answers (one French, one Spanish), how to map outcomes to decisions in your onboarding flow, and how proof codes work.

What you'll learn

  • How to call POST /v1/verifications and what it costs
  • How to read the outcome, reasons, checks and signals
  • Why the same call answers "verified" for a French company and "partial" for a Spanish one
  • How to turn outcomes into onboarding decisions
  • How proof codes work, and who can see what

The call

Send the country and the official identifier. Add your own reference (a case or customer ID, up to 200 characters) so you can find the verification later:

curl -X POST https://api.fuentio.com/v1/verifications \
  -H "X-API-Key: YOUR_API_KEY" -H "Content-Type: application/json" \
  -d '{"country": "FR", "identifier": "552032534", "reference": "onboarding-0042"}'

In Python:

import httpx

r = httpx.post("https://api.fuentio.com/v1/verifications",
               headers={"X-API-Key": "YOUR_API_KEY"},
               json={"country": "FR", "identifier": "552032534", "reference": "onboarding-0042"},
               timeout=30)
v = r.json()["data"]
print(v["result"]["outcome"], v["result"]["reasons"], v["proof_code"])

Cost: 5 units, or 1 unit when a well-formed identifier isn't found; errors cost nothing. For France the identifier is a SIREN or SIRET; for Spain, the Registro Mercantil sheet (find it by name first: see how to find a Spanish company by name).

A real French answer: DANONE, "verified"

Recorded from the API on 12 October 2026 (some fields left out):

{
  "proof_code": "FUE-FR-20261012-ABAT38",
  "checked_at": "2026-10-12T11:26:42.573335+00:00",
  "identifier": { "scheme": "FR_SIREN", "value": "552032534" },
  "result": {
    "outcome": "verified",
    "reasons": ["company_active"],
    "summary": "DANONE (FR, SIREN 552032534): verified, active per Annuaire des Entreprises (API Recherche d'entreprises), checked 2026-10-12. Proof FUE-FR-20261012-ABAT38."
  },
  "checks": [
    { "check": "identifier_valid", "result": "pass", "detail": "The ID has a valid format." },
    { "check": "record_found", "result": "pass", "detail": "Found in the official source." },
    { "check": "status_active", "result": "pass", "detail": "Register status: active." },
    { "check": "address_present", "result": "pass", "detail": "Registered address published." },
    { "check": "fresh", "result": "pass", "detail": "Checked against the source within its refresh window." }
  ],
  "receipt": {
    "request_id": "req_F-kLJX7DF7SffHsi",
    "served_at": "2026-10-12T11:26:42.573335+00:00",
    "data_sha256": "4b555141ade1bb91ab789296aa9d7f4d95e71879c057f4b7797aea1aaa9bab0f"
  }
}

The answer also carries the full company record, a changes_summary and signals.

A real Spanish answer: MERCADONA, "partial"

The same call for MERCADONA SA, Registro Mercantil sheet V-5581, recorded the same day:

{
  "proof_code": "FUE-ES-20261012-966W7X",
  "result": {
    "outcome": "partial",
    "reasons": ["status_unknown", "events_only_coverage"],
    "summary": "MERCADONA SA (ES, Registro Mercantil sheet (hoja) V-5581): partial, status unknown (no dissolution act; latest act 2026-10-07) per BORME — Boletín Oficial del Registro Mercantil (Sección A), checked 2026-10-12. Proof FUE-ES-20261012-966W7X."
  },
  "checks": [
    { "check": "record_found", "result": "pass", "detail": "Found in the official source." },
    { "check": "status_active", "result": "unknown", "detail": "Register status: unknown." }
  ]
}

"Partial" here is not a warning about Mercadona. It reflects the source: Spain's BORME publishes events (acts registered since 2 January 2009), not a live "active" flag. With no dissolution act and a recent act published, the status stays "unknown", and the outcome says so honestly instead of guessing.

How to read the answer

  • result.outcome: one of verified, partial, unverified, insufficient_data.
  • result.reasons: short codes that explain the outcome (company_active, status_unknown, events_only_coverage…). Log them: they are what a reviewer reads first.
  • result.summary: one plain-language line that ends with the source, the check date and the proof code. Safe to show to a user or paste into a case note.
  • checks: each check that ran, with pass, fail or unknown and a one-line detail.
  • signals: what the source carries about closure, dissolution, extinction and insolvency: present, none_found or not_covered. "Not covered" means the source can't tell, never "all clear".
  • receipt: the request_id, when the answer was served and a SHA-256 hash of the data. It lets you prove later that this is exactly what was served.

From outcome to decision

Fuentio gives you facts and an outcome; the decision is yours. A starting point for an onboarding flow:

OutcomeSuggested handling
verifiedProceed. Store the proof code with the customer or supplier record.
partialRead the reasons. For Spain, status_unknown with events_only_coverage is the normal case: add your own checks if the amount at stake justifies it.
unverifiedStop and ask. Read the failed checks: a closed company, a missing record.
insufficient_dataAsk for a better identifier (a SIREN rather than a name, the right sheet).

Whatever you decide, store four things with the record: the proof_code, the outcome, the reasons and the checked_at date. That is your audit trail. For the wider onboarding picture, see a supplier-onboarding check for France and Spain.

Proof codes: who can see what

Every verification is stored with its proof code (FUE- + country + date + six characters), kept 24 months by default.

You, the owner, can fetch the full stored verification at any time with your key, by its ID or proof code, for 0 units:

curl https://api.fuentio.com/v1/verifications/FUE-FR-20261012-ABAT38 -H "X-API-Key: YOUR_API_KEY"

Anyone you share the code with can check it publicly, without a key and for 0 units:

curl https://api.fuentio.com/v1/public/proofs/FUE-FR-20261012-ABAT38

or simply open the proof page and paste the code. The public answer shows the outcome, the reasons, the company (name, identifier, country), the checks, the sources with links, when it was served, the data hash, and whether the stored data is unchanged. It never shows who ran the check: no key, no email, no reference, no internal ID. That makes it safe to put in an email to a bank, an auditor or a customer.

Public proof lookups are rate limited (30 a minute per address), and an unknown code answers a clean 404.

Try it without writing code

  • The free check has a "Get a proof code" button under each company card (3 checks a day, no account).
  • The free list check returns a proof code for each of up to 20 companies, with a CSV file.
  • In an AI agent, the same verification is the verify_company tool: connect over MCP.

When you're ready, a free API key gives 100 units a month, or 20 verifications. Start with the API quickstart if you haven't made a first call yet. See what we cover.

Questions reviewers ask, and where the answer is

Once verifications reach a compliance or finance reviewer, the same questions come back. Each has a field.

  • "How fresh is this?" The fresh check passes when the answer was checked against the source within that source's refresh window, and checked_at gives the exact time. A verification is a snapshot: for a later decision, run a new one.
  • "What did you actually check?" The checks list is the answer, one line per check, with its result. Show it as is rather than summarising it.
  • "Why didn't you flag the dissolution?" Read signals: not_covered means the source can't tell, which is different from none_found. Your policy should say what happens in each case.
  • "Which case was this for?" That is what reference is for. Use your own customer or case ID, and you can find every verification run for it.
  • "Can you prove the data wasn't changed since?" The public proof shows unchanged, computed from the stored data and its SHA-256 hash.

A practical rule many teams adopt: verify at onboarding, then again before any large order, prepayment or credit decision, and file each new proof code next to the previous ones.

Frequently asked questions

How much does a verification cost?

5 units, or 1 unit when a well-formed identifier isn't found. Errors cost nothing. Fetching a stored verification or checking a public proof costs 0.

What does "partial" mean for a Spanish company?

That the source can't confirm an active status: Spain's BORME publishes acts, not a live status. It is the normal outcome for many Spanish companies, explained by the status_unknown and events_only_coverage reasons.

Can someone see who ran a verification from its proof code?

No. The public proof shows the company, the outcome, the checks and the sources, never the key, email, reference or internal ID of whoever ran it.

How long are verifications kept?

24 months by default.

Sources

  • Fuentio API reference: docs and the OpenAPI file
  • The example answers: DANONE and MERCADONA, recorded from the API on 12 October 2026 (site/data/api-examples in the website repository)
  • Official sources behind the data: sources

← All articles · RSS feed