Skip to main content

Verification API

Run an exclusion check and get back a sealed, publicly linkable verification record: the same record the site produces, created from your vendor-onboarding system instead of a browser. Every account receives a one-time allowance of 50 API-created verification records without charge. Additional record credits are purchased upfront: $50 for 100 credits ($0.50 per record). Scheduled monitoring records are included in monitoring service and do not consume this balance.

Every successful check seals a permanent record. Each record is readable by anyone who has its link and preserves the query, the entity identity it resolved, candidate information, and dated source facts. Records that recurring monitoring seals carry the roster contents they cover. Newly issued audit packets do not name the account. Revoking an API key or deleting the account does not remove or rewrite records already issued.

Machine-readable spec: /openapi.json · public registry stats: /v1/stats · liveness: /health · agent setup: /agent-setup.md

Authentication

Send your API key as a bearer token: Authorization: Bearer fc_…. Keys are created in API keys and shown once; we store only a hash.

POST /v1/verify

Body is { "query": string }, a UEI, CAGE code, or legal name (3 to 200 characters). Runs the exclusion check against the latest successfully loaded, dated SAM.gov Exclusions extract, seals a verification record, and returns the record reference plus the full evidence payload.

curl -X POST https://federal.contractors/v1/verify \
  -H "Authorization: Bearer fc_your_key" \
  -H "Content-Type: application/json" \
  -d '{"query": "RZK2AJC7QGA3"}'
{
  "record": {
    "id": "vr_AbC123...",
    "formatVersion": 2,
    "sha256": "9f2c…",
    "url": "https://federal.contractors/record/vr_AbC123...",
    "scitt": {
      "issuedAt": "2026-08-27T12:00:01.000Z",
      "keyId": "base64url-public-key-id",
      "timestamp": {
        "authority": "DigiCert",
        "policyOid": "2.16.840.1.114412.7.1",
        "timestampedAt": "2026-08-27T12:00:02.000Z"
      }
    }
  },
  "query": "RZK2AJC7QGA3",
  "matchType": "uei",
  "matchingMethod": "exact-uei-plus-registry-candidates",
  "matchingVersion": "exclusion-match-v1",
  "normalizationVersion": "legal-name-nfkc-v1",
  "identityStatus": "exact_uei",
  "resultStatus": "no_active_exclusion_record_matched",
  "checkedAt": "2026-08-27T12:00:00.000Z",
  "total": 0,
  "truncated": false,
  "matches": [],
  "source": {
    "file": "SAM_Exclusions_Public_Extract_V2_26238.ZIP",
    "member": "SAM_Exclusions_Public_Extract_V2_26238.CSV",
    "asOf": "2026-08-26",
    "retrievedAt": "2026-08-27T06:58:17.118Z",
    "freshness": { "status": "within-window", "maxAgeHours": 36, "reasons": [], "sourceDate": { "status": "current", "lagDays": 1, "maxLagDays": 1 } },
    "bytes": 11830242,
    "records": 168319,
    "invalidRows": 2,
    "sha256": "b90d…"
  },
  "credits": { "included": 50, "purchased": 100, "used": 12, "remaining": 138 }
}

record.url is public by unguessable id. New records use format version 2. Their seal is SHA-256 over the RFC 8785 canonical UTF-8 bytes of a payload that includes the record id, separate check and source times, source artifact and completeness facts, method versions, identity basis, candidate-set state, results, and explicit limitations. The JSON download names the canonicalization method for recomputation. A matching checksum alone shows byte consistency. New production records add a PS256 SCITT issuer signature over the exact format 2 bytes and a DigiCert RFC 3161 timestamp over the RFC 9921 signature imprint. The record page exposes the bare .scitt file and offline bundle. The bundle retains the timestamp request and response, timestamped statement, trust anchor, and revocation lists. The browser fetches issuer-key history separately from the bundle from federal.contractors. For long-term offline verification, retain issuer-key history obtained through a trusted channel. The timestamp proves that the issuer signature existed no later than the Timestamp Authority's time. Neither mechanism proves check execution time, source truth, matching correctness, identity, or a legal outcome. No independent Transparency Service receipt is attached. The record is evidence of diligence, not a verdict.

Read What is SCITT? for the distinction between a Signed Statement, a receipt, and a Transparent Statement.

source.freshness assesses two separate rules: retrieval age against maxAgeHours, and source-date lag as whole days behind the check against sourceDate.maxLagDays. Its status is delayed when either rule fails, and reasons names each failing rule: retrieval-stale or source-date-delayed. A recently downloaded file can still carry an old source date.

resultStatus distinguishes an exact UEI match, a potential match requiring review, and no active record matched under the recorded method. matchType describes the query, not the outcome. Every candidate records its match basis and field agreements or contradictions. When truncated is true, the returned candidate list is incomplete.

POST /v1/verify/batch

Check a list in one call: body is { "queries": string[] } (1 to 100 items). Each item runs the same check and seals its own record, consuming one record credit. Items after credit exhaustion fail individually while the rest succeed. Rows carry the query, result status, candidate total, truncation and matching versions, and record reference. Full evidence remains at each record URL.

Credits and errors

Every successful API-created record reports credits.used and credits.remaining. Existing record retrieval and seal validation consume no credits. Errors: 401 missing or invalid key, 402 no record credits, 429 request rate limit, 400 malformed body. Every non-2xx response uses the same envelope: { "error": { "code": 401, "message": "..." } }.

MCP server

The API also speaks Model Context Protocol, so Claude, Cursor, or any MCP-compatible assistant can run checks directly. Point an HTTP MCP client at https://federal.contractors/mcp with your API key as a bearer header:

{
  "mcpServers": {
    "federal-contractors": {
      "type": "http",
      "url": "https://federal.contractors/mcp",
      "headers": { "Authorization": "Bearer fc_your_key" }
    }
  }
}

Three tools: verify_entity runs a check and seals a record (one credit per call), verify_batch checks up to 100 entities in one call (one credit per record), and get_record fetches an existing sealed record by id for no charge. Every record response includes its format version, separate check and source timestamps, and SHA-256 seal. Signed records also return SCITT Signed Statement metadata, independent timestamp metadata when present, and links to the bare statement and offline bundle downloads on the permanent record page. The independent timestamp proves the issuer signature existed no later than the Timestamp Authority's time. It does not prove check execution time or the underlying result. The record URL the assistant returns is the same permanent link the API returns. The check's evidence is the sealed record, not the model's word. Step-by-step client setup: how to check federal exclusions with AI.

Integrating with a coding agent? Paste this prompt into Claude Code, Cursor, or any agent with web access. It follows the plain-markdown instructions at /agent-setup.md, which cover both the MCP and REST paths:

Follow the instructions at https://federal.contractors/agent-setup.md to add federal.contractors exclusion checks to this project.

Try it

Run real requests against the live API from this page. The verify and batch requests reduce the record-credit balance and seal real records. Stats needs no key. Error responses display as-is, including missing-key, exhausted-credit, and request-rate-limit cases.

API keys

Every signed-in account can create and revoke keys in API keys. Each key is shown once at creation. Only a hash is stored, so treat it like a password.