MacroLens / Guides

Compare countries' unemployment programmatically

Ranking countries on one indicator usually means one request per country, then aligning years by hand. A comparison endpoint does that in a single call.

The problem

Cross-country comparisons break on the details. Countries report for different latest years, some have gaps, and country names are inconsistent between sources. If your agent fetches each country separately it also pays latency and rate-limit costs ten times over, and it has to sort and rank the results itself.

How /compare answers it

GET /compare takes countries, either a comma-separated list of up to 10 ISO codes or a group name (G7, BRICS, NORDICS, EUROPE_BIG4), and an indicator such as unemployment, inflation, gdp_per_capita, gdp_growth or debt_to_gdp. For each country it takes the most recent available observation, sorts descending (or ascending with order=asc) and returns a ranking with rank, name, ISO codes, year and value. Countries without data are listed under noData instead of failing the whole call. Because each row carries its own year, you can see when two figures are not from the same period.

Request and response

Example: unemployment across the G7.

$ curl -i "https://macrolens.imac2014ville.workers.dev/compare?countries=G7&indicator=unemployment"
HTTP/2 402
payment-required: eyJ4NDAyVmVyc2lvbiI6Mi4uLn0=   # base64 JSON: scheme "exact", network eip155:8453,
                                                  # asset USDC, amount 10000 (= $0.01)
# An x402 client signs the payment, then retries with a PAYMENT-SIGNATURE header.

The paid response (abridged to three of the seven G7 rows):

{
  "ok": true,
  "indicator": { "key": "unemployment", "code": "SL.UEM.TOTL.ZS", "units": "%",
    "name": "Unemployment, total (% of total labor force) (modeled ILO estimate)" },
  "order": "descending",
  "note": "Each value is the most recent available observation for that country; compare the year field.",
  "ranking": [
    { "rank": 1, "country": "France", "iso2": "FR", "year": 2025, "value": 7.542 },
    { "rank": 2, "country": "Canada", "iso2": "CA", "year": 2025, "value": 6.907 },
    { "rank": 7, "country": "Japan", "iso2": "JP", "year": 2025, "value": 2.451 }
  ],
  "source": "World Bank Open Data (CC BY 4.0)"
}

JavaScript with @x402/fetch

import { wrapFetchWithPaymentFromConfig } from "@x402/fetch";
import { ExactEvmScheme } from "@x402/evm";
import { privateKeyToAccount } from "viem/accounts";

const signer = privateKeyToAccount(process.env.PRIVATE_KEY); // wallet holding USDC on Base
const pay = wrapFetchWithPaymentFromConfig(fetch, {
  schemes: [{ network: "eip155:8453", client: new ExactEvmScheme(signer) }],
});
const res = await pay("https://macrolens.imac2014ville.workers.dev/compare?countries=SE,NO,DK,FI&indicator=gdp_per_capita&order=desc");
const { ranking } = await res.json();
for (const r of ranking) console.log(r.rank, r.country, Math.round(r.value), r.year);

Pricing

/compare costs $0.01 per call, whatever the number of countries (up to 10). There is no API key and no account: each request is paid in USDC on Base over x402. Malformed input returns 400 and failed lookups return a non-2xx status, so those are not charged.

Limitations

More guides

Sister services