Wikirate
Developers·REST API·v1·Read-only

Wikirate REST API

The Wikirate API gives read-only access to published Wikirate data — companies, metrics, answers, datasets and benchmarks — over plain HTTPS and JSON. It is a standard REST API over HTTPS. Any HTTP client works, from cURL to Python requests or JavaScript fetch, and no SDK is needed.

01 · Overview

What you can get

Every request needs two credentials: the shared publishable key and your personal API token.

All endpoints are versioned in their name. When a breaking change is needed, a new versioned endpoint will be added and the previous endpoint will keep working for a deprecation period.

Core 5 endpoints
Companies, metrics, the organisations that design them, regions and answers.
v1_companiesv1_metricsv1_designersv1_regionsv1_answers
Datasets 4 endpoints
Curated collections of metrics, companies and answers from one organisation.
v1_datasetsv1_dataset_metricsv1_dataset_companiesv1_dataset_answers
Benchmarks 4 endpoints
Scored rankings of companies, published in yearly editions.
v1_benchmarksv1_benchmark_metricsv1_benchmark_companiesv1_benchmark_answers

02 · Getting access

Get your credentials

You need a free Wikirate account and two values from your account settings: the publishable key and a personal API token. The publishable key is the same for everyone and safe to share; the token identifies you and must stay secret. You can find both on your API access page.

Publishable key Safe to share
API access page, same for everyone.
Sent as the headerapikey
Personal API token Secret
Generated by you, starts with wr_.
Sent as the headerx-api-token

Issue a token

  1. 1
    Open API accessSign in at wikirate.org, open the account menu (your initials, top right) and choose API access.
  2. 2
    Copy the project connectionUnder 1. Project connection, copy the API URL (https://data.wikirate.org) and the Publishable key.
  3. 3
    Generate a personal tokenUnder 2. Your personal token, describe what the token is for (for example "Research notebook") and click Generate token.
  4. 4
    Copy it straight awayCopy the token straight away, or use Copy as .env / Download .env file to get all three values in one file. The token is shown only once; if you lose it, revoke it and generate a new one.
  5. 5
    Manage your tokensThe token now appears under 3. Active API tokens with its label, issue date and prefix. Use Revoke to disable a token you no longer need.
  6. 6
    ConnectUnder 4. Connect, copy a ready-made snippet for JavaScript, Python or cURL.

Keep your token safe

  • The token acts as you: requests run with your permissions on the platform.
  • Keep it in an environment variable or .env file. Never commit it to a repository or paste it into a shared notebook.
  • Use one token per project or tool, so you can revoke one without breaking the others.
  • If a token leaks, revoke it immediately in Active API tokens and generate a new one.

The downloaded .env file looks like this:

WIKIRATE_API_URL=https://data.wikirate.org
WIKIRATE_PUBLISHABLE_KEY=your_publishable_key
WIKIRATE_API_TOKEN=wr_xxxxxxxxxxxxxxxxxxxxxxxx

03 · Making requests

Your first request

Every request is a GET to https://data.wikirate.org/rest/v1/<endpoint> with three headers. Without Accept-Profile: api the endpoints are not found.

HeaderValueRequired
apikeyYour publishable keyYes
x-api-tokenYour personal API tokenYes
Accept-ProfileapiYes
Acceptapplication/json (default) or text/csvNo
Prefercount=exact to get a total row countNo
curl "https://data.wikirate.org/rest/v1/v1_companies?select=id,name&limit=5" \
  -H "apikey: $WIKIRATE_PUBLISHABLE_KEY" \
  -H "x-api-token: $WIKIRATE_API_TOKEN" \
  -H "Accept-Profile: api"

Any other language or tool works the same way: send the three headers and read the JSON response.

04 · Querying

Shape the results

You shape every request with URL query parameters: pick columns with select, filter with column=operator.value, sort with order, and page with limit and offset.

Select columns

select=id,name,website returns only those columns. Rename a column in the output with alias:column, for example select=company_name:name. Omit select to get every column.

Filter

OperatorMeaningExample
eqequalsmetric_id=eq.2929015
neqnot equalvalue=neq.Unknown
gt, gte, lt, ltegreater / less thanyear=gte.2020
inin a listyear=in.(2022,2023,2024)
like, ilikepattern, * as wildcard (ilike ignores case)name=ilike.*nestl*
isnull, true or falsevalue_numeric=is.null
csarray containsdataset_ids=cs.{1234}
not.negate any operatorhq_country_code=not.in.(US,GB)
oreither conditionor=(year.eq.2023,year.eq.2024)

Several filters in one URL are combined with AND.

Filter on JSON fields

Some columns hold JSON objects (headquarters, location, license, company_identifiers). Reach into them with -> (JSON) and ->> (text):

/v1_companies?headquarters->>country_code=eq.DE
/v1_companies?select=name,hq_country:headquarters->>country_code

Order

order=year.desc,company.asc sorts by several columns. Add .nullslast or .nullsfirst to control where empty values go.

Paginate

limit=100&offset=200 returns rows 201–300. Each response returns at most 1,000 rows, so loop with offset for larger result sets. Always add an order when paging, so rows don’t shift between pages.

To know the total, send Prefer: count=exact. The total comes back in the Content-Range response header, for example Content-Range: 200-299/48213. Use count=estimated on very large endpoints such as v1_answers: it is much faster.

const res = await fetch(
  `${BASE_URL}/v1_answers?metric_id=eq.2929015&order=id&limit=1000&offset=0`,
  { headers: { ...headers, Prefer: 'count=exact' } }
);
const answers = await res.json();
const total = Number(res.headers.get('Content-Range').split('/')[1]);

CSV output

Send Accept: text/csv to get CSV instead of JSON. JSON columns are written as JSON text in the cell.

curl "https://data.wikirate.org/rest/v1/v1_dataset_answers?dataset_id=eq.1234" \
  -H "apikey: $WIKIRATE_PUBLISHABLE_KEY" \
  -H "x-api-token: $WIKIRATE_API_TOKEN" \
  -H "Accept-Profile: api" \
  -H "Accept: text/csv" -o answers.csv

05 · Core endpoints

Core endpoints

The five core endpoints cover the building blocks of Wikirate data: companies, metrics, the organisations that design them, regions, and answers (one value for one company, metric and year). IDs and values in the sample responses are illustrative. All timestamps are ISO 8601 in UTC.

GETv1_companiesCompanies

All companies on Wikirate, with their headquarters region.

FieldTypeDescription
idintegerCompany ID
nametextCompany name
headquartersobject or nullHQ region: id, name, type, ilo_region, country_code
logo_urltextLogo image URL
typetextCompany type
company_identifiersobjectExternal identifiers such as LEI, ISIN or SEC CIK
websitetextCompany website
wikipediatextWikipedia page
created_at, updated_attimestampRecord created / last changed

Request — companies headquartered in Switzerland

GET /rest/v1/v1_companies?headquarters->>country_code=eq.CH&order=name&limit=1

Response 200 OK

[
  {
    "id": 1021,
    "name": "Nestlé SA",
    "headquarters": {
      "id": 214,
      "name": "Switzerland",
      "type": "region",
      "ilo_region": "Europe and Central Asia",
      "country_code": "CH"
    },
    "logo_url": "https://data.wikirate.org/storage/v1/object/public/logos/1021.png",
    "type": "company",
    "company_identifiers": {
      "lei": "KY37LUS27QQX7BB93L28",
      "isin": ["CH0038863350"]
    },
    "website": "https://www.nestle.com",
    "wikipedia": "https://en.wikipedia.org/wiki/Nestl%C3%A9",
    "created_at": "2016-03-14T10:22:05Z",
    "updated_at": "2026-09-02T08:15:41Z"
  }
]
GETv1_metricsMetrics

Published metrics: the questions Wikirate collects answers to.

FieldTypeDescription
idintegerMetric ID
metric_nametextMetric name
metric_designertextOrganisation that designed the metric
questiontextThe question researchers answer
metric_typetextHow answers are produced, e.g. researched, formula, score
value_typetextNumber, money, category, multi-category or free text
value_optionsarray or nullAllowed values for category metrics
unittext or nullUnit for numeric values
rangeobject or nullAllowed numeric range
assessment_typetextType of assessment
abouttextDescription and methodology
created_at, updated_attimestampRecord created / last changed

Request

GET /rest/v1/v1_metrics?metric_name=ilike.*modern slavery*&limit=1

Response 200 OK

[
  {
    "id": 2929015,
    "metric_name": "MSA Statement Approved by Board",
    "metric_designer": "Walk Free",
    "question": "Has the modern slavery statement been approved by the board of directors?",
    "metric_type": "researched",
    "value_type": "category",
    "value_options": ["Yes", "No"],
    "unit": null,
    "range": null,
    "assessment_type": "self_reported",
    "about": "Section 54(6) of the UK Modern Slavery Act requires the statement to be approved by the board…",
    "created_at": "2019-05-20T13:01:44Z",
    "updated_at": "2026-07-11T09:30:02Z"
  }
]
GETv1_designersDesigners

Organisations that design metrics and publish datasets and benchmarks.

FieldTypeDescription
idintegerDesigner ID
nametextOrganisation name
locationobject or nullRegion: id, name, type, ilo_region, country_code
logo_urltextLogo image URL
websitetextOrganisation website
topicstextTopics the organisation covers, as a JSON-encoded string
created_at, updated_attimestampRecord created / last changed

Request

GET /rest/v1/v1_designers?name=eq.Walk Free

Response 200 OK

[
  {
    "id": 3107,
    "name": "Walk Free",
    "location": {
      "id": 15,
      "name": "Australia",
      "type": "region",
      "ilo_region": "Asia and the Pacific",
      "country_code": "AU"
    },
    "logo_url": "https://data.wikirate.org/storage/v1/object/public/logos/designer-3107.png",
    "website": "https://www.walkfree.org",
    "topics": "[\"Modern slavery\", \"Human rights\"]",
    "created_at": "2018-11-02T16:40:10Z",
    "updated_at": "2026-06-18T12:04:55Z"
  }
]
GETv1_regionsRegions

Countries and subdivisions used for company headquarters and designer locations.

FieldTypeDescription
idintegerRegion ID
nametextRegion name
ilo_regiontextILO world region
subdivision_codetext or nullISO 3166-2 code for subdivisions
country_codetextISO 3166-1 alpha-2 code
created_at, updated_attimestampRecord created / last changed

Request

GET /rest/v1/v1_regions?country_code=eq.US&subdivision_code=eq.US-CA

Response 200 OK

[
  {
    "id": 488,
    "name": "California (United States)",
    "ilo_region": "Americas",
    "subdivision_code": "US-CA",
    "country_code": "US",
    "created_at": "2016-01-01T00:00:00Z",
    "updated_at": "2025-02-10T11:12:00Z"
  }
]
GETv1_answersAnswers

Published answers to published metrics. Each row is one value for one company, metric and year, with its sources, licence and the datasets it belongs to. This is the largest endpoint: always filter it, for example by metric_id, company_id or year.

FieldTypeDescription
idintegerAnswer ID
company_id, companyinteger, textCompany
hq_region_id, hq_region, hq_country_code, hq_ilo_regioninteger, textCompany headquarters
metric_id, metric_nameinteger, textMetric
metric_designer_id, metric_designerinteger, textMetric designer
metric_typetextMetric type
valuetextThe answer as entered (always text)
value_numericnumber or nullThe value as a number, when it is numeric
unit, value_typetextFrom the metric
yearintegerYear the answer applies to
sourcesarray or nullSources: id, name, description, original_url, file_url
license_id, licenseinteger, objectLicence: id, name, abbreviation, reference_url
dataset_idsinteger array or nullDatasets that include this answer
created_at, updated_attimestampRecord created / last changed

Request — one company's answers for one metric

GET /rest/v1/v1_answers?metric_id=eq.2929015&company_id=eq.1021&order=year.desc

Response 200 OK

[
  {
    "id": 15800342,
    "company_id": 1021,
    "company": "Nestlé SA",
    "hq_region_id": 214,
    "hq_region": "Switzerland",
    "hq_country_code": "CH",
    "hq_ilo_region": "Europe and Central Asia",
    "metric_id": 2929015,
    "metric_name": "MSA Statement Approved by Board",
    "metric_designer_id": 3107,
    "metric_designer": "Walk Free",
    "metric_type": "researched",
    "value": "Yes",
    "value_numeric": null,
    "unit": null,
    "value_type": "category",
    "year": 2024,
    "sources": [
      {
        "id": 9012233,
        "name": "Nestlé UK Modern Slavery Statement 2024",
        "description": "Annual statement under the UK Modern Slavery Act",
        "original_url": "https://www.nestle.co.uk/modern-slavery-statement-2024.pdf",
        "file_url": "https://data.wikirate.org/storage/v1/object/public/sources/9012233.pdf"
      }
    ],
    "license_id": 1,
    "license": {
      "id": 1,
      "name": "Creative Commons Attribution 4.0 International",
      "abbreviation": "CC BY 4.0",
      "reference_url": "https://creativecommons.org/licenses/by/4.0/"
    },
    "dataset_ids": [1234, 1302],
    "created_at": "2025-03-04T09:12:44Z",
    "updated_at": "2025-03-04T09:12:44Z"
  }
]

To find every answer in a dataset, filter the array: dataset_ids=cs.{1234}. The dedicated v1_dataset_answers endpoint is the simpler way to do this.

06 · Dataset endpoints

Dataset endpoints

A dataset is a curated collection of metrics, companies and answers published by one organisation. Start with v1_datasets to find a dataset ID, then use it to filter the other three endpoints. Datasets that are editions of a benchmark are not listed here; use the benchmark endpoints for those.

EndpointOne row perFilter by
v1_datasetsdatasetid, publisher_id, name
v1_dataset_metricsmetric in a datasetdataset_id
v1_dataset_companiescompany in a datasetdataset_id
v1_dataset_answersanswer in a datasetdataset_id
GETv1_datasetsDatasets
FieldTypeDescription
idintegerDataset ID
nametextDataset name
publisher_id, publisher_nameinteger, textPublishing organisation (a designer)
count_metricsintegerNumber of metrics
count_companiesintegerNumber of companies
count_answersintegerNumber of answers
min_year, max_yearintegerYears covered
created_at, updated_attimestampRecord created / last changed

Request

GET /rest/v1/v1_datasets?publisher_name=eq.Walk Free

Response 200 OK

[
  {
    "id": 1234,
    "name": "UK Modern Slavery Act Statements",
    "publisher_id": 3107,
    "publisher_name": "Walk Free",
    "count_metrics": 12,
    "count_companies": 4870,
    "count_answers": 61523,
    "min_year": 2017,
    "max_year": 2025,
    "created_at": "2019-06-01T10:00:00Z",
    "updated_at": "2026-10-12T07:45:19Z"
  }
]
GETv1_dataset_metricsDataset metrics

The published metrics in a dataset. Fields are the same as v1_metrics, plus dataset_id, with the metric ID returned as metric_id.

Request

GET /rest/v1/v1_dataset_metrics?dataset_id=eq.1234&select=dataset_id,metric_id,metric_name,value_type&limit=2

Response 200 OK

[
  {
    "dataset_id": 1234,
    "metric_id": 2929015,
    "metric_name": "MSA Statement Approved by Board",
    "value_type": "category"
  },
  {
    "dataset_id": 1234,
    "metric_id": 2929021,
    "metric_name": "MSA Statement Signed by Director",
    "value_type": "category"
  }
]
GETv1_dataset_companiesDataset companies

The companies with answers in a dataset, each listed once. Fields are the same as v1_companies, plus dataset_id.

Request

GET /rest/v1/v1_dataset_companies?dataset_id=eq.1234&select=dataset_id,id,name,headquarters&limit=1

Response 200 OK

[
  {
    "dataset_id": 1234,
    "id": 1021,
    "name": "Nestlé SA",
    "headquarters": {
      "id": 214,
      "name": "Switzerland",
      "type": "region",
      "ilo_region": "Europe and Central Asia",
      "country_code": "CH"
    }
  }
]
GETv1_dataset_answersDataset answers

The published answers in a dataset. Fields are the same as v1_answers, plus dataset_id, without dataset_ids. Combine filters to narrow down large datasets, for example by year and country.

Request

GET /rest/v1/v1_dataset_answers?dataset_id=eq.1234&year=eq.2024&hq_country_code=eq.CH&select=dataset_id,id,company,metric_name,value,year&limit=2

Response 200 OK

[
  {
    "dataset_id": 1234,
    "id": 15800342,
    "company": "Nestlé SA",
    "metric_name": "MSA Statement Approved by Board",
    "value": "Yes",
    "year": 2024
  },
  {
    "dataset_id": 1234,
    "id": 15800347,
    "company": "Nestlé SA",
    "metric_name": "MSA Statement Signed by Director",
    "value": "Yes",
    "year": 2024
  }
]

To download a full dataset, page through v1_dataset_answers in blocks of 1,000 rows ordered by id, or request it as CSV.

07 · Benchmark endpoints

Benchmark endpoints

A benchmark ranks companies with a scoring methodology and is published in yearly editions; each edition is a dataset. Start with v1_benchmarks to find the benchmark ID and its editions, then filter the other endpoints by benchmark_id and edition_year.

EndpointOne row perFilter by
v1_benchmarksbenchmarkbenchmark_id, publisher_id
v1_benchmark_metricsmetric in an editionbenchmark_id, edition_year, dataset_id
v1_benchmark_companiescompany in an editionbenchmark_id, edition_year, dataset_id
v1_benchmark_answersanswer in an editionbenchmark_id, edition_year, dataset_id
GETv1_benchmarksBenchmarks
FieldTypeDescription
benchmark_idintegerBenchmark ID (the benchmark’s overall score metric)
benchmark_nametextBenchmark name
publisher_id, publisher_nameinteger, textPublishing organisation
editionsarrayOne entry per edition: year and dataset_id, oldest first

Request

GET /rest/v1/v1_benchmarks?publisher_name=eq.Know The Chain

Response 200 OK

[
  {
    "benchmark_id": 5512870,
    "publisher_id": 2894,
    "benchmark_name": "KnowTheChain Food & Beverage Benchmark",
    "publisher_name": "Know The Chain",
    "editions": [
      { "year": 2020, "dataset_id": 2201 },
      { "year": 2022, "dataset_id": 2388 },
      { "year": 2025, "dataset_id": 2756 }
    ]
  }
]
GETv1_benchmark_metricsBenchmark metrics

The published metrics in each edition. Fields are the same as v1_metrics, plus benchmark_id, edition_year and dataset_id. Filter by edition_year to get one edition.

Request

GET /rest/v1/v1_benchmark_metrics?benchmark_id=eq.5512870&edition_year=eq.2025&select=benchmark_id,edition_year,dataset_id,id,metric_name,value_type&limit=1

Response 200 OK

[
  {
    "benchmark_id": 5512870,
    "edition_year": 2025,
    "dataset_id": 2756,
    "id": 5512901,
    "metric_name": "Recruitment: Responsible recruitment fees policy",
    "value_type": "number"
  }
]
GETv1_benchmark_companiesBenchmark companies

The companies assessed in each edition. Fields are the same as v1_companies, plus benchmark_id, edition_year and dataset_id.

Request

GET /rest/v1/v1_benchmark_companies?benchmark_id=eq.5512870&edition_year=eq.2025&select=benchmark_id,edition_year,dataset_id,id,name&limit=1

Response 200 OK

[
  {
    "benchmark_id": 5512870,
    "edition_year": 2025,
    "dataset_id": 2756,
    "id": 1021,
    "name": "Nestlé SA"
  }
]
GETv1_benchmark_answersBenchmark answers

The published answers in each edition, including the overall benchmark score. Fields are the same as v1_answers, plus benchmark_id, edition_year and dataset_id, without dataset_ids.

Request — overall scores for the 2025 edition, highest first

GET /rest/v1/v1_benchmark_answers?benchmark_id=eq.5512870&edition_year=eq.2025&metric_id=eq.5512870&order=value_numeric.desc.nullslast&select=benchmark_id,edition_year,dataset_id,company_id,company,metric_name,value,value_numeric,year&limit=2

Response 200 OK

[
  {
    "benchmark_id": 5512870,
    "edition_year": 2025,
    "dataset_id": 2756,
    "company_id": 1021,
    "company": "Nestlé SA",
    "metric_name": "KnowTheChain Food & Beverage Benchmark",
    "value": "61.5",
    "value_numeric": 61.5,
    "year": 2025
  },
  {
    "benchmark_id": 5512870,
    "edition_year": 2025,
    "dataset_id": 2756,
    "company_id": 1187,
    "company": "Unilever PLC",
    "metric_name": "KnowTheChain Food & Beverage Benchmark",
    "value": "58",
    "value_numeric": 58,
    "year": 2025
  }
]

08 · Errors and good practice

When something goes wrong

A successful request returns 200 OK with a JSON array, which is empty ([]) when nothing matches. Errors return a JSON object with code, message, details and hint.

{
  "code": "42703",
  "message": "column v1_companies.nme does not exist",
  "details": null,
  "hint": "Perhaps you meant to reference the column \"v1_companies.name\"."
}
StatusTypical causeWhat to do
400 Bad RequestMalformed filter, unknown column or wrong value typeCheck column names and operator syntax
401 UnauthorizedMissing or wrong publishable key, or missing, revoked or invalid API tokenCheck both headers; generate a new token if yours was revoked
404 Not FoundEndpoint name misspeltCheck the name, including the v1_ prefix
406 Not AcceptableAccept-Profile is not api, or an unsupported Accept formatSend Accept-Profile: api
416 Range Not Satisfiableoffset past the last rowStop paging
500 or 503Query too heavy or timed outAdd filters, select fewer columns, use smaller pages

Good practice

  • Filter large endpoints (v1_answers, v1_dataset_answers, v1_benchmark_answers) and select only the columns you need.
  • Page with limit, offset and a stable order, such as order=id.
  • Prefer count=estimated over count=exact on large endpoints.
  • Cache results you reuse. Most data changes daily at most; updated_at tells you what changed.
  • Credit the data: every answer carries its license (mostly CC BY 4.0). Cite Wikirate and the metric designer when you publish results.

Need help?

Contact the Wikirate team with the request URL and the error response (never the token).

info@wikirate.org