API documentation

REST/JSON. No account or API key: pay per check with x402. Machine-readable: OpenAPI 3.1, llms.txt, coverage, pricing.

What is checked

The request is routed to the responsible US authority: consumer products → CPSC; vehicles → NHTSA; food, drugs and medical devices → FDA (openFDA enforcement reports). Without a category, a VIN or model year routes to NHTSA, an NDC to FDA drugs, a UDI to FDA devices, and product words decide otherwise; when unclear, all non-vehicle authorities are queried. Not covered (422, never charged): Meat, poultry and processed egg products (USDA FSIS); Vehicle equipment, tires and child car seats (NHTSA equipment campaigns); Cosmetics; Recreational boats (USCG).

1. Ask (free)

POST https://productrecallcheck.online/api/v1/check
Content-Type: application/json

{
  "brand": "Example Brand",        // brand / manufacturer / (vehicles) make
  "product_name": "Example Blender",
  "model": "XB-200",               // as printed; separators normalised, digits never
  "upc": "012345678905",           // UPC/EAN/GTIN, check digit validated, leading zeros kept
  "category": "consumer_product",  // optional: consumer_product | vehicle | food | drug | medical_device | auto
  "jurisdiction": "US"             // optional, default US
}
// Other shapes: {"vin":"1HGCV1F30JA012345"} · {"make":"Honda","model":"Accord","model_year":2018}
//   {"ndc":"0409-4888-20","lot":"…"} · {"brand":"Jif","product_name":"peanut butter","upc":"…","lot":"…"}
// More identifiers: sku, serial, lot/batch, date_code, manufacture_date, expiration_date/best_by, udi

Identifiers are validated and normalised locally (UPC check digit, VIN check digit, NDC shape, dates). Invalid values return 400; unsupported categories or jurisdictions return 422. A valid request returns 402 with the x402 requirement (header PAYMENT-REQUIRED), the price (0.018 USDC) and the official sources that will be queried. Nothing is stored and no source is contacted.

2. Pay and check

Resend the identical body with PAYMENT-SIGNATURE (base64 x402 v2 payload, exact scheme, USDC on Base mainnet) and an Idempotency-Key (16–128 characters of A–Z a–z 0–9 _ -). The authorization is verified, the sources are queried live, and the payment is settled only for a determinate result. The settlement is returned in PAYMENT-RESPONSE.

{
  "check_id": "prc_…",
  "result": "RECALL_FOUND",
  "confidence": "HIGH",
  "summary": "Official recall found for …",
  "no_match_meaning": "NO_MATCH_FOUND means only that no matching recall was found in the checked official sources under the supplied identifiers. It does not mean the product is safe, free of defects, or will never be recalled.",
  "product": { "brand": "…", "model": "…", "matched_identifiers": { "brand_match": true, "model_match": true, "upc_match": null, … } },
  "recalls": [{
    "match_state": "RECALL_FOUND", "confidence": "HIGH",
    "match_explanation": { "brand_match": true, "model_match": true, "upc_match": null,
                           "lot_match": null, "serial_range_match": null, "date_range_match": null, … },
    "restrictions": [{ "kind": "date_code", "evaluation": "matched", "parse_confidence": "high",
                       "text_original": "date codes of 2510 (Oct-2025), 2511 …", "detail": "…" }],
    "recall": { "recall_id": "25214", "authority": "CPSC", "title": "…", "published_at": "2025-04-03",
                "hazard_original": "…verbatim…", "hazard_normalized": ["INJURY"],
                "consumer_action_original": "…verbatim…", "affected_products": [ … ],
                "original_description": "…verbatim…", … },
    "source": { "url": "https://www.cpsc.gov/Recalls/…", "api_url": "https://www.saferproducts.gov/…",
                "checked_at": "…", "source_type": "OFFICIAL_RECALL_SOURCE" }
  }],
  "excluded_candidates": [ { "recall_id": "…", "reasons": ["The recall lists specific models and … is not one of them."] } ],
  "routing": { "categories": ["consumer_product"], "routing_basis": "explicit", "sources_checked": ["us-cpsc-recalls"], … },
  "verification": { "checked_at": "…", "cache": { "cache_used": false, "cache_status": "LIVE", "source_version": { … } },
                    "sources": [{ "request_urls": ["https://www.saferproducts.gov/…"], "outcome": "ok", … }] },
  "next_steps": [ … ], "unknowns": [ … ], "limitations": [ … ],
  "language": { "source_languages": ["en"], "output_language": "en", "original_values_preserved": true },
  "payment": { "charged": true, "status": "settled", "amount": "0.018", "transaction": "0x…" }
}

3. Retrieve later (free)

GET https://productrecallcheck.online/api/v1/checks/{check_id}
Authorization: Bearer <Idempotency-Key>

Returns the stored evidence package with cache_status: STORED and its original checked_at — it is not re-checked. Evidence is kept 90 days.

Results

RECALL_FOUNDAn exact published identifier (UPC/GTIN, NDC, model, SKU, lot or serial within a listed range) ties the product to an official recall, and no stated restriction is left unverified. Charged.
POSSIBLE_MATCHA recall may apply, but a restriction is unverified (e.g. only some serial numbers, lot codes not supplied, vehicle VIN population not public) or the identity match is at model-family / brand+name level. Charged.
AMBIGUOUSSeveral different recalls (or only weak name similarities) relate to the product; the identifiers cannot tell which applies. Candidates are returned. Charged.
NO_MATCH_FOUNDThe relevant official source(s) answered and nothing matched sufficiently specific identifiers. NO_MATCH_FOUND means only that no matching recall was found in the checked official sources under the supplied identifiers. It does not mean the product is safe, free of defects, or will never be recalled. Charged.
SOURCE_UNAVAILABLEAn official source could not be queried. Never reported as "no recall". Not charged; retry with the same Idempotency-Key.
UNABLE_TO_VERIFYThe sources answered but the evidence cannot support a determination (identifiers too weak for a no-match, vehicle model not recognised, too many candidates, or a relevant authority that is not covered, e.g. USDA FSIS for meat). Not charged.

How matching works

Errors

Every error is {"error":{"code","message","details?"}}. Codes: invalid_request, invalid_json, missing_identifier, insufficient_identifiers, invalid_gtin, invalid_vin, invalid_ndc, invalid_date, invalid_model_year, conflicting_identifiers, unknown_category, category_not_covered, jurisdiction_not_supported, payment_required, invalid_payment, payment_rejected, payment_expired, payment_wrong_*, idempotency_key_required, idempotency_conflict, payment_replay, in_progress, settlement_failed, rate_limited, not_configured, payment_provider_unavailable, service_unavailable.