Docs

API Reference

Base URL: https://api.exchek.us

Paid endpoints use the x402 payment protocol (USDC on Base). Session endpoints require a valid jobId from a paid or first-free start.

Endpoints

GET /health

Health check. No payment. Returns { "status": "ok", "service": "exchek-api" }.

POST /api/classify/start-free

First classification free. No payment. Body: { "walletAddress": "0x..." }. Returns jobId, nextStep, and promptForUser on success. If this wallet has already used the free classification, returns 402 with error, promptForUser, nextStep: "payment_required", requiredAction: "pay_start", paymentAmount: "$0.01", and paymentEndpoint: "POST /api/classify/start".

POST /api/classify/start

x402 paid ($0.01). Start a new AITL classification. Returns jobId, nextStep, promptForUser.

POST /api/classify/jurisdiction

x402 paid ($2). Determine jurisdiction (BIS vs ITAR). Body: item fields (description, specifications, intendedUse, notes; optionally performanceParameters, valuation, units, htsCode, scheduleBNumber, endUser, endUse, destinationCountry). Returns jurisdiction, regulatoryAgency, justification, citations, exportRestrictions, licenseRequirements, auditLog.

POST /api/classify/submit-info

No payment. Body: jobId plus item fields (description, specifications, intendedUse, notes; optionally performanceParameters, valuation, units, htsCode, scheduleBNumber, endUser, endUse, destinationCountry). Runs jurisdiction and returns determination; ask user to confirm or refine.

POST /api/classify/submit-classification

No payment. Body: jobId, proposedClassification (regulatoryAgency, eccnOrClassification, justification, exportRestrictions, licenseRequirements, restrictionsJustifications, auditLog). Use when the agent has run classification and submits the result for adjudicator review. Then call request-oor to retrieve the proposal.

POST /api/classify/confirm-jurisdiction

No payment. Body: jobId, confirmed: true or feedback. Confirms or refines jurisdiction.

POST /api/classify/request-oor

No payment. Body: jobId. Runs Order of Review (or returns agent-submitted classification if submit-classification was used); returns proposed ECCN, justification, citations, exportRestrictions, licenseRequirements, auditLog.

POST /api/classify/refine-oor

No payment. Body: jobId, feedback. Refines OOR result.

POST /api/classify/approve

No payment. Body: jobId. Finalizes classification; generates and stores report. Returns reportUrl when Supabase Storage is configured. If report storage fails, returns reportStorageError with a message; the classification is still approved.

POST /api/classify/status

No payment. Body: { "jobId": "..." }. Returns current job state and suggested next step: jobId, state, nextStep, promptForUser, hasItemInfo, hasJurisdiction. Use to recover context (e.g. "where are we?"). Returns 404 if the job is not found.

Error responses

All error responses include error and promptForUser so agents can relay a clear message to the user. Many include nextStep to indicate the suggested next action.

CodeMeaning
400Bad request (e.g. missing jobId, missing confirmed/feedback, invalid proposedClassification). May include validationErrors: [{"field": "...", "message": "..."}].
402Payment required (x402) or first free already used. Response includes nextStep: "payment_required", requiredAction: "pay_start", paymentAmount, paymentEndpoint.
404Job not found (session expired or invalid).
500Server error (jurisdiction, Order of Review, or refinement failed). Includes promptForUser and nextStep where applicable.
503Regulatory data (eCFR) temporarily unavailable.