gridscoot
rest api

REST endpoint reference

Non-MCP integrations call /api/v1. Same data the MCP tools return, exposed as conventional JSON over HTTPS.

Overview

The MCP server is the primary surface for AI agents (Claude, Cline, OpenWebUI, Ollama). For everything else — server-side scripts, browser extensions, other comparison bots, plain curl from a terminal — the same data is exposed at /api/v1 as conventional REST.

Endpoints mirror the MCP tool surface 1:1 so you can prototype with one and migrate to the other without re-modelling. The free tier (no key) is rate-limited but functional for evaluation.

Authentication

Two auth modes:

  • Anonymous (free tier) — no header required. Hit /api/v1/search?q=...&demo=1 directly. 60 req/min per IP. track_price not available.
  • Bearer key (paid tiers)Authorization: Bearer gs_live_.... Issued from /account/keys. Per-key rate limits per /pricing.
curl
# Free tier
curl 'https://gridscoot.vercel.app/api/v1/search?q=sony+wh-1000xm5&demo=1'

# Authenticated
curl 'https://gridscoot.vercel.app/api/v1/search?q=sony+wh-1000xm5' \
  -H 'Authorization: Bearer gs_live_REDACTED'

Rate limits

Limits are enforced per IP (free tier) or per key (paid tier). When you hit the limit, the response is HTTP 429 with Retry-After header in seconds.

  • Free / demo: 60 requests / minute / IP
  • Solo (paid): 600 requests / minute / key
  • Pro (paid): 6,000 requests / minute / key + webhook delivery

Discovery

Two endpoints help you find the rest:

  • GET /api/v1 — returns the full endpoint catalogue as JSON (machine-readable)
  • GET /.well-known/mcp.json — MCP-spec discovery manifest (for agents)
curl
curl https://gridscoot.vercel.app/api/v1 | jq

Endpoints

GET /api/v1/search

Search the catalogue. Query params:

  • q (required) — free-text query (URL-encoded)
  • max_price_aud, min_price_aud — price bounds
  • retailer_slug — restrict to one retailer
  • page_size — default 20, max 50
  • demo=1 — free-tier flag; required when no Bearer key
curl
curl 'https://gridscoot.vercel.app/api/v1/search?q=sony+wh-1000xm5&demo=1' | jq

Response shape matches search_products MCP tool output. See /docs/mcp-tools.

GET /api/v1/products/[id]

Single canonical product + every in-stock offer. Mirrors compare_product.

curl
curl 'https://gridscoot.vercel.app/api/v1/products/1?demo=1' | jq

GET /api/v1/products/[id]/history

Price history with fake-discount flagging. Mirrors get_price_history. Query param window=30|90|365 (default 90).

GET /api/v1/retailers

Active retailer feeds + status. Mirrors list_retailers. No params; no auth required.

curl
curl https://gridscoot.vercel.app/api/v1/retailers | jq

POST /api/v1/alerts

Subscribe to a price drop. Mirrors track_price. Pro tier required.

curl
curl -X POST 'https://gridscoot.vercel.app/api/v1/alerts' \
  -H 'Authorization: Bearer gs_live_REDACTED' \
  -H 'Content-Type: application/json' \
  -d '{"product_id": "1", "target_price_aud": 399.00}'

POST /api/v1/find-alternatives

Equal-or-better alternatives to a baseline product. Mirrors find_alternatives. Bearer key required — no demo tier. Two input modes: inline (pass full baseline + candidates) and DB-lookup (pass just baselineProductId and let the server resolve candidates from the catalog). The DB-lookup response carries a catalogResolution object disclosing what fields were synthesised. See the full input/output shape on /docs/mcp-tools.

curl · db-lookup mode
# DB-lookup mode: server resolves baseline + candidates from catalog
curl -X POST 'https://gridscoot.vercel.app/api/v1/find-alternatives' \
  -H 'Authorization: Bearer gs_live_REDACTED' \
  -H 'Content-Type: application/json' \
  -d '{"baselineProductId": 1, "buyerCountry": "HU"}'
curl · inline mode
# Inline mode: caller supplies the full baseline + candidates payload
curl -X POST 'https://gridscoot.vercel.app/api/v1/find-alternatives' \
  -H 'Authorization: Bearer gs_live_REDACTED' \
  -H 'Content-Type: application/json' \
  -d @baseline-plus-candidates.json

GET /api/health

Public health endpoint (no auth). Returns 200 when the catalogue is queryable.

Errors

Errors follow the standard HTTP-status + JSON-body convention:

error
{
  "error": {
    "code": "validation_error",
    "message": "max_price_aud must be a positive number",
    "field": "max_price_aud"
  }
}

Status codes you’ll see

  • 400 — bad input (your problem; fix the params)
  • 401 / 403 — auth (missing or invalid Bearer key, or Pro-tier route called with non-Pro key)
  • 404 — product / retailer not found, or DB-lookup baseline doesn’t exist (baseline_not_found)
  • 429 — rate limit; Retry-After header in seconds
  • 500 / 503 — transient; retry with exponential backoff (250ms → 500ms → 1s)