API Documentation

Complete reference for integrating Safe Shelf API into your e-commerce platform.

Authentication

All API requests require a Bearer token in the Authorization header:

curl -H "Authorization: Bearer *** \
  -H "Content-Type: application/json" \
  https://api.safeshelf.com/v1/check

POST /v1/check — Single Product Check

Request

POST https://api.safeshelf.com/v1/check
Content-Type: application/json
Authorization: Bearer ***  "product_name": "Instant Pot Duo 7-in-1",
  "brand": "Instant Brands",
  "sku": "IP-DUO60",
  "upc": "850007281156"
}

Response — Match Found

{
  "status": "MATCH",
  "confidence": 0.92,
  "matches": [{
    "recall_id": "26715",
    "title": "Instant Pot Pressure Cookers Recalled Due to Burn Hazard",
    "agency": "CPSC",
    "hazard": "Burn",
    "remedy": "refund",
    "recall_date": "2023-03-23",
    "url": "https://cpsc.gov/Recalls/2023/instant-pot",
    "confidence": 0.92
  }]
}

Response — No Match

{
  "status": "CLEAR",
  "confidence": 0.99,
  "matches": []
}

POST /v1/check/bulk — Bulk Check

Check up to 1,000 products in a single request. Maximum payload: 500KB.

{
  "products": [
    { "product_name": "Product A", "brand": "Brand X", "sku": "SKU-001" },
    { "product_name": "Product B", "brand": "Brand Y", "sku": "SKU-002" }
  ]
}

Response returns an array of results in the same order as input.

Webhooks — Real-time Notifications

Configure webhook endpoints in your dashboard to receive instant alerts when new recalls match your products.

Payload

{
  "event": "recall.match",
  "timestamp": "2024-01-15T10:30:00Z",
  "data": {
    "product_id": "prod_abc123",
    "product_name": "Instant Pot Duo",
    "match": {
      "recall_id": "26715",
      "title": "Instant Pot Pressure Cookers Recalled Due to Burn Hazard",
      "agency": "CPSC",
      "confidence": 0.92
    }
  }
}

Verification (HMAC-SHA256)

const crypto = require('crypto');
const signature = req.headers['x-safeshelf-signature'];
const expected = crypto
  .createHmac('sha256', process.env.WEBHOOK_SECRET)
  .update(JSON.stringify(req.body))
  .digest('hex');

if (signature !== expected) {
  return res.status(401).send('Invalid signature');
}

Error Codes

CodeHTTPDescription
UNAUTHORIZED401Invalid or missing API key
RATE_LIMITED429Monthly quota exceeded
VALIDATION_ERROR400Invalid request body
INTERNAL_ERROR500Server error — retry with backoff