› compliance_grid.aiCOMPLIANCEGRIDGOV · COMPLIANCE · INTELLIGENCE
Back to Docs

KYC & Due Diligence Workflow

Build automated Know Your Customer (KYC) and enhanced due diligence workflows using SEC EDGAR, FDIC, FINRA BrokerCheck, OFAC screening, and SAM.gov — all through a single API platform.

Reading time: 8 minLast updated: Oct 2026

Use Cases

New Customer Onboarding

Verify entity legitimacy before opening accounts or extending credit.

Periodic Re-screening

Re-screen existing customers quarterly for new sanctions hits or regulatory changes.

Vendor Due Diligence

Verify vendors and counterparties before entering into contracts.

M&A Due Diligence

Screen acquisition targets across multiple regulatory databases.

Workflow Steps

Step 1: SEC EDGAR Entity Search

Search SEC EDGAR for company filings, registrations, and disclosure history. Verify the entity is a legitimate SEC registrant.

View API docs

Step 2: FDIC Bank Verification

Look a bank up in the FDIC institution directory: certificate number, location, assets and deposits, regulator, and whether the institution is still active.

View API docs

Step 3: FINRA BrokerCheck

Search the FINRA disciplinary records held here (a subset of FINRA actions, not the BrokerCheck registry). A hit is a disciplinary record to read; no hit says nothing about registration.

View API docs

Step 4: OFAC Sanctions Screening

Screen the entity against the OFAC SDN list and the other U.S. restricted-party lists. A potential match needs human review.

View API docs

Step 5: SAM.gov Entity Validation

Check the entity against SAM.gov registrations and the public exclusions list (UEI, CAGE and NPI matches are exact; name matches need confirming).

View API docs

Step 1: SEC EDGAR Entity Search

Verify a company's SEC registration and pull recent filings, CIK numbers, and disclosure data.

1-sec-edgar.ts
const API = "https://api.compliancegrid.ai";
const headers = { "x-api-key": process.env.CG_API_KEY! };
const get = (path: string) => fetch(API + path, { headers }).then((r) => r.json());

// Find a company in the EDGAR registrant list (q matches the company name)
const edgar = await get("/v1/financial/sec/search?q=" + encodeURIComponent("Apple Inc."));
const match = edgar.results[0];
console.log(match.entityName, "| CIK", match.cik, "| tickers", match.tickers);   // Apple Inc. | CIK 0000320193 | [ 'AAPL' ]

// Company profile and recent filings by CIK
const filings = await get("/v1/financial/sec/filings/" + match.cik);
const company = filings.company;
console.log(company.entityName, "| SIC", company.sic, company.sicDescription, "| incorporated in", company.stateOfIncorporation);
for (const f of company.filings.slice(0, 5)) {
  console.log(f.filingDate, f.form, f.primaryDocDescription, f.filingUrl);
}

Step 2: FDIC Bank Verification

2-fdic-lookup.ts
// Search the FDIC directory by name (also: state)
const fdic = await get("/v1/financial/fdic/search?q=" + encodeURIComponent("Wells Fargo Bank") + "&state=SD");
for (const b of fdic.results) {
  console.log(b.institutionName, "| cert", b.certNumber, "|", b.city + ", " + b.state);
  console.log("  active:", b.activeFlag, "| regulator:", b.regulatorName, "| assets ($ thousands):", b.totalAssets);
}

// Or look an institution up by its certificate number
const bank = await get("/v1/financial/fdic/institution/3511");
if (bank.found) console.log(bank.institution.institutionName, "active:", bank.institution.activeFlag);
// activeFlag false means the charter is closed or merged: the institution no longer holds insured deposits.

Step 3: FINRA BrokerCheck

3-finra-check.ts
// Search the FINRA disciplinary records held here (also: crd, firm)
const finra = await get("/v1/financial/finra/brokers?name=" + encodeURIComponent("Morgan Stanley"));
console.log(finra.totalResults + " records");
for (const r of finra.results) {
  console.log(r.firmName, "| disclosures:", r.disclosureCount);
}
// This is a small subset of FINRA disciplinary actions, not BrokerCheck: it has no registration
// status. To confirm a broker or firm is registered, use FINRA BrokerCheck directly.
console.log(finra.meta.dataSource);

Step 4: OFAC Sanctions Screening

4-ofac-screening.ts
// Screen the entity against the U.S. restricted-party lists
const screening = await fetch(API + "/v1/compliance/restricted-party-screening", {
  method: "POST",
  headers: { ...headers, "Content-Type": "application/json" },
  body: JSON.stringify({ parties: [{ name: "Goldman Sachs Group Inc.", country: "US" }] }),
}).then((r) => r.json());

// overallResult is CLEAR or POTENTIAL_MATCH
console.log(screening.data.overallResult, "|", screening.data.totalMatches, "matches");
for (const match of screening.data.results[0].matches.slice(0, 3)) {
  console.log("  " + match.listName + ": " + match.matchedName + " (score " + match.matchScore + ", " + match.matchType + ")");
}

Step 5: SAM.gov Entity Validation

5-sam-gov.ts
// Registration details in SAM.gov (also: uei, cage, state)
const sam = await get("/v1/business/sam/search?q=" + encodeURIComponent("Lockheed Martin") + "&limit=3");
for (const e of sam.results) {
  console.log(e.legalBusinessName, "| UEI", e.ueiSAM, "|", e.registrationStatus, "| exclusion:", e.exclusionStatus);
}

// The public exclusions list. Pass uei or cage for an exact match; a name match needs confirming.
const ex = await get("/v1/legal/exclusions/check?name=" + encodeURIComponent("Lockheed Martin Corporation"));
console.log(ex.totalMatches + " exclusion matches");
for (const m of ex.matches) console.log(m.matchType, m.entityName, m.reason, m.agency);

Complete KYC Function

Here's a complete function that runs all five checks and returns a consolidated risk assessment.

kyc-workflow.ts
async function runKYC(entityName: string, country: string) {
  const results = {
    entity: entityName,
    timestamp: new Date().toISOString(),
    checks: {} as Record<string, any>,
    reasons: [] as string[],
    overallRisk: "LOW" as "LOW" | "MEDIUM" | "HIGH" | "REVIEW",
  };
  const raise = (to: "MEDIUM" | "REVIEW" | "HIGH", why: string) => {
    const order = ["LOW", "MEDIUM", "REVIEW", "HIGH"];
    if (order.indexOf(to) > order.indexOf(results.overallRisk)) results.overallRisk = to;
    results.reasons.push(why);
  };
  const q = encodeURIComponent(entityName);

  // All checks in parallel; a call that fails is reported, never read as a clean result
  const [screening, edgar, fdic, finra, sam, ex] = await Promise.all([
    fetch(API + "/v1/compliance/restricted-party-screening", {
      method: "POST",
      headers: { ...headers, "Content-Type": "application/json" },
      body: JSON.stringify({ parties: [{ name: entityName, country }] }),
    }).then((r) => r.json()).catch(() => null),
    get("/v1/financial/sec/search?q=" + q).catch(() => null),
    get("/v1/financial/fdic/search?q=" + q).catch(() => null),
    get("/v1/financial/finra/brokers?name=" + q).catch(() => null),
    get("/v1/business/sam/search?q=" + q + "&limit=3").catch(() => null),
    get("/v1/legal/exclusions/check?name=" + q).catch(() => null),
  ]);

  results.checks = { screening: screening?.data, secEdgar: edgar?.results, fdic: fdic?.results, finra: finra?.results, samGov: sam?.results, exclusions: ex?.matches };

  if (!screening?.data) raise("REVIEW", "Restricted-party screening unavailable");
  else if (screening.data.overallResult === "POTENTIAL_MATCH") raise("REVIEW", "Possible restricted-party list match: review the matches");

  if (!ex?.success) raise("REVIEW", "SAM.gov exclusions check unavailable");
  else if (ex.matches.some((m: any) => m.matchType !== "NAME")) raise("HIGH", "Exact SAM.gov exclusion match");
  else if (ex.totalMatches > 0) raise("REVIEW", "SAM.gov exclusion name match to confirm");

  if ((finra?.results ?? []).some((r: any) => r.disclosureCount > 0)) raise("MEDIUM", "FINRA disciplinary record found: read it");

  return results;
}

// Usage
const kyc = await runKYC("Goldman Sachs Group Inc.", "US");
console.log("Risk Level:", kyc.overallRisk, kyc.reasons.join("; "));
Healthcare Credentialing Guide

DEA + OIG + SAM verification

Export Compliance Guide

Screening through AES filing