Skip to content
worldgovdata
Documentation / Core concepts

Core concepts

Credits

One number, spent only when rows of data come back. Browsing the catalogue, reading metadata and checking freshness are free — so working out what to buy never costs anything.

One credit is 100 observation rows. Credits are whole numbers, they do not expire, and there is no subscription.

What a credit is

A credit is a unit of data delivered, not a unit of time or of requests. The rule for the one variable endpoint is:

/v1/data

cost = max(1, ceil(rows_returned / 100))

Every other billable route is a flat 1. Everything else is 0. Three consequences worth holding on to:

  • You are billed for what arrived, not for what you asked for. A query matching 40 rows costs 1 credit whether you scoped it tightly or got lucky.
  • Errors are free. Credits are debited after a successful response exists and its row count is known. A 4xx or 5xx costs nothing — including too_many_rows, which is decided by a count before any data is read.
  • Every request rounds up separately. Two requests of 60 rows cost 2 credits; one request of 120 rows costs 2 as well. The rounding only starts to matter when you chunk aggressively — see the third worked example below.

New accounts receive 2,000 credits — about 200,000 rows — at email verification, not at signup. After that, credits come from a one-off pack; nothing renews and no card is stored. Prices are on the pricing page.

The full cost table

Credit cost of every public API route
RouteCreditsWhat it returns
GET /v1/countriesfreeThe country spine.
GET /v1/countries/{iso3}1One country with every latest value it has.
GET /v1/indicatorsfreeThe catalogue. Search, filter, sort, page.
GET /v1/indicators/{id}freeOne indicator plus its related set.
GET /v1/topicsfreeThe 13-topic taxonomy with counts.
GET /v1/meta/freshnessfreePer-provider licence, cadence, last successful load.
GET /v1/meta/coveragefreePer-country observation and indicator counts.
GET /v1/rankings/{indicator}1Every country ranked on one indicator, one year.
GET /v1/datamax(1, ceil(rows / 100))Raw observations, JSON or CSV. The only variable price.
GET /v1/usagefreeYour own balance and recent usage.
GET /v1/pingfreeKey liveness: key id, scopes, balance.

Three worked examples

A five-country time series

GDP per capita for India, China, the United States, Germany and Japan, 2000 to 2024.

GET /v1/data?indicator=wdi.gdp_per_capita_ppp&countries=IND,CHN,USA,DEU,JPN&from=2000&to=2024
  • 5 countries × 25 years = 125 rows
  • ceil(125 / 100) = 2
  • max(1, 2) = 2

Total2 credits

A world map for one year

The latest control-of-corruption ranking for every country, to colour a choropleth.

GET /v1/rankings/wgi.control_of_corruption
  • Rankings are a flat price: 1 credit
  • 213 rows returned — the row count does not enter into it
  • Finding the indicator id first, via /v1/indicators?q=corruption, is free

Total1 credit

A full panel, chunked

One indicator for all 218 countries over 60 years — about 13,000 rows, fetched 25 countries at a time.

GET /v1/data?indicator=…&countries=<25 codes> ×9
  • 218 countries ÷ 25 per chunk = 9 requests
  • ≈1,450 rows per chunk → ceil(1450 / 100) = 15 credits each
  • 9 × 15 = 135
  • One unchunked request would have been ceil(13000 / 100) = 130 — chunking costs a little more, because each chunk rounds up separately

Total135 credits (130 unchunked)

Estimating before you spend

You never have to guess. Two free moves tell you the size of a pull in advance.

Read the coverage block

Every indicator record carries coverage: how many countries hold it and the span of years. Multiply. /v1/indicators/{id} is free.

Upper bound

"coverage": { "n_countries": 213, "yr_min": 2000, "yr_max": 2024, "latest_year": 2024 }

213 countries × 25 years ≈ 5,325 rows  →  ceil(5325 / 100) = 54 credits

That is an upper bound, not a figure: coverage is rarely complete, so the real row count is usually lower and so is the real cost.

Probe with one country

One credit buys you an exact answer. Pull a single country, read meta.count, and scale.

One-credit probe

# How many rows before you spend anything: ask for one country, read meta.count.
curl -sS "https://api.worldgovdata.com/v1/data?indicator=wdi.gdp_per_capita_ppp&countries=IND" \
  -H "Authorization: Bearer $WGD_API_KEY" | jq '.meta.count'

Reading the credit headers

Every metered response tells you what it cost and what is left. There is no reason to poll a balance endpoint on a schedule — the answer is already attached to the work you are doing.

Credit headers on every metered response
HeaderExampleMeaning
X-Credits-Charged3Credits this request cost. Always sent on a metered call, including when it is 0.
X-Credits-Remaining24997Your balance after the charge. Watch this instead of polling /v1/usage.

Response headers · 200

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: private, no-store
X-Request-Id: 0f3a91c4e2b7
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 594
X-RateLimit-Reset: 1785315600
X-Credits-Charged: 2
X-Credits-Remaining: 24998
  • Both headers are absent on a request that was never metered — an anonymous call to a free route, for instance.
  • X-Credits-Charged: 0 on a 4xx or 5xx is a promise, not a rounding: failed requests genuinely cost nothing.
  • Log X-Credits-Remaining from your batch jobs and alert on it falling below a day of headroom. It is the cheapest budget monitor available and it is free.

When you run out

We never serve on credit. If your balance is below what a request needs, it is refused before the query runs — so an over-budget request costs nothing and leaves nothing half-done.

Insufficient credits · 402

HTTP/1.1 402 Payment Required

{
  "error": {
    "code": "insufficient_credits",
    "message": "This request needs 1 credit and your balance is 0.",
    "required": 1,
    "balance": 0,
    "top_up_url": "https://worldgovdata.com/account/billing"
  }
}

The body is deliberately actionable. required is what this request needed, balance is what you hold, and top_up_url is where to fix it. A client that gets a bare 402 can only guess whether it is one credit short or a hundred thousand.

Handling it

  • Do not retry. A 402 is not transient; retrying is the one response guaranteed not to help. Stop the loop.
  • Record where you stopped. In a chunked pull, keep the index of the last chunk that succeeded. Credits are debited per request, so everything before the 402 was delivered and paid for — resume there rather than starting over.
  • Surface it as a budget event. This is not an outage and not a bug. Alert whoever owns the account, not whoever is on call.
  • Then retry the identical request. Once topped up, the same URL returns the same rows. Nothing about the request needs to change.

What credits are not

  • Not a licence. Credits buy delivery, not rights. An indicator whose licence forbids redistribution returns 403 display_only at any balance. See Licensing.
  • Not a rate limit. The two ceilings are independent: a full balance does not raise your requests-per-minute, and hitting a 429 does not cost you anything. See Rate limits.
  • Not perishable. Credits do not expire, do not reset monthly and are not use-it-or-lose-it.
  • Not charged to the portal. Browsing worldgovdata.com in a browser never touches your balance. Only calls you make with your own key do.