Liksy Enterprise API

Real-time price intelligence,
sourced from the ground.

Query millions of verified price points, run aggregate statistics, detect anomalies, and chart trends — all from supermarkets, pharmacies, fuel stations, and markets across 150+ countries. Updated continuously by a global network of data collectors who earn a share of every query you make.

Request API key →

730K+

live data points

150+

countries covered

11

production endpoints

50%

revenue to collectors

Quickstart

Make your first API call in under a minute. Replace lk_live_YOUR_KEY with your actual API key, which we send after approval.

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/prices?country=HU&limit=5"

The response includes a meta object (pagination + quota info) and a data array (the prices themselves):

{
  "meta": {
    "total": 10265,
    "returned": 5,
    "limit": 5,
    "offset": 0,
    "tier": "starter",
    "tier_max_limit": 100,
    "cost_credits": 1,
    "queries_remaining": 9999,
    "response_ms": 142
  },
  "data": [
    {
      "id": 7633,
      "product_name": "MILK 1L",
      "product_brand": "Auchan",
      "category": "grocery",
      "subcategory": "dairy",
      "price": 349,
      "currency": "HUF",
      "price_usd": 0.96,
      "country": "HU",
      "city": "Budapest",
      "lat": 47.526462,
      "lng": 19.039627,
      "store_name": "Auchan Magyarország Kft.",
      "store_type": "supermarket",
      "store_chain": "Auchan",
      "confidence": 0.92,
      "source": "receipt",
      "captured_at": "2026-04-21T18:52:00+00:00"
    }
  ]
}

Authentication

All API requests require an API key passed via the Authorization header as a bearer token. Keys look like lk_live_... and are tied to a specific tier and quota.

Authorization: Bearer lk_live_efbe7495ed2d04df11b781b64f481920acf0783dcea9e75b

Key security

  • Keep your key secret. Never commit it to a public repo or expose it in client-side code.
  • Use environment variables. Store the key in your deployment's env vars, not in source.
  • Rotate if compromised. Revoke a leaked key immediately from your dashboard — contact us to revoke yours.
  • Revocation is permanent. A revoked key cannot be restored. You'll get a new one.

Endpoints

The API exposes four production endpoints. Each costs a different number of credits based on the computational work involved. Your monthly quota is denominated in credits, so a Starter plan with 10,000 credits gets you 10,000 /prices calls, or 5,000 /stats calls, or any mix.

EndpointCostTier requiredWhat it does
/api/v1/prices1 creditAllRaw price record query with filters
/api/v1/stats2 creditsStarter+Aggregate statistics (median, percentiles, trends)
/api/v1/timeseries3 creditsAll (capped)Time-bucketed series for charts
/api/v1/anomalies5 creditsGrowth+Detect significant price changes vs baseline
/api/v1/export1 / 1K rows creditsAll (capped)Bulk download — csv, ndjson, json (streamable)
/api/v1/inflation3 creditsAllLiksy Food Inflation Index — monthly, country-specific, baseline-normalized
/api/v1/risk/country5 + 1/compare creditsAllComposite 0-100 food-risk score with letter grade (AAA-D)
/api/v1/correlation4 + 1/matrix creditsAllPearson correlation between countries — pair or matrix mode
/api/v1/coverage1 creditAllData availability — global snapshot, country drill, or filtered query
/api/v1/supply-chain/stress6 creditsAllCross-country anomaly clusters with severity rating and per-country breakdown
/api/v1/webhooksfree creditsAllReal-time event delivery — register URL, receive HMAC-signed POSTs on anomaly + supply-chain stress events

✓ Outlier filtering is on by default

/stats, /anomalies, and /timeseries apply Tukey IQR filtering (1.5× interquartile range) to remove extreme values before aggregation. Each response includes outliers_excluded for transparency. Set include_outliers=true if you need raw aggregates (research, debugging, or custom downstream filtering).

GET/api/v1/pricesLIVE1 creditAll tiers

Query individual price records with rich filters. Supports pagination, sorting, and CSV export. Use this when you want raw data — for storage, custom analysis, or feeding your own pipeline.

Example: Hungarian dairy, last 30 days, sorted newest first

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/prices?country=HU&limit=5"

Sample response:

{
  "meta": {
    "total": 10265,
    "returned": 5,
    "limit": 5,
    "offset": 0,
    "tier": "starter",
    "tier_max_limit": 100,
    "cost_credits": 1,
    "queries_remaining": 9999,
    "response_ms": 142
  },
  "data": [
    {
      "id": 7633,
      "product_name": "MILK 1L",
      "product_brand": "Auchan",
      "category": "grocery",
      "subcategory": "dairy",
      "price": 349,
      "currency": "HUF",
      "price_usd": 0.96,
      "country": "HU",
      "city": "Budapest",
      "lat": 47.526462,
      "lng": 19.039627,
      "store_name": "Auchan Magyarország Kft.",
      "store_type": "supermarket",
      "store_chain": "Auchan",
      "confidence": 0.92,
      "source": "receipt",
      "captured_at": "2026-04-21T18:52:00+00:00"
    }
  ]
}

See for the complete filter list and for every field in a record.

GET/api/v1/statsLIVE2 creditsStarter+

Aggregate statistics over the price database — median, average, percentiles, standard deviation, and a 7-day trend signal. Returns a single object (or grouped breakdown when group_by is set). Cheaper than fetching all records and aggregating client-side.

Parameters

All /prices filters work here, plus:period (7d, 30d, 90d, all), group_by (none, country, city, store_chain, subcategory, category — Growth+ for non-none), include_outliers (default false; set to true for raw stats including extreme values).

Example

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/stats?period=30d"

Sample response — global aggregate over the last 30 days:

{
  "meta": {
    "credits_used": 2,
    "remaining": 9998,
    "period": "30d",
    "group_by": "none",
    "filters_applied": {},
    "response_ms": 988
  },
  "data": {
    "count": 8677,
    "avg_usd": 9.632,
    "min_usd": 0.05,
    "max_usd": 2150,
    "median_usd": 3.03,
    "p25_usd": 2.07,
    "p75_usd": 4.65,
    "stddev_usd": 103.4002,
    "latest_captured_at": "2026-04-21T18:52:00+00:00",
    "trend_7d_vs_prior_pct": -5.61,
    "countries": 14,
    "cities": 33,
    "store_chains": 10
  }
}

The trend_7d_vs_prior_pct field compares the median of the last 7 days against the prior 23 days. Useful as an early inflation signal.

GET/api/v1/anomaliesLIVE5 creditsGrowth+

Detect significant price changes by comparing a recent window against a baseline. Aggregates at the subcategory + country [+ city] level — surfaces regional inflation signals, supply disruptions, and competitive pricing shifts.

Parameters

recent_days (1-90, default 7), baseline_days (7-365, default 30, must be > recent_days), threshold_pct (1-100, default 10), direction (up, down, both), min_sample (default 5), group_by_city (default true), include_outliers (default false). Plus the standard filters: country, category, subcategory, city, store_chain.

Example

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/anomalies?threshold_pct=10&recent_days=7"

Sample response — a real US anomaly detected in our database:

{
  "meta": {
    "credits_used": 5,
    "remaining": 9999995,
    "recent_window": {
      "days": 7,
      "start": "2026-04-16T10:20:04Z",
      "end": "2026-04-23T10:20:04Z"
    },
    "baseline_window": {
      "days": 23,
      "start": "2026-03-24T10:20:04Z",
      "end": "2026-04-16T10:20:04Z"
    },
    "threshold_pct": 10,
    "direction": "both",
    "results_count": 1,
    "tier_max_results": 500,
    "response_ms": 1147
  },
  "data": [
    {
      "category": "grocery",
      "subcategory": "beverages",
      "country": "US",
      "city": "Town of Smithtown",
      "recent_median_usd": 7.37,
      "baseline_median_usd": 5.69,
      "recent_avg_usd": 7.37,
      "baseline_avg_usd": 5.69,
      "change_pct": 29.53,
      "direction": "up",
      "recent_samples": 40,
      "baseline_samples": 20,
      "first_detected": "2026-04-21T00:00:00Z",
      "last_observed": "2026-04-21T00:00:00Z"
    }
  ]
}

Results are sorted by absolute change_pct descending. The recent_samples and baseline_samples fields let you assess statistical significance.

GET/api/v1/timeseriesLIVE3 creditsAll (capped by tier)

Time-bucketed aggregates ready for direct charting. Each bucket contains median, average, percentiles, and sample count. Choose daily, weekly, or monthly granularity.

Tier caps: Starter 90 buckets · Growth 365 · Pro 730 · Enterprise 1,825. Requesting beyond your cap automatically trims the period — no error, just a cap_applied: true flag in the response.

Parameters

period_days (1-1825), granularity (daily/weekly/monthly), min_sample (default 1, exclude buckets with fewer samples), include_outliers (default false; per-bucket IQR filter applied). Plus the standard filters: country, category, subcategory, city, store_chain.

Example

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/timeseries?country=HU&subcategory=dairy&period_days=180&granularity=weekly"

Sample response — Hungarian dairy, weekly for 180 days:

{
  "meta": {
    "credits_used": 3,
    "remaining": 9999992,
    "granularity": "weekly",
    "period_days": 180,
    "period_start": "2025-10-25T10:38:23Z",
    "period_end": "2026-04-23T10:38:23Z",
    "filters_applied": {
      "subcategory": "dairy",
      "country": "HU"
    },
    "min_sample": 1,
    "buckets_returned": 2,
    "tier_max_buckets": 1825,
    "response_ms": 790
  },
  "data": [
    {
      "bucket_start": "2026-04-13T00:00:00Z",
      "samples": 12,
      "median_usd": 2.63,
      "avg_usd": 2.2825,
      "min_usd": 1.16,
      "max_usd": 3.48,
      "p25_usd": 1.425,
      "p75_usd": 2.9875,
      "stddev_usd": 0.8719
    },
    {
      "bucket_start": "2026-04-20T00:00:00Z",
      "samples": 17,
      "median_usd": 2.66,
      "avg_usd": 2.6141,
      "min_usd": 1.27,
      "max_usd": 4.93,
      "p25_usd": 1.38,
      "p75_usd": 3.42,
      "stddev_usd": 1.2281
    }
  ]
}

Buckets without samples are omitted (not zero-filled). Use min_sample=N to require minimum statistical significance per bucket.

GET/api/v1/exportLIVE1 per 1K rows creditsAll (capped by tier)

Bulk download for analysis pipelines, hedge fund backtests, and academic research. Supports csv, ndjson (newline-delimited JSON, streamable), and json. Streams chunked — millions of rows without buffering memory.

Tier limits (max rows per call): Starter 10K · Growth 100K · Pro 1M · Enterprise 5M. JSON format capped at 100K rows; use ndjson or csv for larger exports.

Parameters

format (csv/ndjson/json), country, city, category, subcategory, data_source (collector/wfp/scrape/openfoodfacts), since, until, min_price_usd, max_price_usd, limit.

Example

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/export?country=KE&format=csv&since=2025-01-01" \
  > kenya_2025.csv

Cost: 1 credit per 1,000 rows returned (rounded up, minimum 1). A 75K-row export = 75 credits.

GET/api/v1/inflationLIVE3 creditsAll

Liksy Food Inflation Index — a monthly, country-specific basket cost normalized to a January 2020 baseline of 100. Methodology mirrors the WFP Minimum Food Basket framework with country-specific weight overrides, IQR outlier filtering, and unit normalization. Read the full methodology at liksy.app/methodology.

Coverage: 12 countries with WFP institutional data — KE, NG, ET, EG, YE, SY, LB, UA, JO, IQ, GH, TR. Each returns up to 130+ monthly index points. New countries added as ingestion expands.

Parameters

country (required, ISO2), months (history depth, default 24, max 360).

Example

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/inflation?country=KE&months=24"

Sample response — Kenya, 24 months:

{
  "meta": {
    "country": "KE",
    "as_of": "2026-03-01",
    "tier": "starter",
    "cost_credits": 3,
    "response_ms": 943
  },
  "latest": {
    "index_value": 131.72,
    "basket_cost_usd": 1.773,
    "yoy_pct": 0.62,
    "mom_pct": 7.86
  },
  "methodology": {
    "basket_name": "standard",
    "baseline_date": "2020-01-01",
    "baseline_value": 100,
    "docs": "https://liksy.app/methodology"
  },
  "basket_components": {
    "effective_weight": 0.5,
    "subcategories_used": 2,
    "breakdown": [
      { "subcategory": "grains", "weight": 0.4, "current_median_usd_per_unit": 0.75, "yoy_pct": 0 },
      { "subcategory": "meat", "weight": 0.1, "current_median_usd_per_unit": 5.865, "yoy_pct": 8.21 }
    ]
  },
  "history": [
    { "month": "2024-04-01", "index": 123.36 },
    { "month": "2026-03-01", "index": 131.72 }
  ]
}

Index returns null when basket coverage falls below 40% (insufficient subcategory data). Always check basket_components.effective_weight for the subcategory share actually measured.

GET/api/v1/risk/countryLIVE5 + 1 per compare creditsAll

Composite 0–100 food-risk score with S&P-style letter grade (AAA→D). Designed for trade credit insurance, sovereign macro analysis, and EM hedge fund overlays. Combines inflation volatility (40%), absolute inflation (30%), anomaly density (20%), and data freshness (10%) over a 24-month rolling window.

Use compare to benchmark: add up to 9 additional countries with compare=NG,ET,YE. Returns the same risk breakdown for every country in a single call. 1 extra credit per compared country.

Parameters

country (required, ISO2), compare (comma-separated ISO2 list, max 9).

Example

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/risk/country?country=KE&compare=NG,ET,YE,LB"

Sample response — Kenya benchmarked against 4 EM/crisis countries:

{
  "meta": {
    "country": "KE",
    "tier": "starter",
    "cost_credits": 9,
    "response_ms": 2858
  },
  "primary": {
    "country": "KE",
    "risk_score": 30.66,
    "letter_grade": "BBB",
    "components": {
      "volatility": { "risk_score_0_100": 27.4, "weight": 0.4 },
      "absolute_inflation": { "risk_score_0_100": 52.57, "weight": 0.3 },
      "anomaly_density": { "risk_score_0_100": 12, "weight": 0.2 },
      "data_freshness": { "risk_score_0_100": 15.33, "weight": 0.1 }
    },
    "data_quality": {
      "inflation_months_used": 11,
      "avg_index": 126.29,
      "stddev_index": 6.92,
      "latest_data_date": "2026-03-01"
    }
  },
  "methodology": {
    "formula": "0.40*volatility + 0.30*inflation + 0.20*anomalies + 0.10*freshness",
    "grades": { "AAA": "<10", "AA": "10-19", "A": "20-29", "BBB": "30-44", "BB": "45-59", "B": "60-74", "CCC": "75-89", "D": ">=90" },
    "docs": "https://liksy.app/methodology"
  },
  "comparison": [
    { "country": "NG", "risk_score": 38.01, "letter_grade": "BBB" },
    { "country": "ET", "risk_score": 14.67, "letter_grade": "AA" },
    { "country": "YE", "risk_score": 70.51, "letter_grade": "B" },
    { "country": "LB", "risk_score": 43.51, "letter_grade": "BBB" }
  ]
}

Countries with insufficient data (<6 months in 24-month window) return letter_grade: "NR" (Not Rated). Full methodology at liksy.app/methodology.

GET/api/v1/correlationLIVE4 + 1/matrix country creditsAll

Pearson correlation coefficient between two countries' monthly median prices for a given subcategory. Reveals price passthrough (supply chain coupling), regional cohesion, and crisis dissociation. Two modes: pair (A ↔ B) and matrix (A vs many).

Real example: UA ↔ NG grains correlation = −0.81 over 24 months. When Ukraine grain exports tighten, Nigerian markets compensate through alternative sourcing — a negative correlation signals shock absorption, not transmission. Hedge fund alpha signal.

Parameters

Pair mode: country_a, country_b, subcategory, months (default 24, max 60).
Matrix mode: country, matrix (comma-separated ISO2 list, max 9), subcategory, months.

Example

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/correlation?country=UA&matrix=NG,EG,KE,YE,LB,JO,IQ,SY&subcategory=grains&months=24"

Sample response — Ukraine grains vs 8 EM countries, sorted by coupling strength:

{
  "meta": {
    "mode": "matrix",
    "anchor_country": "UA",
    "cost_credits": 12,
    "response_ms": 4850
  },
  "correlations": [
    {
      "country_a": "UA",
      "country_b": "NG",
      "subcategory": "grains",
      "pearson_r": -0.8069,
      "overlapping_months": 24,
      "interpretation": {
        "label": "very strong negative",
        "variance_explained_pct": 65,
        "note": "tight coupling — consider as single exposure"
      }
    },
    {
      "country_a": "UA",
      "country_b": "IQ",
      "pearson_r": -0.4696,
      "overlapping_months": 23,
      "interpretation": { "label": "moderate negative", "variance_explained_pct": 22 }
    }
  ],
  "methodology": {
    "method": "Pearson correlation coefficient",
    "aggregation": "monthly median USD price per unit (kg/L), IQR-trimmed",
    "sort_order": "absolute correlation strength, descending"
  }
}

Each month requires at least 3 IQR-trimmed samples per country to be included in the correlation. Minimum 6 overlapping months required for meaningful interpretation — fewer returns insufficient_data.

GET/api/v1/coverageLIVE1 creditAll

Instant answer to "what data do you have?" — designed for pre-sales demos, self-service prospect evaluation, and internal monitoring. Three modes:

  • Global (no params): platform snapshot — total records, top countries, category breakdown, 30/7-day momentum.
  • Country drill (?country=XX): subcategory + city + data_source breakdown with freshness status.
  • Filtered (any combination): record count + status + sample rows for your exact query.

Coverage status labels: strong (5K+ records, active), partial (100-5K), sparse (<100), stale (no updates in 90 days), no_coverage (none). Honest signaling — we flag gaps explicitly.

Parameters

All optional: country, city, category, subcategory, product. No params = global snapshot (served from hourly cache, <200ms).

Example

# Global snapshot — no auth burden, 1 credit, cache served
curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/coverage"

# Country drill-down
curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/coverage?country=TR"

# Filtered query — "do you have grains in Nigeria?"
curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/coverage?country=NG&subcategory=grains"

Sample response — Türkiye country drill (stale status demonstration):

{
  "meta": {
    "mode": "country",
    "tier": "starter",
    "cost_credits": 1,
    "response_ms": 1240
  },
  "coverage": {
    "country": "TR",
    "status": "stale",
    "total_records": 11392,
    "total_cities": 4,
    "earliest_capture": "2013-05-15T00:00:00Z",
    "latest_capture": "2022-03-15T00:00:00Z",
    "median_age_days": "2535.9",
    "records_last_30d": 0
  },
  "by_subcategory": [
    { "subcategory": "vegetables", "records": 3092, "median_usd": 0.80 },
    { "subcategory": "condiments", "records": 1840, "median_usd": 5.70 },
    { "subcategory": "grains", "records": 1561, "median_usd": 0.88 }
  ],
  "by_city": [
    { "city": "Istanbul", "records": 2566, "latest_capture": "2022-03-15T00:00:00Z" },
    { "city": "Ankara", "records": 2599 },
    { "city": "Izmir", "records": 2590 }
  ],
  "status_legend": {
    "strong": "5,000+ records, actively updated",
    "stale": "no updates in last 90 days",
    "no_coverage": "no data for this country"
  }
}

Cheapest endpoint at 1 credit — designed to be queried freely during evaluation. Global mode served from hourly materialized cache for <200ms latency.

GET/api/v1/supply-chain/stressLIVE6 creditsAll

Supply Chain Stress Index. Detects when the same subcategory shows statistically significant price moves across multiple countries simultaneously — a leading indicator of upstream supply shocks, trade disruption, or regional commodity stress.

Real example: Current run detects oils surge in JO +16.7%, LB +13.0%, KE -13.5% — Middle East / East Africa price decoupling signal. Hedge fund pair trade setup, Lloyd's cargo risk repricing trigger.

Methodology

For every country × subcategory pair we compute the z-score of the recent median vs a preceding baseline distribution. When |z| exceeds the threshold in N+ countries simultaneously, the subcategory is flagged as a cluster and ranked by severity (avg |z| × countries affected).

Parameters

All optional: recent_days (14-365, default 90), baseline_days (60-1825, default 540), min_z (0.5-5.0, default 1.0), min_countries (2-10, default 2). Defaults tuned for WFP monthly-cadence data.

Example

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \ "https://liksy.app/api/v1/supply-chain/stress"

Severity scale: critical (avg |z| ≥ 3.0 AND ≥ 5 countries), high, elevated, moderate. Each cluster includes per-country z-scores and automated interpretation narrative.

/api/v1/index2 CREDITSNEW

External authoritative index series — currently FAO Consumer Price Indices (food + general CPI) for 151 countries, January 2000 to present. Liksy serves upstream values verbatim under CC-BY-4.0. Use this to cross-check Liksy-computed inflation against official reference data, or as a standalone time-series feed for research dashboards.

Parameters

ParamTypeDescription
countrystringISO2, required (e.g. TR, HU, KE)
seriesstringOptional: food_cpi or general_cpi. Returns both if omitted.
sourcestringOptional data_source filter. Currently faostat_cp; more sources coming.
fromdateYYYY-MM-DD, default 36 months ago
todateYYYY-MM-DD, default today
limitintegerMax points returned, default 360, max 1000
list_seriesbooleantrue → returns the catalog of available series for the country (no time-series payload)

Example — Turkey food CPI, last 36 months

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/index?country=TR&series=food_cpi"

Example response (truncated)

{
  "meta": {
    "tier": "starter",
    "cost_credits": 2,
    "total_points": 29,
    "series_returned": 1,
    "response_ms": 142
  },
  "country": "TR",
  "time_window": { "from": "2023-04-24", "to": "2026-04-24" },
  "series": [{
    "data_source": "faostat_cp",
    "series_code": "food_cpi",
    "series_label": "FAO Food Consumer Price Index",
    "unit": "index",
    "base_period": "2015=100",
    "cadence": "monthly",
    "points": [
      { "period": "2023-05", "value": 660.90, "flag": "X", "confidence": 0.95 },
      { "period": "2024-09", "value": 1181.23, "flag": "X", "confidence": 0.95 },
      { "period": "2025-09", "value": 1607.19, "flag": "X", "confidence": 0.95 }
    ],
    "latest": { "period": "2025-09", "value": 1607.19 },
    "yoy_pct": 36.06
  }],
  "methodology": {
    "note": "External authoritative index series — Liksy serves upstream values verbatim, no recomputation.",
    "sources": {
      "faostat_cp": "FAO Consumer Price Indices, monthly, 2015=100. License CC-BY-4.0."
    },
    "docs": "https://liksy.app/methodology"
  }
}

Discover what's available for a country

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/index?country=KE&list_series=true"

Use cases

  • Validate Liksy-computed inflation against FAO official series for the same country
  • Standalone time-series feed for academic, policy, or central-bank research dashboards
  • Multi-country food vs general CPI comparison for emerging-market macro strategy
  • Pair with /inflation (Liksy basket) for ground-truth benchmarking


/api/v1/webhooksFREE MGMTNEW

Real-time event delivery via HMAC-signed POST callbacks. Register a URL once, then receive push notifications when Liksy detects price anomalies or supply-chain stress clusters that match your filters — no polling, no missed events, no stale data.

Why webhooks instead of polling /anomalies every minute? You don't pay credits for empty polls, you receive events within a minute of detection (vs your polling interval), and Liksy's HMAC-SHA256 signature proves the payload originated from us so you can trust it.

How it works

Liksy runs a trigger every 15 minutes that recomputes anomalies and stress clusters across the database. Matching events are queued for each webhook subscription whose filters apply. A separate delivery worker drains the queue every minute, signing each payload with your webhook's secret and POSTing to your URL. Failed deliveries retry with exponential backoff (1m, 5m, 30m); after 3 failures the delivery is marked dead and the event is visible in your audit log.

Register a webhook

curl -X POST "https://liksy.app/api/v1/webhooks" \
  -H "Authorization: Bearer lk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Trading desk anomaly feed",
    "url": "https://your-server.example.com/liksy-webhook",
    "event_types": ["anomaly_detected", "supply_chain_stress"],
    "filter_country": "TR",
    "filter_subcategory": "dairy",
    "min_severity": "elevated"
  }'

The response contains a one-time secret (32-byte hex) — store it securely. You'll need it to verify signatures on incoming deliveries. Liksy never returns this secret again.

Sample response

{
  "id": "9f319edd-53d8-4004-bde5-2587cf00c89d",
  "name": "Trading desk anomaly feed",
  "url": "https://your-server.example.com/liksy-webhook",
  "secret": "3d3ceeda599a04961ed5fcd37d9378907ad79c75f9b157f053b564b8edf9144f",
  "secret_warning": "This secret is shown ONCE. Store it now — it cannot be retrieved later.",
  "event_types": ["anomaly_detected", "supply_chain_stress"],
  "filter_country": "TR",
  "filter_subcategory": "dairy",
  "min_severity": "elevated",
  "created_at": "2026-04-25T14:35:42.496Z"
}

List your webhooks

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/webhooks"

Returns all your subscriptions with delivery counters (total_deliveries, total_failures, last_triggered_at) but never the secret. Revoked subscriptions remain visible with is_active: false for audit.

Revoke a webhook

curl -X DELETE "https://liksy.app/api/v1/webhooks/{id}" \
  -H "Authorization: Bearer lk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "rotated to new endpoint" }'

Soft delete — the subscription is marked inactive immediately, no new events are queued, but pending deliveries already in the queue will still be sent before the worker picks up the revocation. Idempotent: revoking an already-revoked webhook returns 200.

Filtering

FieldTypeDescription
event_typesarrayArray of "anomaly_detected", "supply_chain_stress", or both. Default: both.
filter_countrystring?ISO2 (e.g. "TR"). For stress events, matches if any country in the cluster matches. null = all countries.
filter_subcategorystring?e.g. "dairy", "grains". null = all subcategories.
min_severityenumOne of moderate, elevated, high, critical. Default: elevated.

Incoming delivery — request headers

Every delivery POST to your URL includes these headers:

HeaderDescription
X-Liksy-Signaturesha256=<hex> — HMAC-SHA256 of the raw request body, using your webhook secret. Always verify before processing.
X-Liksy-Eventanomaly_detected or supply_chain_stress
X-Liksy-Delivery-IdUnique UUID per delivery attempt. Use as your idempotency key — we may retry on transient failures.
X-Liksy-AttemptInteger, 1-3. Anything >1 means we're retrying.

Sample payload — anomaly_detected

{
  "event": "anomaly_detected",
  "severity": "high",
  "country": "TR",
  "category": "grocery",
  "subcategory": "dairy",
  "city": null,
  "change_pct": 31.8,
  "direction": "up",
  "recent_avg_usd": 1.45,
  "baseline_avg_usd": 1.10,
  "recent_median_usd": 1.42,
  "baseline_median_usd": 1.08,
  "recent_samples": 87,
  "baseline_samples": 412,
  "first_detected": "2026-04-22T08:14:00Z",
  "last_observed": "2026-04-25T11:58:54Z",
  "detected_at": "2026-04-25T14:48:00Z"
}

Sample payload — supply_chain_stress

{
  "event": "supply_chain_stress",
  "severity": "elevated",
  "subcategory": "oils",
  "countries_affected": 3,
  "country_list": ["JO", "LB", "KE"],
  "avg_price_move_pct": 14.4,
  "avg_z_score": 1.85,
  "max_z_score": 2.31,
  "direction": "up",
  "severity_score": 5.55,
  "detected_at": "2026-04-25T14:48:00Z"
}

Verifying the signature — Node.js

import crypto from "node:crypto";
import express from "express";

const app = express();

// IMPORTANT: capture the raw body BEFORE JSON parsing.
// HMAC verification depends on the exact byte sequence.
app.post("/liksy-webhook",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const signature = req.header("X-Liksy-Signature") || "";
    const expected = "sha256=" + crypto
      .createHmac("sha256", process.env.LIKSY_WEBHOOK_SECRET)
      .update(req.body)
      .digest("hex");

    // Constant-time compare avoids timing attacks
    const ok = signature.length === expected.length &&
      crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));

    if (!ok) return res.status(401).send("invalid signature");

    const event = JSON.parse(req.body.toString());
    const deliveryId = req.header("X-Liksy-Delivery-Id");

    // Idempotency: skip if you've seen this delivery_id before

    console.log("Liksy event:", event.event, event.severity);
    res.status(200).send("ok");
  }
);

Verifying the signature — Python (Flask)

import hmac, hashlib, os
from flask import Flask, request, abort

app = Flask(__name__)
SECRET = os.environ["LIKSY_WEBHOOK_SECRET"].encode()

@app.post("/liksy-webhook")
def liksy_webhook():
    raw_body = request.get_data()  # exact bytes, BEFORE Flask parses JSON
    signature = request.headers.get("X-Liksy-Signature", "")
    expected = "sha256=" + hmac.new(SECRET, raw_body, hashlib.sha256).hexdigest()

    if not hmac.compare_digest(signature, expected):
        abort(401, "invalid signature")

    event = request.get_json()
    delivery_id = request.headers.get("X-Liksy-Delivery-Id")

    print(f"Liksy event: {event['event']} {event['severity']}")
    return ("ok", 200)

Retry policy

Liksy considers a delivery successful only on a 2xx response within 8 seconds. Any other status (including 5xx, redirects, timeouts) triggers a retry. Backoff schedule is +1 min, then +5 min, then +30 min. After 3 failed attempts the delivery is marked dead and surfaced in your operator console. For idempotency, dedupe on X-Liksy-Delivery-Id — the same delivery may arrive twice if your server times out after processing but before responding.

Idempotency & deduplication

The same anomaly cluster (e.g. "TR dairy high") can recur across multiple 15-minute trigger runs while the underlying condition persists. Liksy fingerprints each event by (country, subcategory, severity, direction, day) and de-duplicates within a 24-hour window — you receive at most one notification per webhook per event-day. The fingerprint key is internal; you should still dedupe on X-Liksy-Delivery-Id for retry safety.

Webhook management endpoints (POST/GET/DELETE) do not consume credits and do not count against your monthly quota. Event deliveries are also free — you only pay for queries you issue against the data API.

Query Parameters

The table below covers /prices. Most filters (category, country, city, store_chain, etc.) also work on /stats, /anomalies, and /timeseries. Endpoint-specific parameters are documented in each endpoint's section above.

ParameterTypeDescription
categorystringFilter by category: grocery, electronics, fuel, pharma, clothing, restaurant, hardware, services, commodity, realestate
subcategorystringFilter by subcategory (e.g., dairy, bakery, phones, gasoline)
countrystringISO 3166-1 alpha-2 code (HU, TR, US, GB, DE, etc.)
citystringCity name (case-insensitive, partial match)
productstringProduct name search (case-insensitive, partial match)
store_typestringsupermarket, convenience, market, pharmacy, gas_station, restaurant, online
store_chainstringSpecific chain (Tesco, Migros, Auchan, Walmart, etc.)
barcodestringEAN/UPC barcode exact match
date_fromISO dateEarliest captured date (YYYY-MM-DD)
date_toISO dateLatest captured date (YYYY-MM-DD)
min_pricenumberMinimum price in USD
max_pricenumberMaximum price in USD
min_confidencenumberMinimum OCR confidence (0–1). Default: 0.75
verifiedbooleanReturn only human-verified records
limitintegerMax results per request (capped by tier). Default: 100
offsetintegerPagination offset. Default: 0
sortenumprice_asc, price_desc, date_asc, date_desc. Default: date_desc
formatenumjson (default) or csv for direct spreadsheet export

Example: Hungarian dairy prices, last 30 days

curl -H "Authorization: Bearer lk_live_YOUR_KEY" \
  "https://liksy.app/api/v1/prices?country=HU&subcategory=dairy&date_from=2026-03-22&sort=date_desc&limit=50"

Response Schema

Each price record in the data array of /prices has the following shape. Fields marked with ? may be null. Other endpoints return aggregated shapes — see their sections above.

FieldTypeDescription
idbigintUnique record identifier
product_namestringProduct name as captured
product_brandstring?Brand name if detected
product_sizestring?Size/volume (e.g., 500g, 1L)
barcodestring?EAN/UPC barcode if captured
categorystringTop-level category
subcategorystring?More specific category
pricenumberPrice in local currency
currencystringISO 4217 currency code
price_usdnumberPrice normalized to USD (daily FX rate)
countrystringISO 3166-1 alpha-2 country code
citystringCity name
districtstring?District/neighborhood within city
latnumberLatitude of capture point
lngnumberLongitude of capture point
store_namestringStore name as captured
store_typestringStore type classification
store_chainstring?Chain name if part of a chain
confidencenumberOCR/extraction confidence (0–1)
sourcestringscan, receipt, supplier, external
captured_atISO datetimeWhen the price was captured in-store

Meta fields

The meta object on every response helps you manage pagination and monitor quota usage:

FieldTypeDescription
totalintegerTotal records matching the query (across all pages, /prices only)
returnedintegerNumber of records in this response
limitintegerThe limit used for this request (clamped to tier max)
offsetintegerThe offset used for this request
tierstringYour API tier (starter, growth, pro, enterprise, research)
credits_usedintegerCredits this request consumed (1-5 depending on endpoint)
remainingintegerRemaining credits this billing period
response_msintegerServer-side response time in milliseconds

Rate Limits & Pricing

Each tier has a monthly credit quota, per-minute rate limit, and result caps. Endpoints consume different amounts of credits: /prices = 1, /stats = 2, /timeseries = 3, /anomalies = 5. Exceeding your quota returns 429 insufficient_credits; exceeding the rate limit returns 429 Too Many Requests.

Research

Free

for academic use

5,000 credits / month

60 / min

100 records / 100 anomalies

  • Academic research only
  • Attribution required
  • All 7 endpoints
  • Manual approval

Starter

$99

per month

10,000 credits / month

60 / min

100 records, 90 buckets

  • /prices, /stats, /timeseries, /export
  • /inflation index + /risk score
  • JSON + CSV + NDJSON export
  • Email support
  • 99.5% uptime SLA

Growth

$499

per month

100,000 credits / month

300 / min

500 records / 365 buckets

  • All 7 endpoints incl. /anomalies + /risk
  • Priority email support
  • 99.9% uptime SLA
  • Daily usage reports
Most popular

Pro

$999

per month

1,000,000 credits / month

1,200 / min

5,000 records / 730 buckets

  • Everything in Growth
  • Dedicated Slack channel
  • Custom subcategory filters
  • Anomaly webhooks (beta)

Enterprise

Custom

volume pricing

Unlimited credits

6,000 / min

50,000 records / 1,825 buckets

  • Everything in Pro
  • Dedicated infrastructure
  • 5-year history access
  • Revenue-share partnerships
  • On-premise deployment

Error Codes

Errors use standard HTTP status codes. The response body includes a structured error object with code and message fields. Some errors include extra context (e.g., upgrade_to, credits_remaining).

{
  "error": {
    "code": "tier_required",
    "message": "Anomaly detection requires Growth tier or higher. This is a premium feature for inflation tracking, supply chain alerts, and competitive intelligence."
  },
  "current_tier": "starter",
  "upgrade_to": "growth",
  "contact": "emir@delmundo.hu"
}
StatusNameWhen it happens
200OKRequest successful, data returned.
400Bad RequestInvalid query parameter. Check country code format, date format, or numeric fields.
401UnauthorizedAPI key missing or invalid. Include it as 'Authorization: Bearer lk_live_...'
403ForbiddenTier required (e.g., /anomalies needs Growth+) or key revoked. Check the upgrade_to field in the response.
429Too Many RequestsRate limit hit, or insufficient credits for the endpoint cost. Slow down or upgrade.
500Server ErrorSomething went wrong on our side. We've been notified. Retry with exponential backoff.

Handling rate limits and quota

When rate-limited (429), use exponential backoff in production clients. When credits are insufficient, the response includes credits_required and credits_remaining so you can decide whether to retry, switch to a cheaper endpoint, or upgrade.

Ready to get started?

Tell us briefly what you're building. We'll reply within a day with your API key, the right tier for your use case, and pricing.

Request API access →

Or email us directly: emir@delmundo.hu

Privacy · Terms · © 2026 Del Mundo Kft. · Budapest