Screening API

One request before every listing, intake or purchase. Verdicts are explainable and cite official notices. Auth is a bearer key from your dashboard; keys are stored hashed and can be revoked instantly. Default limit: 1,000 screens per rolling 24h per key.

POST /api/v1/screen

Screen a consumer product, food, drug or device against CPSC, FDA and USDA records. title is required; brand, upc and model sharpen the verdict when you have them (UPC hits are conclusive; an exact model/part/catalog code plus brand agreement scores 0.94+).

curl -X POST $BASE/api/v1/screen \
  -H "Authorization: Bearer ac_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Boppy Original Newborn Lounger",
    "brand": "Boppy",
    "upc": "769662004106"
  }'
{
  "verdict": "match",            // match | review | all_clear
  "top_score": 0.95,
  "matches": [
    {
      "source": "cpsc",          // cpsc | fda | usda
      "source_id": "21207",
      "title": "The Boppy Company Recalls Over 3 Million Original Newborn Loungers...",
      "hazard": "Infants can suffocate...",
      "remedy": "Refund",
      "url": "https://www.cpsc.gov/Recalls/2021/...",
      "recall_date": "2021-09-23",
      "severity": null,          // FDA: class_i | class_ii | class_iii
      "tier": "upc",             // upc | brand_model | model_related | brand_related | fuzzy
      "score": 1.0,
      "signals": {
        "upc_hit": true,
        "model_hit": false,
        "brand_hit": true,
        "idf_coverage_nonbrand": 1.0,
        "idf_coverage": 1.0,
        "word_similarity": 0.968,
        "token_overlap": 3
      }
    }
  ],
  "sources": ["cpsc", "fda"],
  "screened_at": "2026-07-09T21:00:00Z",
  "disclaimer": "..."
}

Verdict semantics

match (score ≥ 0.72) — identity-level evidence: exact UPC, or brand agreement plus high coverage of the query's distinctive tokens. Treat as: do not sell; check the notice.

review (0.45–0.72) — real signal, not identity: the brand has recalls of a related line, or generic text overlap. Treat as: human glance before listing.

all_clear — no qualifying signal in the corpus. Absence of evidence, stated honestly: we show you exactly what was checked.

POST /api/v1/screen-vehicle

Vehicles are exact-identified — this queries NHTSA live (24h cache) by make, model and year. Same bearer key, metered with your screens.

curl -X POST $BASE/api/v1/screen-vehicle \
  -H "Authorization: Bearer ac_live_..." \
  -H "Content-Type: application/json" \
  -d '{"make": "Tesla", "model": "Model Y", "year": 2021}'
{
  "verdict": "recalls_found",    // recalls_found | none_found
  "count": 22,
  "recalls": [
    {
      "campaign": "22V037000",
      "component": "ELECTRICAL SYSTEM:ADAS...",
      "summary": "Tesla, Inc. (Tesla) is recalling certain...",
      "remedy": "...",
      "report_date": "2022-01-27",
      "park_it": false,
      "park_outside": false,
      "ota_update": true
    }
  ],
  "note": "Campaign-level result... VIN check at nhtsa.gov/recalls."
}

GET /api/v1/audit-log Pro

Compliance export of your screening history — every screen, vehicle check and export event across all your keys (attributed via key_prefix), oldest-first. Keyset-paginated: pass next_cursor back as cursor until it returns null. format=csv streams a spreadsheet-safe CSV (formula-injection hardened) and carries the cursor in the x-next-cursor header.

curl "$BASE/api/v1/audit-log?since=2026-01-01&format=csv" \
  -H "Authorization: Bearer ac_live_..." -o audit.csv
{
  "rows": [
    {
      "id": 812, "created_at": "2026-07-10T14:02:11Z",
      "kind": "screen",              // screen | key_check | export
      "title": "Peloton Tread+", "brand": null, "upc": null,
      "verdict": "match", "match_count": 3, "latency_ms": 41,
      "key_prefix": "ac_live_a1b2c3d"
    }
  ],
  "count": 1,
  "next_cursor": null               // non-null -> request the next page
}

POST /api/v1/screen-image

Barcode-first intake for the resale floor: send a photo of the label, we decode the retail barcode (UPC-A/EAN-13/UPC-E/EAN-8), validate the GTIN check digit, and run the standard screen on the exact UPC — either GTIN spelling matches. Add "certify": true to mint a clearance certificate instead (Pro). No checksum-valid barcode →422 no_barcode; we never guess from a blurry read. Images are processed in memory and never stored.

curl -X POST $BASE/api/v1/screen-image \
  -H "Authorization: Bearer ac_live_..." \
  -H "Content-Type: application/json" \
  -d '{"image_base64": "<base64 of the label photo>", "title": "Infant lounger", "certify": false}'
{
  "verdict": "match",
  "matches": [ ... ],
  "scan": {
    "symbology": "EAN13",
    "gtin": "036000291452",       // canonical UPC-A spelling
    "kind": "GTIN-13",
    "forms": ["036000291452", "0036000291452"],
    "codes_found": 1
  }
}

POST /api/v1/certify Pro

A screen, minted as a tamper-evident clearance certificate. Certificates live on a global hash chain (altering any historical record breaks every later link) and are issuer-signed. Anyone — a buyer, an insurer, an inspector — can verify one without an account. Print the verify link or its QR on a tag; that's the whole workflow.

curl -X POST $BASE/api/v1/certify \
  -H "Authorization: Bearer ac_live_..." \
  -H "Content-Type: application/json" \
  -d '{"title": "Boppy Original Newborn Lounger"}'
{
  "verdict": "match",
  "top_score": 0.95,
  "matches": [ ... ],
  "certificate": {
    "cert_uid": "acc_1f9c04b7e2a86d3c55aa",
    "chain_hash": "8c1b...e9",
    "issued_at": "2026-07-10T19:04:12Z",
    "verify_path": "/api/v1/verify/acc_1f9c04b7e2a86d3c55aa"
  }
}

GET /api/v1/verify/{cert_uid} Public

No auth. Returns the server-held certificate plus recomputed integrity checks: payload hash, chain hash, issuer signature, and the forward chain link. A human-readable version lives at /verify/{cert_uid}. The current chain head is public via rpc/ac_cert_head and is anchored daily into an append-only CI log for third-party timestamping.

{
  "found": true,
  "valid": true,
  "cert_uid": "acc_1f9c04b7e2a86d3c55aa",
  "certificate": { "item": {...}, "verdict": "match", "matches": [...], "corpus": {...} },
  "integrity": {
    "payload_ok": true, "chain_ok": true,
    "issuer_ok": true, "next_link_ok": true, "is_chain_head": false
  }
}

Errors

401 { "error": "invalid_key" }
403 { "error": "plan_required" }   // audit-log on a non-Pro plan
429 { "error": "rate_limited", "limit_per_day": 1000 }   // Retry-After: 3600
400 { "error": "invalid_request", "issues": ["title: ..."] }
502 { "error": "upstream_error" }

Fair use & guarantees

Verdicts reflect federal data as ingested (CPSC SaferProducts, openFDA enforcement, USDA FSIS, NHTSA). They are a screening signal, not legal advice — always confirm a match against the cited notice. We log query text for metering and abuse prevention; we never log or store raw IPs, only salted hashes.