In one sentence
Personal use of the Trust Index (extension + website) is free; organisations pay for Spaces; developers and companies pay for API and embedding.
Endpoints
Base URL: your GriGsi server (e.g. https://your-domain.com). No auth required for read and vote; optional X-Api-Key for higher limits.
| Method | Path | Description |
|---|---|---|
| GET | /trust?hash=<hash> | Trust for one hash. Add ?details=1 for tierLabel, trustPercent, etc. |
| GET | /api/trust?hash=<hash> | Same as above. |
| GET / POST | /api/trust/batch | Trust for many hashes (max 50). GET: ?hashes=hash1,hash2; POST: JSON { "hashes": ["..."] }. Optional details=1. |
| POST | /vote-hash or /api/vote-hash | Submit vote: JSON { "hash", "vote": 1|−1, "clientId" }. |
Single trust response (200)
{
"hash": "a1b2c3...1",
"plus1": 120,
"minus1": 5,
"weighted_score": 112.5,
"tier": 2,
"totalVotes": 125
}
With ?details=1 you also get: tierLabel, trustPercent, uniqueVisits, countries, spanHours, flagged, flagReason.
Hash format: SHA-256("<type>:<normalized_value>") first 32 hex chars + one digit (1=domain, 2=email, 3=phone, 4=iban, 5=string, 6=info_index). Example: domain:example.com → hash ending in 1. Normalize: domain = lowercase, no www/path; email = lowercase; phone = digits only.
Trust Check API
Runtime endpoints used by the Trust Check UI (hash/check/vote + interest signals).
| Method | Path | Description |
|---|---|---|
| POST | /api/trust-hash-preview | Server hash preview for clients without crypto.subtle. |
| POST | /api/trust-check | Check trust for one hash/display label. |
| POST | /api/vote-hash | Submit trust vote: { "hash", "vote": 1|-1, "clientId" }. |
| POST | /api/passive-check | Record passive check event (no vote). |
| POST | /api/interest-survey/request | Create/update positive or negative interest request. |
| POST | /api/interest-survey/passive | Record passive interest event. |
| GET | /api/interest-survey/info?hash=...&clientId=... | Read current interest summary for a hash. |
Example: trust check
POST /api/trust-check
Content-Type: application/json
{ "hash": "6c57ebfc23cdad8e0ae18249defc8d285", "clientId": "opaque-id", "display": "example.com" }
→ { "hash": "...", "score": 0, "tier": 1, "trust": 0, "warn": 0 }
Source/claim workflows are UI-level features; this public runtime API focuses on trust hash checks and voting primitives.
Labour Coverage Index (LCI) API
Anonymous price observations and public index snapshots for the Labour Coverage Index. Same origin as your GriGsi server (e.g. dashboard for a web submit form). Canonical data-source definitions: GET /api/lci/registry/public (shared infrastructure for future Open Data Hub).
| Method | Path | Description |
|---|---|---|
| GET | /api/lci/meta | Methodology version, geohash precision, basket weights, categories, confidence bands, LCI semantic bands. |
| GET | /api/lci/global | Latest global snapshot (macro-only blend in v0.1) + lci_semantic. |
| GET | /api/lci/core?region_cell=<7-char geohash> | Latest snapshot for a region cell (includes crowd when enough signals exist). |
| GET | /api/lci/personal?region_cell=…&monthly_net_income=…&income_currency=…[&country_iso=…][&monthly_expense=…&expense_currency=…][&hours_per_month=…][¯o_year=…][¯o_month=…] | Personal monthly pressure check + Labour Coverage Index (public name; labour_cost_of_life: headline lci and CRV/LCR/HNC decomposition). Optional hours_per_month (80–280, default 173) scales net income to hourly wage for LCI. Optional macro_year (1990–2100) and macro_month (1–12) select Eurostat HICP (monthly) and HPI (quarterly) observations from the stored ingest tail for LCI; if a period is missing, the server falls back to latest (see labour_cost_of_life.meta). Optional expense; if omitted, server derives baseline from macro inputs. If no regional snapshot exists for region_cell, use country_iso for macro country; lci_core falls back to global snapshot. |
| GET | /api/lci/history?region_cell=…&limit=… | Time series of snapshots for __global__ or a geohash. |
| GET | /api/lci/registry/public | Public ingest registry (providers, parsers, enrichment metadata, placeholders) plus grv_subcomponent_catalog (5-driver map) and normalization_rule_params (parameter slots; not used in scoring v0). |
| POST | /api/lci/signals | Submit one crowd price signal (see contract below). Rate-limited per IP. |
| GET | /api/lci/cells | Recent signal counts by region_cell (transparency / debugging). |
Crowd signal contract (POST /api/lci/signals)
Content-Type: application/json. Prices are converted server-side to EUR for aggregation when FX rates are available.
| Field | Required | Description |
|---|---|---|
region_cell | yes | String, length = geohash_precision from /api/lci/meta (default 7). Lowercase base32 geohash. |
category | yes | One of the basket keys from /api/lci/meta categories (e.g. food_beverages, housing, …). |
price | yes | Positive number; local shelf/unit price in currency. |
currency | yes | ISO 4217, 3 letters (e.g. EUR, BGN). |
product_label | no* | Short human-readable label (recommended for transparency; max 200 chars). *Dashboard MVP treats it as required for quality. |
barcode | no | Optional EAN/UPC etc. (max 64 chars). |
country_iso | no | Optional ISO 3166-1 alpha-2 country code (e.g. BG, DE). Stored for future country-level macro mapping. |
monthly_net_income | no | Optional positive number (household context). Stored as EUR in income_eur_monthly when FX is available. Not blended into public LCI v0.1 lci_core — reserved for future personal/cohort stress metrics. |
income_currency | no | ISO 4217 for monthly_net_income; defaults to EUR if omitted. |
schema_version | no | Default 1. |
timestamp | no | Client ms epoch; stored as client_ts when valid. |
micro_cell, venue_hash, device_install_hash, quantity_unit, confidence_local | no | Optional diversity / provenance hints (hashes only; no PII). |
Example: submit signal
POST /api/lci/signals
Content-Type: application/json
{
"schema_version": 1,
"region_cell": "u05p88m",
"category": "food_beverages",
"product_label": "Milk 3.6% 1L store brand",
"price": 2.49,
"currency": "EUR",
"barcode": "5901234123457",
"country_iso": "BG",
"monthly_net_income": 1800,
"income_currency": "EUR",
"timestamp": 1700000000000
}
→ { "ok": true, "id": 42, "received_at": 1700000000123, "price_eur": 2.49, "income_eur_monthly": 1800 }
Omit monthly_net_income if you do not want to send income; the response then has no income_eur_monthly field.
Errors
- 400 — invalid JSON or validation (
{ "ok": false, "error": "…" }). - 422 — EUR conversion unavailable (FX not ingested yet or unsupported currency).
- 429 — rate limit (
rate_limited).
Pipeline
Signals persist in lci_signals. The scheduled LCI job runs ingest + aggregation (~6h by default). Regional lci_core / confidence use crowd data when density allows; global v0.1 snapshot remains a macro-only summary — check components_json / methodology notes on /api/lci/global.
Validation: from server/ run npm run test:lci (includes signal contract tests and an isolated end-to-end persist → aggregate → history check). Demo seed: npm run seed:lci:crowd (dry run); apply with GRIGSI_SEED_LCI_CONFIRM=1 node lci/seed-crowd-signals.cjs --apply.
Personal check contract (GET /api/lci/personal)
Computes a financial ease score (0–100, higher = more comfortable cushion after expenses) for a region_cell from your income and optional total expense. Regional lci_core slightly lowers ease when living costs are structurally high. When expense is omitted, the server uses an API-derived baseline from macro inputs. Optional country_iso (ISO 3166-1 alpha-2) selects World Bank macro series when there is no regional LCI snapshot yet for that geohash.
Monthly Breathing Room answers: “How much monthly flexibility do you have?”
Labour Coverage Index (labour_cost_of_life.lci, short LCI) — single headline derived from currency real value (CRV), labour conversion (LCR), and human necessity coverage (HNC); see docs/LCI-LABOUR-INDEX-PHASE1.md. GRV remains in the response for legacy clients.
Macro period (Phase 5): macro_year / macro_month align LCI Eurostat inputs with a calendar moment; re-run ingest so snapshots include an observations tail (HICP uses the last 96 periods by default). Breathing room and GRV still use the latest regional snapshot.
Labour Coverage Index — data gaps & overrides: labour_cost_of_life may include data_gaps (EN/BG messages) and user_value_hints when a HICP slice or HPI YoY is missing or the requested period is not in the stored series (server may fall back to latest). Optional query parameters let you supply official annual % YoY values: lci_override_CP00, lci_override_CP01, lci_override_CP03, lci_override_CP06, lci_override_CP07, lci_override_CP10, lci_override_CP041, lci_override_CP045, lci_override_hpi, lci_override_lending (World Bank–style domestic lending % for the transparency row). See docs/LCI-LABOUR-INDEX-PHASE1.md §9.
GriGsi Real Value Index (GRV) answers: “How strong is that flexibility in current real economic conditions?” It is part of an economic reality mapping engine for consumer purchasing power. Canonical driver IDs and labels: server/lci/grv-driver-ids.js (docs under docs/LCI-*.md are explanatory, not a second registry).
GET /api/lci/personal?region_cell=u05p88m&monthly_net_income=2500&income_currency=EUR&country_iso=BG
→ {
"ok": true,
"region_cell": "u05p88m",
"country_iso": "BG",
"lci_core": 67.8,
"monthly": {
"income_eur_monthly": 2500,
"expense_eur_monthly": 1398.24,
"expense_source": "api_baseline",
"residual_eur_monthly": 1101.76
},
"personal_financial_ease_score": 74.5,
"personal_financial_ease_label": "Manageable",
"personal_stress_score": 74.5,
"personal_stress_label": "Manageable"
}
personal_stress_* duplicates ease for backwards compatibility; prefer personal_financial_ease_*.
GRV contract: response includes grv (baseline 100) with score, label, interpretation, and a required drivers breakdown aligned with the five locked drivers (Cost of Living, Housing, Monetary, Utility & Energy, Tax & Policy Pressure — see grv_subcomponent_catalog). If market data is missing, market contribution is neutral (0). Drivers are directional estimates, not exact decomposed contributions.
Similarity API
The Similarity engine detects lookalike domains and emails (homograph/typosquat). It is used in the extension to warn when a visited domain or email is similar to one you already trust.
Current use: Logic runs in the extension (client-side). A list of your trusted domains/emails is compared locally with the current URL or email; similarity is computed on normalized labels (skeleton/NFKC) with thresholds (e.g. ≥90% almost identical, 80–89% suspicious).
API: A server-side Similarity API (e.g. GET /api/similarity/domains?domain=example.com or POST /api/similarity/check with a list of hashes) can be offered for embedding in your app — same rate limits as Trust API. Contact us for access or when it becomes available.
Rate limits
| Usage | Limit | Notes |
|---|---|---|
| Free (no key) | Low volume | Per IP and per clientId; avoid high-frequency polling. Cache results on your side. |
| Paid (API key) | Starter: ~5k/mo · Growth: ~50k/mo · Scale: custom | Header X-Api-Key: your-key. Higher limits and SLA. See Pricing. |
For production embedding or high traffic, use an API plan or call from your backend (server-to-server) to avoid browser CORS and rate limits.
Trust badge (embed)
Show your domain’s trust score on your site. Add a container and load the script (same origin as the GriGsi server, or use your backend to proxy the request).
1. HTML
<div id="grigsi-trust-badge" data-grigsi-domain="example.com"></div>
<script src="https://YOUR-GRIGSI-DOMAIN/js/trust-badge.js"></script>
Use data-grigsi-domain (e.g. example.com) or data-grigsi-base to point to another GriGsi server URL if needed.
2. Demo on this site
Free badge: links to GriGsi. Paid/white-label options: see Pricing.
CORS
For cross-origin requests from a browser (e.g. your site on another domain), the server may need to allow your origin. Alternatively, call the API from your backend and serve the result to your frontend — no CORS needed.