What the API offers
The API gives your organisation programmatic access to the reports in your licence. Every endpoint is scoped to your entitlement: your licensed companies, report types and fiscal years. You never need to filter for it yourself, and you cannot list, read or download a report outside it.
Reports and metadata
Sustainability, integrated and annual reports and specialty disclosures, each with 50 metadata fields: identifiers, report type, fiscal period, frameworks, materiality and assurance.
Original PDFs
A short-lived signed link to each report PDF, with a SHA-256 hash so you can verify every file and skip unchanged ones.
Change feed
An incremental feed of added, updated and withdrawn reports. After the first load, a weekly sync only moves what changed.
Identifier resolution
Map your ISINs, LEIs, FIGIs, CIKs and tickers to our company keys, up to 1,000 identifiers per call.
Base URL
All requests use HTTPS and one base URL. Sandbox and production keys use the same URL.
https://api.sustainabilityreports.com/api/v2Requests and responses are JSON in UTF-8. Timestamps are ISO 8601 in UTC. Dates are YYYY-MM-DD.
Authentication
Send your API key on every request, in either header. Only GET /health works without a key.
Authorization: Bearer <your key>
X-API-Key: <your key>Keys start with srk_live_. We store keys only as one-way hashes, so we cannot read a key back: a lost key is replaced. We deliver keys through a one-time secret link to your named technical contact, never by plain email.
Keep keys secret
Store keys in a secret manager, never in source code, tickets or chat. If a key may have been exposed, email [email protected]. We revoke it immediately and issue a replacement. When you write to us, quote only the key prefix (the first 15 characters, for example srk_live_ab12cd).
Rate limits
Each key has its own per-minute limit, set when we issue it. Production keys normally allow 600 requests per minute and sandbox keys 120. Every authenticated response tells you where you stand:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed per minute for this key. |
X-RateLimit-Remaining | Requests left in the current one-minute window (approximate). |
Retry-After | On a 429 response: seconds to wait before retrying. |
Use up to 8 parallel connections, and stay below 10 requests per second from one IP address. Our network edge protects the service per IP address, and traffic from other users who share your egress address counts too. If you run from fixed IP addresses, tell us which ones. GET /meta/usage shows your requests and downloads this calendar month.
Pagination
List endpoints return a page of results in data and a page_info object. To get the next page, pass page_info.next_cursor back as the cursor parameter. Stop when has_more is false. Cursors are opaque: store and return them, but do not build or edit them.
{
"data": [ ... ],
"page_info": { "count": 200, "has_more": true, "next_cursor": "eyJpIjo1Mjk3Njl9" }
}GET /reports returns up to 200 reports per page and GET /watchlist up to 500 companies. Filters can repeat: ?type=SR&type=IR means SR or IR. Different filters combine with AND. Repeated framework values must all apply. A request may carry at most 500 filter values.
Errors
Errors from the API use RFC 9457 problem details, with content type application/problem+json.
{"type": "about:blank", "title": "Forbidden", "status": 403, "detail": "Report 123 is not within your entitlement."}Errors from our network edge, such as a 403 or 5xx page from Cloudflare, may be HTML. Check the status code and content type before you parse the body. If you receive an HTML 403 or 429, it came from the edge: email us with the time (UTC) and your egress IP address.
| Status | Meaning | What to do |
|---|---|---|
| 400, 422 | Invalid request or parameter. 422 responses list each invalid field in errors. | Fix the request. |
| 401 | Missing, invalid, revoked or expired key. | Check the header. Contact us if the key should work. |
| 403 | Outside your entitlement, or the key lacks a scope. | Expected for reports outside your licence. |
| 404 | No such report in your entitlement, or no PDF for it. | Skip it. It may have been withdrawn. |
| 429 | Rate limit exceeded. | Wait for Retry-After seconds, then retry. |
| 500, 502, 503, 504 | Temporary service problem. A 503 on a download request carries Retry-After. | Retry with exponential backoff. Contact us if it lasts beyond 15 minutes. |
Versioning
This is version 2 of the API, under /api/v2. The current release is 2.4.0. Within v2 we only make additive changes: new endpoints, new optional parameters, new fields and new report-type codes. Build your client to ignore fields it does not know. A breaking change would come as a new major version, announced by email at least 90 days ahead. Every release is listed in the changelog.
Endpoints
All 13 endpoints in version 2.4.0. The API reference has every parameter, schema and example.
| Endpoint | What it does | Key |
|---|---|---|
| GET/health | Liveness check | None |
| GET/entitlements | Your access window | Required |
| GET/watchlist | Your licensed companies | Required |
| POST/companies/resolve | Resolve identifiers to companies | Required |
| GET/reports | List your entitled reports | Required |
| GET/reports/changes | Changes since a point in time (incremental sync) | Required |
| POST/reports/lookup | Map report keys to report ids | Required |
| GET/reports/{report_id} | One report's metadata | Required |
| GET/reports/{report_id}/download | Signed link to the report PDF | Required |
| GET/meta/schema | The 50 metadata fields, field by field | Required |
| GET/meta/field-guide.pdf | The metadata field guide as PDF | Required |
| GET/meta/frameworks | Framework filter codes | Required |
| GET/meta/usage | Your usage this calendar month | Required |
Getting access
API access comes with an Enterprise Licence. We agree the companies, report types and fiscal years with you, then issue keys for your technical contact. On request we first issue a sandbox key for a small set of your companies, with the same API and data, so you can build and test before the production key.
Questions about the API or your integration: email [email protected]. Include your key prefix, the request path, the time (UTC), and the response status and body. Never send a full key.
Guides
Your first requests in curl and Python.
Bulk PDF downloadsLoad a full PDF collection and keep it in sync.
Data modelIdentifiers, report types, the 50 metadata fields and their conventions.
API referenceEvery endpoint, parameter and response, from the OpenAPI file.
ChangelogWhat changed in each version.
