Loading the API docs
Loading the API docs
Built with PayPal, Claude, Elastic, Channel3, Bryntum, AG Grid, APIMatic and Render.
Every endpoint, its fields, errors and limits. The same description is at /openapi.json for API clients, SDK generators and AI agents.
Send your key as Authorization: Bearer rm_test_…. With a key: 60 requests a minute and 1,000 a day, and every call shows on your usage page. Without one: 20 a minute.
Every response has the same shape: { data, meta, error }. meta carries request_id, version and latency_ms. Rate-limit headers: X-RateLimit-Limit, X-RateLimit-Remaining, and Retry-After on a 429.
16 endpoints. Each one opens to its fields and an example request.
GET /api/v1/recallsSearch US consumer product recalls since 2024 in plain words, or list the newest that fit the filters. Each hit carries its proof rule in short.| Field | Type | About |
|---|---|---|
query | query | Plain words, for example power bank or a crib that tips. Leave out to list the newest recalls. |
photo_refund | "true" | "false" | true for recalls that offer a refund for a photo of the product made safe; false for the others. |
year | query | Recall year, 2024 to 2026. |
category | query | Product type, for example Heaters or Baby and nursery. |
remedy | "Refund" | "Repair" | "Replace" | "Dispose" | "New Instructions" | "Label" | "Inspect" | A CPSC remedy option. |
units | "under-1k" | "1k-10k" | "10k-50k" | "50k-plus" | How many units were recalled. |
limit | query | Hits to return, 1 to 100. Default 20. A search with words returns at most 30. |
offset | query | Skip this many hits, for the next page. |
curl "https://remedy-y0ym.onrender.com/api/v1/recalls?query=power%20bank&photo_refund=true" \ -H "Authorization: Bearer rm_test_…"
| Field | Type | About |
|---|---|---|
total | integer | How many recalls fit. With words, the matches in the reranked top 30. |
hits[].number | string | The CPSC recall number. |
hits[].title | string | The recall's title as the CPSC published it. |
hits[].date | string | Recall date, YYYY-MM-DD. |
hits[].photo_refund | boolean | The remedy offers a refund for a photo of the product made safe. |
hits[].units | integer | null | US units recalled, as the CPSC states them. |
hits[].proof_rule | object | null | The rule in short: actions, marker_text, must_show, remedy, refund_amount, steps. |
hits[].score | number | null | Relevance from the reranker. Null when listing. |
meta.search.mode | string | elastic (hybrid search), local (the in-app keyword ranking) or list. |
GET /api/v1/recalls?query=power%20bank&photo_refund=true&limit=2{
"data": {
"query": "power bank",
"filters": {
"photoRefund": true
},
"total": 30,
"hits": [
{
"number": "27056",
"title": "HAIARA Power Banks Recalled Due to Risk of Serious Injury or Death from Fire and Burn Hazards; Sold on Amazon.com by Mitrytech",
"date": "2026-10-29",
"category": "Batteries and chargers",
"product_names": [
"HAIARA power banks"
],
"photo_refund": true,
"units": 11000,
"remedies": [
"Refund"
],
"image": {
"url": "https://cpsc.gov/s3fs-public/HAIARA1.jpg?VersionId=myWygu.qNAqSjgZDm8rx5DlFPHoyO9tW",
"thumb": "/recalls/27056/1.webp",
"caption": "HAIARA power bank, model W5 PRO (front)"
},
"cpsc_url": "https://cpsc.gov/Recalls/2027/HAIARA-Power-Banks-Recalled-Due-to-Risk-of-Serious-Injury-or-Death-from-Fire-and-Burn-Hazards-Sold-on-Amazon-com-by-Mitrytech",
"page": "/recalls/27056",
"score": 1.295,
"proof_rule": {
"photo_required": true,
"actions": [
"write_recalled"
],
"marker_text": "recalled",
"must_show": [
"whole_product",
"marking"
],
"remedy": "full_refund",
"refund_amount": null,
"refund_amount_text": "full refund",
"steps": [
"Write recalled on the power bank in permanent marker.",
"Take a photo of the power bank showing the writing.",
"Email the photo to Mitrytech at HAIARArecall@outlook.com.",
"Dispose of the power bank following local laws."
]
},
"sample": false
},
{
"number": "26090",
"title": "Belkin Recalls Portable Power Banks and Wireless Charging Stands Due to Fire and Burn Hazards",
"date": "2025-11-13",
"category": "Batteries and chargers",
"product_names": [
"Portable Power Banks and Wireless Charging Stands"
],
"photo_refund": true,
"units": 83500,
"remedies": [
"Refund"
],
"image": {
"url": "https://www.cpsc.gov/s3fs-public/belkin-01.jpg",
"thumb": "/recalls/26090/1.webp",
"caption": "Recalled MMA008 Portable Wireless Charging Stand"
},
"cpsc_url": "https://www.cpsc.gov/Recalls/2026/Belkin-Recalls-Portable-Power-Banks-and-Wireless-Charging-Stands-Due-to-Fire-and-Burn-Hazards",
"page": "/recalls/26090",
"score": 1.203,
"proof_rule": {
"photo_required": true,
"actions": [],
"marker_text": null,
"must_show": [
"whole_product"
],
"remedy": "full_refund",
"refund_amount": null,
"refund_amount_text": "a full refund",
"steps": [
"Stop using the power bank or charging stand.",
"Take photos of the front and back of the product.",
"Send the photos with the online recall submission form.",
"Ask your hazardous waste center before dropping off the device."
]
},
"sample": false
}
],
"agencies": {
"checked": false,
"hits": [],
"agencies": [],
"ms": 0,
"note": "The CPSC search found the product, so the other agencies were not asked."
}
},
"meta": {
"request_id": "req_2a6934ba527b4836abcb",
"version": "2026-11-05",
"latency_ms": 526,
"search": {
"mode": "elastic",
"model": ".jina-embeddings-v3",
"reranker": ".jina-reranker-v3",
"agencies": []
}
},
"error": null
}GET /api/v1/recalls/{number}One recall: its products, official images, hazard, the remedy exactly as published, and its proof rule with confidence per field.| Field | Type | About |
|---|---|---|
number required | path | The CPSC recall number, for example 27056. |
curl "https://remedy-y0ym.onrender.com/api/v1/recalls/27056" \ -H "Authorization: Bearer rm_test_…"
| Field | Type | About |
|---|---|---|
remedy_text | string | The official remedy, every paragraph joined, word for word. |
hazard | string | The hazard, as the CPSC states it. |
images[] | array of objects | Official CPSC images: url, caption, and a local thumbnail where one is stored. |
products[] | array of objects | Each product: name, model, type, units_text. |
proof_rule | object | null | The full stored rule, with explanation, confidence (actions, must_show, remedy, each 0 to 1), source and model. |
claim_page | string | Where an owner starts a claim on Remedy. |
GET /api/v1/recalls/27056{
"data": {
"number": "27056",
"title": "HAIARA Power Banks Recalled Due to Risk of Serious Injury or Death from Fire and Burn Hazards; Sold on Amazon.com by Mitrytech",
"date": "2026-10-29",
"category": "Batteries and chargers",
"units": 11000,
"units_text": "About 11,000",
"hazard": "The power bank’s lithium battery can explode and ignite, posing fire and burn hazards to consumers.",
"remedy_text": "Consumers should stop using the recalled power banks immediately. Consumers who purchased their power banks on Amazon.com from Mitrytech should contact Mitrytech for instructions on how to receive a full refund. To recei...",
"remedies": [
"Refund"
],
"photo_refund": true,
"flags": {
"photo": true,
"refund": true,
"marker": true,
"cut": false,
"email": true,
"webmail": true
},
"products": [
{
"name": "HAIARA power banks",
"model": "",
"type": "Battery Chargers",
"units_text": "About 11,000"
}
],
"firms": [],
"retailers": [
"Sold At: Amazon.com from May 2025 through September 2026 for between $18 to $22.",
"Huizhou Yancheng Trading Co., Ltd. d/b/a Mitrytech, of China"
],
"consumer_contact": "Email at HAIARArecall@outlook.com or online at www.haiara.net/recalls.html or www.haiara.net and click on “Recalls” for ...",
"images": [
{
"url": "https://cpsc.gov/s3fs-public/HAIARA1.jpg?VersionId=myWygu.qNAqSjgZDm8rx5DlFPHoyO9tW",
"caption": "HAIARA power bank, model W5 PRO (front)",
"thumb": "/recalls/27056/1.webp",
"width": 217,
"height": 322
}
],
"cpsc_url": "https://cpsc.gov/Recalls/2027/HAIARA-Power-Banks-Recalled-Due-to-Risk-of-Serious-Injury-or-Death-from-Fire-and-Burn-Hazards-Sold-on-Amazon-com-by-Mitrytech",
"page": "/recalls/27056",
"claim_page": "/claim/27056",
"proof_rule": {
"photo_required": true,
"actions": [
"write_recalled"
],
"marker_text": "recalled",
"must_show": [
"whole_product",
"marking"
],
"remedy": "full_refund",
"refund_amount_text": "full refund",
"refund_amount": null,
"contact_channel": "email",
"steps": [
"Write recalled on the power bank in permanent marker.",
"Take a photo of the power bank showing the writing.",
"Email the photo to Mitrytech at HAIARArecall@outlook.com.",
"Dispose of the power bank following local laws."
],
"explanation": {
"plain": "Stop using the power bank. Write recalled on it in permanent marker, send a photo, and throw it away safely to get your money back.",
"technical": "\"submit a photo of their recalled power bank with the word recalled written on it in permanent marker\" sets photo_requir..."
},
"confidence": {
"actions": 0.95,
"must_show": 0.93,
"remedy": 0.97
},
"source": "selfcheck",
"model": "claude-opus-5-5",
"extracted_at": "2026-11-05T19:11:05.337Z"
},
"sample": false,
"sample_note": null
},
"meta": {
"request_id": "req_803d910f558040aaac54",
"version": "2026-11-05",
"latency_ms": 0
},
"error": null
}POST /api/v1/proof-ruleClaudeTurn a recall's remedy into a proof rule: what to cut or mark, what the photo must show, and the refund. Send a recall number for the stored rule, or any remedy text.With remedy_text, the quick reader answers at once with no AI. Add "mode": "claude" and an API key for Claude Opus 5.5 with a self-check, up to 20 a day per key.
| Field | Type | About |
|---|---|---|
recall_number | string | A CPSC recall number, for example "27056". Returns the stored rule for that recall. |
remedy_text | string | Any recall's remedy text, as the CPSC published it. Returns a rule read from it. |
consumer_contact | string | The recall's consumer contact text, which helps find how the photo is sent. Optional. |
mode | "quick" | "claude" | For remedy_text: "quick" is the deterministic reader (no AI, instant). "claude" uses Claude Opus 5.5 with a self-check, needs an API key and counts toward a daily limit. Default "quick". |
curl -X POST "https://remedy-y0ym.onrender.com/api/v1/proof-rule" \
-H "Authorization: Bearer rm_test_…" \
-H "Content-Type: application/json" \
-d '{"recall_number":"27056"}'| Field | Type | About |
|---|---|---|
rule | object | The proof rule. See the fields below. |
rule.photo_required | boolean | True when the owner must send a photo to get the remedy. |
rule.actions | array of string | What to do to the product first: cut_cord, cut_in_half, write_recalled, remove_part, puncture, disassemble, other. |
rule.marker_text | string | null | The exact words to write on the product, for example recalled. |
rule.must_show | array of string | What the photo must show: whole_product, label, model_number, serial_or_lot, date_code, cut_or_damage, marking. |
rule.remedy | string | What the owner gets: full_refund, partial_refund, replacement, repair, refund_or_replacement, other. |
rule.refund_amount | number | null | A fixed dollar amount the remedy states. Null for a full refund of the price paid. |
rule.steps | array of string | Up to four plain steps for the owner. |
rule.confidence | object | How sure the reader is of actions, must_show and remedy, each 0 to 1. |
source | string | stored (extracted by Claude in a batch), claude (read just now) or quick (deterministic, no AI). |
lint | array of objects | Mechanical checks the rule must pass against its remedy text. Empty when all pass. |
POST /api/v1/proof-rule {"recall_number":"27056"}{
"data": {
"recall": {
"number": "27056",
"title": "HAIARA Power Banks Recalled Due to Risk of Serious Injury or Death from Fire and Burn Hazards; Sold on Amazon.com by Mitrytech"
},
"rule": {
"photo_required": true,
"actions": [
"write_recalled"
],
"marker_text": "recalled",
"must_show": [
"whole_product",
"marking"
],
"remedy": "full_refund",
"refund_amount_text": "full refund",
"refund_amount": null,
"contact_channel": "email",
"steps": [
"Write recalled on the power bank in permanent marker.",
"Take a photo of the power bank showing the writing.",
"Email the photo to Mitrytech at HAIARArecall@outlook.com.",
"Dispose of the power bank following local laws."
],
"explanation": {
"plain": "Stop using the power bank. Write recalled on it in permanent marker, send a photo, and throw it away safely to get your money back.",
"technical": "\"submit a photo of their recalled power bank with the word recalled written on it in permanent marker\" sets photo_requir..."
},
"confidence": {
"actions": 0.95,
"must_show": 0.93,
"remedy": 0.97
}
},
"source": "stored",
"model": "claude-opus-5-5",
"extracted_at": "2026-11-05T19:11:05.337Z",
"method": "Claude Opus 5.5, structured output at medium effort, then a self-check pass against the re...",
"lint": []
},
"meta": {
"request_id": "req_371b35846ea646cbaeaf",
"version": "2026-11-05",
"latency_ms": 2
},
"error": null
}POST /api/v1/verifyClaudeCheck an owner's photo against a recall's proof rule: right product, made safe, their own photo, within the recall. Returns each check and the decision. Nothing is paid.| Field | Type | About |
|---|---|---|
photo required | file | JPEG, PNG or WebP, up to 10 MB. |
recall_number required | string | The CPSC recall number the photo is for. |
amount | string | The refund the firm would pay, for example 34.99. Optional; the decision then applies a $50 auto-approve cap. |
curl -X POST "https://remedy-y0ym.onrender.com/api/v1/verify" \ -H "Authorization: Bearer rm_test_…" \ -F "photo=@photo.jpg" \ -F "recall_number=27056"
| Field | Type | About |
|---|---|---|
decision | string | verified, retake (with guidance) or firm_review (a person at the firm looks). |
mode | string | full (every check, with Claude vision) or free (quality and own-photo checks only, no AI). Without a key it is free. |
checks.C1 to checks.C6 | object | Each check: name, status (pass, fail, unclear, skipped, unavailable), score, a plain reason and a technical one. |
guidance | object | null | For a retake: what to change, in plain steps. |
summary | object | The decision in one plain sentence and one technical one. |
timings | object | Milliseconds for each stage and in total. |
POST /api/v1/verify (photo: the recall's own official picture, recall_number=27056, no key){
"data": {
"decision": "retake",
"decided_by": "own_photo",
"mode": "free",
"mode_note": "Without an API key only the free checks run: photo quality and the own-photo match. Add a key for the full checks.",
"summary": {
"plain": "Please send a photo of your own product.",
"technical": "Retake (own_photo). Own-photo check: Matches this recall's official image https://cpsc.gov/s3fs-public/HAIARA1.jpg?VersionId=myWygu.qNAqSjgZDm8rx5DlFPHoyO9tW (\"..."
},
"guidance": {
"plain": "Please send a photo of your own product.",
"steps": [
"Take a new photo of the product with your phone camera.",
"Show the product itself, not a screen, a printout or the recall picture.",
"We ask for your own photo so the refund goes to the person who has the product."
],
"technical": "Own-photo check: Matches this recall's official image https://cpsc.gov/s3fs-public/HAIARA1.jpg?VersionId=myWygu.qNAqSjgZDm8rx5DlFPHoyO9tW (\"HAIARA power bank, model W5 PRO (front)\") at 0 bits (upright). dHash e48280e0c0c1c9e0; nearest official 0 bits, nearest earlier claim none (reused at 10 or less)."
},
"checks": {
"C1": {
"name": "Right product",
"status": "skipped",
"pass": false,
"score": null,
"reason": "Not checked yet.",
"technical": "The photo matches one of this recall's official images."
},
"C2": {
"name": "Made safe",
"status": "skipped",
"pass": false,
"score": null,
"reason": "Not checked yet.",
"technical": "The photo matches one of this recall's official images."
},
"C3": {
"name": "Your own photo",
"status": "fail",
"pass": false,
"score": null,
"reason": "This is the official recall picture. Please send a photo of your own product.",
"technical": "Matches this recall's official image https://cpsc.gov/s3fs-public/HAIARA1.jpg?VersionId=myWygu.qNAqS..."
},
"C4": {
"name": "Within the recall",
"status": "skipped",
"pass": false,
"score": null,
"reason": "Not checked yet.",
"technical": "The photo matches one of this recall's official images."
},
"C5": {
"name": "Claim limits",
"status": "pass",
"pass": true,
"score": null,
"reason": "This claim is within the limit for one purchase.",
"technical": "Payee claim 1 of 1 unit purchased; recall claim 1 of 11000 units."
},
"C6": {
"name": "Not already refunded",
"status": "pass",
"pass": true,
"score": null,
"reason": "No PayPal purchase linked.",
"technical": "No capture is linked, so there is no earlier PayPal refund or dispute to check."
}
},
"amount": null,
"recall": {
"number": "27056",
"title": "HAIARA Power Banks Recalled Due to Risk of Serious Injury or Death from Fire and Burn Hazards; Sold on Amazon.com by Mitrytech"
},
"proof_rule": {
"photo_required": true,
"actions": [
"write_recalled"
],
"marker_text": "recalled",
"must_show": [
"whole_product",
"marking"
],
"remedy": "full_refund",
"refund_amount": null,
"refund_amount_text": "full refund",
"steps": [
"Write recalled on the power bank in permanent marker.",
"Take a photo of the power bank showing the writing.",
"Email the photo to Mitrytech at HAIARArecall@outlook.com.",
"Dispose of the power bank following local laws."
]
},
"photo": {
"sha256": "a58b28b7cd859a6c481d4901c2326f0419cb8b10cf2ada2f49a9f0fa934da0c7",
"dhash": "e48280e0c0c1c9e0",
"width": 217,
"height": 322,
"mime": "image/jpeg"
},
"review": null,
"model": null,
"timings": {
"decode_ms": 22,
"official_ms": 1,
"vision_ms": 0,
"checks_ms": 0,
"reviewers_ms": 0,
"total_ms": 23
},
"payment": null,
"note": "No claim was stored and nothing was paid. To open a claim and pay the refund, use POST /api/claims."
},
"meta": {
"request_id": "req_7375568d77304461b6a3",
"version": "2026-11-05",
"latency_ms": 28
},
"error": null
}POST /api/v1/labelClaudeIs it recalled? Send a photo of the product's label: Claude reads the brand, product, model numbers, UPC and lot or date codes, each with the text read, and code looks them up in every recall since 2024. A model number or UPC in a recall's own list settles it. The photo is never stored.Claude reads; code decides. Fields whose value is not in the line it was read from, or read with confidence under 0.4, are set aside. Each model number read is one catalog-scan row with Claude off, so a label costs one model call. Live readings: 6 in 10 minutes and 20 a day per visitor, 25 a day per key, within the site's daily AI budget; the samples count against nothing.
| Field | Type | About |
|---|---|---|
photo | file | JPEG, PNG or WebP of the label, up to 10 MB. Leave out to send a sample instead. |
sample | string | Instead of a photo: a sample label, brightline, kidisle or lenovo. Replays its recorded reading with no model call. Also accepted as JSON. |
curl -X POST "https://remedy-y0ym.onrender.com/api/v1/label" \ -H "Authorization: Bearer rm_test_…" \ -F "photo=@photo.jpg"
| Field | Type | About |
|---|---|---|
outcome | string | match (one recall lists a code read from the label), candidates (close recalls to compare), no_match, unreadable, or person (a person is in the photo, so a photo of the label alone is asked for). |
plain | string | The answer in one sentence for the owner, for example Matched by model number KC101B, read from your photo. |
matches[] | array of objects | Each recall: number, title, product, photo_refund, remedy_summary, refund_amount, claim_url, page, image, matched_by (model, upc or keywords), code, how, recall_models, and compare (lot or date codes the recall states beside the label's). |
label | object | What was read: brand, product, models, upc (with check_digit_ok) and lots, each with value, text_read, confidence, and whether it was used or set aside and why. |
search | string | The brand and product as read, to search by name when nothing matched. |
source | object | kind (live or recorded), model, recorded_at, sample, ms and cost_usd of the reading. |
POST /api/v1/claimsClaudeOpen a claim with the owner's photo. Remedy stores it, runs the six checks and records the decision. Paying is the next call. Sandbox only.Send Accept: text/event-stream to get each stage as it runs (claim, stage, result and error events). The same route as POST /api/claims, which the /claim page uses, with the same limits on live checks.
| Field | Type | About |
|---|---|---|
photo required | file | JPEG or PNG of the product made safe, up to 15 MB. |
recall required | string | The CPSC recall number, for example 27056. |
sale_id | string | The sample-shop purchase to refund, from the shop's receipt. Optional. |
capture_id | string | The PayPal capture to refund to, inside 180 days. Optional. |
paypal_email | string | Find the sample-shop purchase by the buyer's PayPal email instead. Optional. |
curl -X POST "https://remedy-y0ym.onrender.com/api/v1/claims" \ -H "Authorization: Bearer rm_test_…" \ -F "photo=@photo.jpg" \ -F "recall=27056"
| Field | Type | About |
|---|---|---|
id | string | The claim id (a UUID). |
status, decision | string | Where the claim stands, and the checks' verdict: verified, retake or firm_review. |
checks[] | array of objects | C1 to C6, each with its status and plain reason. |
amount | object | null | The refund: the firm's amount, or the linked PayPal capture's, whichever is lower. |
receipt_url | string | The owner's live receipt page. |
GET /api/v1/claims/{id}Where a claim stands: the six checks, the decision, and the payment with its PayPal status. The payee is masked.The same route as GET /api/claims/{id}.
| Field | Type | About |
|---|---|---|
id required | path | The claim id returned when it was opened. |
refresh | "1" | 1 asks PayPal for the payment's latest status first. |
curl "https://remedy-y0ym.onrender.com/api/v1/claims/00000000-0000-0000-0000-000000000000" \ -H "Authorization: Bearer rm_test_…"
| Field | Type | About |
|---|---|---|
payment.status_plain | string | null | Where the money is, in plain words. |
payment.paypal_status | string | null | PayPal's own word for it, for example SUCCESS or UNCLAIMED. |
payment.ids | object | The PayPal payout batch, item, refund, order and capture ids. |
POST /api/v1/claims/{id}/paySay where the refund goes, then pay it in the PayPal sandbox: a payout to PayPal or Venmo, a refund to the original PayPal purchase inside 180 days, or a safe replacement.A linked purchase is refunded to its capture and needs no payee. The firm's auto rule pays a verified claim at or under its cap at once; anything else waits for a person at the firm. A second call never pays twice. The same route as POST /api/claims/{id}/pay.
| Field | Type | About |
|---|---|---|
id required | path | The claim id. |
| Field | Type | About |
|---|---|---|
choice | "money" | "replacement" | money (with payee_type and payee) or replacement (with replacement_id). Default money. |
payee_type | "email" | "phone" | "venmo" | Where a money refund goes. Venmo falls back to a PayPal phone payout in the sandbox. |
payee | string | The owner's PayPal email or phone number. Stored encrypted; shown masked. |
replacement_id | string | A product id from the replacements call. |
curl -X POST "https://remedy-y0ym.onrender.com/api/v1/claims/00000000-0000-0000-0000-000000000000/pay" \
-H "Authorization: Bearer rm_test_…" \
-H "Content-Type: application/json" \
-d '{"choice":"money","payee_type":"email","payee":"jordan@example.com"}'| Field | Type | About |
|---|---|---|
payment | object | The plan and the payment: route, amount, approval, and PayPal's status. |
GET /api/v1/claims/{id}/replacementsProducts a verified owner can choose instead of money, found by Channel3, each checked against active recalls first.The same route as GET /api/claims/{id}/replacements.
| Field | Type | About |
|---|---|---|
id required | path | The claim id. |
curl "https://remedy-y0ym.onrender.com/api/v1/claims/00000000-0000-0000-0000-000000000000/replacements" \ -H "Authorization: Bearer rm_test_…"
POST /api/v1/scanClaudeCheck a whole catalog at once. Each row comes back photo_refund (a recall pays for a photo of it made safe), recalled (a recall with another remedy), clear or unknown, with the recall and the claim link.Up to 50 rows without a key, 500 with one. The body can also be a CSV (Content-Type text/csv, or a multipart file field) with name, model, sku and brand columns. A stated model or UPC that appears in a recall's own list settles a row without AI; Claude Opus 5.5 reads only the ambiguous rows, in batches, within the site's daily AI budget.
| Field | Type | About |
|---|---|---|
format | "csv" | csv returns the results as a CSV file instead of JSON. |
ai | "false" | With a CSV body: false skips Claude for the ambiguous rows. |
| Field | Type | About |
|---|---|---|
items[] required | array of objects | Up to 500 rows (50 without an API key). |
items[].name required | string | The product as listed, for example "HAIARA 10000mAh power bank". |
items[].model | string | null | The model number, when known. A model in the recall's own list settles the row. |
items[].sku | string | null | Your SKU or the UPC. A UPC in the recall's list settles the row. |
items[].brand | string | null | The brand or maker, when it is not in the name. |
ai | boolean | False skips Claude for the ambiguous rows, which then come back unknown. Default true. Default true. |
curl -X POST "https://remedy-y0ym.onrender.com/api/v1/scan" \
-H "Authorization: Bearer rm_test_…" \
-H "Content-Type: application/json" \
-d '{"items":[{"name":"HAIARA 10000mAh power bank","brand":"HAIARA"},{"name":"Bamboo cutting board, 18 by 12 inch","brand":"Greenfield Kitchen"}]}'| Field | Type | About |
|---|---|---|
summary | object | Counts: total, photo_refund, recalled, clear, unknown. |
results[].status | string | photo_refund, recalled, clear or unknown. |
results[].confidence | number | 0 to 1: how sure the match (or the clear) is. |
results[].matched_by | string | null | model or upc (a code in the recall's own list), keywords (the recall's words cover the row's), or claude (read against its candidates). |
results[].recall | object | null | number, title, date, photo_refund, remedy_summary, refund_amount, refund_amount_text, cpsc_url, page. |
results[].claim_url | string | null | The owner's claim page, for a photo-refund recall. |
results[].reason | string | Why the row was decided this way, in one sentence. |
ai | object | Whether Claude read any ambiguous rows (used, rows, note). |
POST /api/v1/scan {"items": the sample catalog, 9 rows}{
"data": {
"summary": {
"total": 9,
"photo_refund": 5,
"recalled": 1,
"clear": 3,
"unknown": 0
},
"results": [
{
"row": 1,
"item": {
"name": "HAIARA power banks",
"model": null,
"sku": null,
"brand": null
},
"status": "photo_refund",
"confidence": 1,
"matched_by": "keywords",
"reason": "The recall's product and firm cover 100% of the row's words.",
"recall": {
"number": "27056",
"title": "HAIARA Power Banks Recalled Due to Risk of Serious Injury or Death from Fire and...",
"date": "2026-10-29",
"photo_refund": true,
"remedy_summary": "Write RECALLED, Full refund",
"refund_amount": null,
"refund_amount_text": "full refund",
"cpsc_url": "https://cpsc.gov/Recalls/2027/HAIARA-Power-Banks-Recalled-Due-to-Risk-of-Serious-Injury-or-Death-from-Fire-and-Burn-Hazards-Sold-on-Amazon-com-by-Mitrytech",
"page": "http://localhost:3400/recalls/27056"
},
"claim_url": "http://localhost:3400/claim/27056"
},
{
"row": 2,
"item": {
"name": "Wantefully Hair Dryer Brushes",
"model": null,
"sku": null,
"brand": null
},
"status": "photo_refund",
"confidence": 1,
"matched_by": "keywords",
"reason": "The recall's product and firm cover 100% of the row's words.",
"recall": {
"number": "26754",
"title": "Guang Zhou Recalls Wantefully Hair Dryer Brushes Due to Risk of Serious Injury o...",
"date": "2026-09-10",
"photo_refund": true,
"remedy_summary": "Cut the cord, Full refund",
"refund_amount": null,
"refund_amount_text": "full refund",
"cpsc_url": "https://cpsc.gov/Recalls/2026/Guang-Zhou-Recalls-Wantefully-Hair-Dryer-Brushes-Due-to-Risk-of-Serious-Injury-or-Death-from-Electrocution-Shock-and-Burn-Hazards-Violate-Federal-Regulations",
"page": "http://localhost:3400/recalls/26754"
},
"claim_url": "http://localhost:3400/claim/26754"
},
{
"row": 7,
"item": {
"name": "Bamboo cutting board, 18 by 12 inch",
"model": null,
"sku": "GK-CB-1812",
"brand": "Greenfield Kitchen"
},
"status": "clear",
"confidence": 0.89,
"matched_by": null,
"reason": "No recall since 2024 covers these words; the nearest, recall 26658, shares too little.",
"recall": null,
"claim_url": null
}
],
"ai": {
"used": false,
"rows": 0,
"note": "No row needed the AI reader."
}
},
"meta": {
"request_id": "req_e05bd566185047b78fc7",
"version": "2026-11-05",
"latency_ms": 1310,
"search": {
"mode": "elastic",
"model": ".jina-embeddings-v3"
},
"scan_ms": 1310
},
"error": null
}GET /api/v1/scan/sampleA small catalog built from real recalls in Remedy's data plus three everyday items no recall covers, ready to send to the scan.curl "https://remedy-y0ym.onrender.com/api/v1/scan/sample" \ -H "Authorization: Bearer rm_test_…"
| Field | Type | About |
|---|---|---|
items[] | array of objects | name, model, sku, brand: the same fields the scan takes. |
GET /api/v1/scan/sample{
"data": {
"note": "A sample catalog: real CPSC recalls from Remedy's data (public domain) and three everyday items no recall covers. Send it to POST /api/v1/scan as { items }.",
"items": [
{
"name": "HAIARA power banks"
},
{
"name": "Wantefully Hair Dryer Brushes"
},
{
"name": "QZH.DUAO Children’s Pajama Sets"
},
{
"name": "X-VESOLJE Nursing Pillows"
}
]
},
"meta": {
"request_id": "req_9fcfec9d371d4169ac0b",
"version": "2026-11-05",
"latency_ms": 1
},
"error": null
}POST /api/v1/hash-pool/checkAsk whether a photo is already in the shared pool: every photo claimed on any recall at any firm, every hash a connected firm registered, and the published pictures of every recall. Send the 64-bit hash only; the answer is a hit or no hit, the distance and an opaque ref.Send the upright 64-bit dHash of the photo (the pipeline is documented in src/lib/verify/dhash.ts: greyscale, fit inside 256 by 256, a 9 by 8 grid, one bit per row neighbour). The pool holds upright hashes and compares your one hash with them, so hash the photo as it stands. No photo crosses, and nothing about the holder comes back but the ref.
| Field | Type | About |
|---|---|---|
dhash required | string | The 64-bit perceptual hash of the photo, upright, as 16 lowercase hex characters (the dHash in src/lib/verify/dhash.ts). |
phash | string | Optional: the second 64-bit hash of the photo's center (src/lib/verify/phash.ts), which holds under a small crop or turn. Matched against claim and partner rows that carry one, at 6 bits. |
recall_number | string | The recall the photo is claimed on. With it, that recall's own earlier claim photos and published pictures are matched at 10 bits; everything else at 4. |
curl -X POST "https://remedy-y0ym.onrender.com/api/v1/hash-pool/check" \
-H "Authorization: Bearer rm_test_…" \
-H "Content-Type: application/json" \
-d '{"dhash":"337bfb9f4e7f3e0f","recall_number":"FW-2026-01"}'| Field | Type | About |
|---|---|---|
hit | boolean | True when a stored hash is within the threshold. |
distance | integer | null | Differing bits between your hash and the closest stored one, 0 to 64. |
threshold_bits | integer | null | The threshold that applied to the hit: 10 for the claimed recall's own pictures and earlier claim photos, 4 for everything else. |
ref | string | null | The holding row's opaque ref: a photo row id or the ref a firm registered. It opens nothing and names no firm, recall or claimant. |
source | string | null | claim (a photo claimed on Remedy), partner (registered by a connected firm) or official (a published recall picture). |
pool | object | How many claim rows, partner rows and distinct published pictures were compared. |
POST /api/v1/hash-pool/registerAdd the hash of a photo your firm has paid a claim on, so the same photo sent to any other firm is held for a person before any model call. Only the hash, your recall number and your own opaque ref are stored.Needs a firm key: a key tied to a firm connected to Remedy, with the hash-pool:register scope, issued to the firm when it connects. A self-serve sandbox key is answered 403 forbidden; checking needs no key. The firm is recorded in Remedy's audit ledger, never in the pool row, so a hit at another firm can never name yours. A hash within 4 bits of one registered, sent on any other recall at any firm, is held for a person at that firm.
| Field | Type | About |
|---|---|---|
dhash required | string | The 64-bit perceptual hash of the photo, upright, as 16 lowercase hex characters (the dHash in src/lib/verify/dhash.ts). |
phash | string | Optional: the second 64-bit hash of the photo's center (src/lib/verify/phash.ts), which holds under a small crop or turn. Matched against claim and partner rows that carry one, at 6 bits. |
recall_number required | string | The recall the photo was claimed on, as your firm names it. |
ref | string | Your own opaque id for the row, up to 64 characters; it is the only thing another firm sees on a hit. Left out, Remedy makes a UUID. |
curl -X POST "https://remedy-y0ym.onrender.com/api/v1/hash-pool/register" \
-H "Authorization: Bearer rm_test_…" \
-H "Content-Type: application/json" \
-d '{"dhash":"337bfb9f4e7f3e0f","recall_number":"BH-2026-01","ref":"partner-demo-1"}'| Field | Type | About |
|---|---|---|
registered | boolean | True when the row is new. False when the same ref was already in the pool; nothing changed. |
ref | string | The ref stored: yours, or the UUID Remedy made. |
dhash | string | The hash stored. |
GET /api/embed/badgeA small server-rendered page for an iframe: the recall's one-line remedy and refund, with a Get your refund link. Light and dark follow the visitor's setting.Embed it with <iframe src="/api/embed/badge?recall=27056" title="Recall badge" loading="lazy" style="border:0;width:100%;max-width:28rem;height:7.5rem"></iframe>, or load /api/embed/badge.js with data-recall="27056" on the script tag to insert the same badge where the script sits.
| Field | Type | About |
|---|---|---|
recall | query | A CPSC recall number, for example 27056. |
q | query | Or the product in plain words; the best-matching recall is shown. |
curl "https://remedy-y0ym.onrender.com/api/embed/badge?recall=27056"
GET /api/ledger/verifyRecompute the audit ledger's SHA-256 hash chain from the first entry and report whether every entry still matches.curl "https://remedy-y0ym.onrender.com/api/ledger/verify"
GET /api/healthWhether PayPal, Claude, the database and each tool Remedy is built on are live, on a fallback, or not connected right now.curl "https://remedy-y0ym.onrender.com/api/health"
The same search, proof rules and photo checks, as tools for AI assistants, over the Model Context Protocol (streamable HTTP, JSON answers). Add it to Claude Code with:
claude mcp add --transport http remedy https://remedy-y0ym.onrender.com/api/mcp
| Tool | What it does |
|---|---|
ping | Confirms the Remedy MCP server is reachable and says which API version it serves. Changes nothing. |
search_recalls | Finds US consumer product recalls since 2024 from plain words, for example "power bank" or "crib that tips over". Each result says whether the recall pays a refund for a photo of the product made safe, and what to do. Changes nothing. |
scan_catalog | Checks a list of products (name, with model, SKU or brand when known) against every CPSC recall since 2024 at once. Each row comes back photo_refund (a recall pays for a photo of it made safe, with the claim link), recalled (a recall with another remedy), clear or unknown. Changes nothing. |
check_label | Says whether a product is recalled from a photo of its label (the rating plate, sticker or tag with the model number). Claude reads the label once; code then looks the model number or UPC up in every CPSC recall since 2024, and a code in a recall's own list settles it. Returns match, candidates, no_match, unreadable or person, with each recall, how it matched, and the owner's claim link. The photo is never stored. Reading your own photo needs an API key; the sample labels need none. Changes nothing. |
get_proof_rule | Reads one recall's remedy as a proof rule: what to cut or mark on the product, what the photo must show, and the refund, with the official remedy text it came from. Changes nothing. |
verify_photo | Checks an owner's photo against a recall's proof rule: right product, made safe, their own photo, within the recall. Returns each check and the decision (verified, retake or firm_review). Without an API key no model is called: the free checks run, and a photo checked before is answered from the verification cache. Stores nothing and pays nothing. |
open_claim | Starts a refund claim for a recall. With only the recall number it returns the owner's own claim link and checklist, and changes nothing. With the owner's photo it opens the claim and runs the six checks; the owner then chooses where the refund goes on their receipt page. This tool never pays. Changes: With a photo, opens a claim in the recalling firm's queue (sandbox). Nothing is paid by this tool. |
claim_status | Says where a claim stands: the checks, the decision, and the payment with its PayPal status. Changes nothing. |
Send your key as Authorization: Bearer rm_test_… for the full photo checks (up to 25 a day per key); without one, verify_photo calls no model: the free checks run, and a photo checked before is answered from the verification cache. Discovery: server card, AI catalog and llms.txt.
Every error has a code you can branch on and a plain message you can show to people.
invalid_request 400, 409, 413, 422forbidden 403not_found 404rate_limited 429internal 500