Export Compliance Workflow
A complete guide to building an automated export compliance workflow using the ComplianceGrid APIs — from party screening through AES filing.
Overview
U.S. exporters must comply with multiple regulations: EAR (Export Administration Regulations), ITAR (International Traffic in Arms Regulations), OFAC sanctions, and Census Bureau AES filing requirements. This workflow automates the key compliance checks using ComplianceGrid APIs.
Workflow Steps
Step 1: Screen All Parties
Screen every party in the transaction — USPPI, consignee, end user, freight forwarder, and intermediaries — against the Consolidated Screening List (OFAC SDN, BIS Entity List, Denied Persons List and the other U.S. restricted-party lists).
Step 2: Classify the Commodity
Use AI-assisted HS code classification to propose a tariff code (up to three candidates with reasoning). Treat it as a suggestion: confirm the code, and the ECCN, before relying on it.
Step 3: Check for Prohibitions & Restrictions
Screen the commodity against destination-country prohibitions, sanctions programs, and import restrictions. Identify any license requirements.
Step 4: Determine Required Documents
Based on the commodity, destination, and regulatory findings, get the complete list of documents required for the shipment.
Step 5: Validate & File AES/EEI
For shipments over $2,500 (or any requiring a license), validate the Electronic Export Information and hand it off to AESDirect through a WebLink browser session.
Step 1: Restricted Party Screening
Screen all transaction parties against OFAC SDN, BIS Entity List, Denied Persons List and the other U.S. restricted-party lists in a single API call.
const API = "https://api.compliancegrid.ai";
const headers = { "x-api-key": process.env.CG_API_KEY!, "Content-Type": "application/json" };
const get = (path: string) => fetch(API + path, { headers }).then((r) => r.json());
const post = (path: string, body: unknown) => fetch(API + path, { method: "POST", headers, body: JSON.stringify(body) }).then((r) => r.json());
// Screen all parties in the transaction (type is free text; country improves match confidence)
const screening = await post("/v1/compliance/restricted-party-screening", {
parties: [
{ name: "Acme Electronics Inc.", country: "US", type: "USPPI" },
{ name: "Berlin Tech GmbH", country: "DE", type: "CONSIGNEE" },
{ name: "Munich Semiconductor AG", country: "DE", type: "END_USER" },
],
});
// overallResult is CLEAR or POTENTIAL_MATCH
if (screening.data.overallResult === "POTENTIAL_MATCH") {
console.log("REVIEW REQUIRED: potential matches found");
for (const result of screening.data.results) {
for (const match of result.matches) {
console.log(" " + result.party.name + " ~ " + match.matchedName + " | " + match.listName + " | score " + match.matchScore + " (" + match.matchType + ")");
}
}
} else {
console.log("CLEAR against list version " + screening.data.listVersion + " (retrieved " + screening.data.listRetrievedAt + "). Proceed to classification.");
}Step 2: HS Code Classification
Classify the commodity to determine the correct HS/HTS code, duty rates, and whether an export license is required.
// AI-assisted classification: up to three candidate codes, each with reasoning
const classification = await post("/v1/hs/classify", {
description: "High-frequency oscilloscope, 20 GHz bandwidth, digital storage",
});
for (const c of classification.data.suggestions) {
console.log(c.htsNumber, "| Schedule B", c.scheduleBNumber, "|", c.confidence); // HIGH, MEDIUM or LOW
console.log(" " + c.reasoning.slice(0, 160));
}
// Returns 503 AI_PROVIDER_UNAVAILABLE if the AI provider is down, and 403 AI_DISABLED when AI is switched off.
// The response does not contain an ECCN: determine it separately (step 3 takes it as an input).
// Search the tariff schedule by keyword for manual verification
const search = await post("/v1/hs/search", { query: "oscilloscope", limit: 5 });
console.log("Found " + search.data.totalResults + " matching HTS entries");Step 3: Prohibitions & Restrictions
// Check for country-specific prohibitions and restrictions
const prohibited = await post("/v1/compliance/prohibited-goods", {
originCountry: "US",
destinationCountry: "DE",
commodityDescription: "High-frequency oscilloscope, 20 GHz bandwidth",
hsCode: "9030.20",
});
const ev = prohibited.data.evaluation;
if (ev.isProhibited) {
console.log("EXPORT BLOCKED: prohibited for this destination");
console.log(ev.prohibitions);
} else if (ev.isRestricted) {
console.log("Restricted; a licence may be required:");
for (const r of ev.restrictions) console.log(" " + r.regulation + ": " + r.description);
} else {
console.log("No prohibitions or restrictions found (risk level " + ev.riskLevel + ").");
}
// Export licence determination (supply the ECCN if you know it; without one the item is treated as EAR99.
// For an ITAR item pass usmlCategory instead, and the answer comes from DDTC rules, not the EAR)
const license = await post("/v1/compliance/export-license", {
originCountry: "US",
destinationCountry: "DE",
commodityDescription: "Digital oscilloscope, 20 GHz",
eccn: "3A002",
endUse: "Commercial electronics testing",
});
const d = license.data.determination;
console.log("Licence required:", d.licenseRequired, "| type:", d.licenseType); // NLR = no licence required
console.log(d.reason);Step 4: Required Documents
// Which shipping and compliance documents does this shipment need?
// (Shipping Documents API, base path /api/v1. Query names: origin, destination, direction, transport_mode,
// commodity, value_usd, plus flags such as export_license, dual_use, letter_of_credit)
const docs = await get("/api/v1/required-documents/quick?origin=US&destination=DE&direction=export" +
"&transport_mode=air&commodity=electronics&value_usd=50000");
// Read the sanctions warnings BEFORE anything else
for (const w of docs.sanctions_warnings) console.warn("[" + w.level + "] " + w.description);
console.log(docs.total_documents + " documents (" + docs.required_count + " required, " + docs.conditional_count + " conditional, " + docs.recommended_count + " recommended):");
for (const doc of docs.documents) {
console.log(" [" + doc.priority + "] " + doc.document_name + " (" + doc.document_code + ") | issued by " + doc.issuing_party);
}
// Valid commodity categories
const categories = await get("/api/v1/reference/commodity-categories");
console.log(categories.map((c: any) => c.code).join(", "));Step 5: AES/EEI Filing
For shipments valued over $2,500 (or any requiring an export license), file Electronic Export Information through AESDirect WebLink (a browser session; the API does not transmit the filing to CBP directly).
// Validate the EEI filing data (the full schema is in the OpenAPI spec for POST /v1/aes/validate)
const validation = await post("/v1/aes/validate", {
usppi: {
companyName: "Acme Electronics Inc.",
ein: "12-3456789",
contactName: "Jane Doe",
phone: "214-555-0100",
address: { line1: "100 Main St", city: "Dallas", state: "TX", zip: "75201" },
},
ultimateConsignee: {
companyName: "Berlin Tech GmbH",
type: "R",
address: { line1: "Friedrichstr. 100", city: "Berlin", country: "DE" },
},
countryOfUltimateDestination: "DE",
modeOfTransport: "40", // air
carrierIdentification: "UPSN", // SCAC code, required for air shipments
portOfExport: "4304", // Dallas/Fort Worth (GET /v1/aes/reference/ports)
portOfUnlading: "4101",
dateOfExport: "2026-11-15",
filingType: "predeparture",
relatedPartyTransaction: false,
routedExportTransaction: false,
hazardousMaterials: false,
commodities: [{
scheduleBNumber: "9030200500", // ten digits, no dots
description: "Digital oscilloscope, 20 GHz",
quantity1: 2,
unitOfMeasure1: "NO",
shippingWeightKg: 8,
value: 50000,
eccn: "3A002",
// C33 = No License Required. NLR is reported with its keyword, so do not send a licenseNumber.
// For a BIS license use C30 with licenseNumber and licenseValue.
licenseType: "C33",
exportInformationCode: "OS",
originState: "TX",
dfIndicator: "D",
}],
});
// A field error is a 400 whose error.details names the field (for example "usppi.ein"); otherwise the
// response has valid and issues (each issue has severity ERROR, WARNING or INFO)
if (validation.success === false) {
console.error("Rejected:", validation.error.message);
} else if (validation.data.valid) {
console.log("Validation passed: ready to prepare the filing");
// The filing is handed to CBP through an AESDirect WebLink browser session; the API does not
// transmit it to CBP. The ITN comes back through the WebLink callback.
} else {
console.log("Validation issues:");
for (const issue of validation.data.issues) console.log(" [" + issue.severity + "] " + issue.field + ": " + issue.message);
}Complete Workflow Summary
Screen All Parties
Classify the Commodity
Check for Prohibitions & Restrictions
Determine Required Documents
Validate & File AES/EEI
APIs used: Compliance Screening, HS Code Lookup, Shipping Documents, AES Filing
Response times: most calls return in about one to three seconds; the AI classification is the slowest step (typically five to fifteen seconds).
SEC + FDIC + FINRA lookups
Browse all compliance workflows