API Reference

Base URL: https://api.greenscore.dev

Authentication

All endpoints (except /v1/health) require an API key:

Authorization: Bearer gs_live_your_api_key_here

Rate Limits

Every response includes rate limit headers:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1711900800

Endpoints

POST /v1/score Score a single product
POST /v1/score/batch Score up to 100 products
GET /v1/factors/search Search emission factors
GET /v1/factors/:id Get factor by ID
GET /v1/alternatives Find lower-impact alternatives
GET /v1/categories List product archetypes
GET /v1/sources List CO2 data sources
GET /v1/usage Current API key usage
GET /v1/export/factors Bulk factor export (Scale+)
GET /v1/health Health check No auth

POST /v1/score

Score a single product. Accepts barcode, product name, description, or base64 image.

Request body

{
  "barcode": "3017620422003",     // EAN/UPC barcode (optional)
  "name": "Nutella 400g",         // Product name (optional)
  "description": "...",            // Free-text description (optional)
  "image_base64": "...",           // JPEG base64 (optional, max 7.5MB)
  "weight_kg": 0.4,               // Override weight (optional)
  "price_eur": 3.49,              // Override price for spend-based (optional)
  "category": "Food"              // Override category (optional)
}

At least one of barcode, name, description, or image_base64 is required.

Response

{
  "data": {
    "product_name": "Nutella",
    "category": "Food",
    "barcode": "3017620422003",
    "co2e_kg": 2.14,
    "co2e_per_kg": 5.35,
    "co2e_per_kg_low": 4.80,
    "co2e_per_kg_high": 6.10,
    "uncertainty_pct": 24,
    "eco_grade": "D",
    "confidence": 0.82,
    "data_quality_rating": 5,
    "weight_kg": 0.400,
    "weight_source": "Open Food Facts",
    "source_breakdown": [
      {
        "source_id": "agribalyse",
        "source_name": "AGRIBALYSE (Hazelnut spread)",
        "co2e_per_kg": 5.35,
        "confidence": 0.95,
        "methodology": "OFF AGRIBALYSE live",
        "used_in_final": true
      }
    ],
    "lca_phases": {
      "agriculture": 3.12,
      "processing": 1.05,
      "packaging": 0.42,
      "transportation": 0.38,
      "distribution": 0.22,
      "consumption": 0.16
    },
    "methodology": "2 source(s) evaluated, agree",
    "archetype_id": "food.processed.spread.chocolate"
  }
}

Search the emission factor database. Supports product name text search and barcode lookup.

Query parameters

q (required) — Search text or barcode (8-13 digits)

region — Filter by region (e.g. "FR", "DE", "GLOBAL")

source — Filter by source (e.g. "ademe", "defra")

limit — Max results (default 10, max 50)

GET /v1/alternatives

Find lower-impact alternatives for a product category.

Query parameters

product_name — Product name to find alternatives for

category — Product category

limit — Max alternatives (default 5, max 20)

Error Responses

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded. Retry after reset."
  }
}

// Common error codes:
// 401 — auth_error (invalid or missing API key)
// 403 — tier_required (endpoint requires higher tier)
// 429 — rate_limited | quota_exceeded
// 400 — invalid_input
// 404 — not_found
// 500 — internal_error