API keys
Open the key management page, log in, and create a key. The page shows the key once: copy it then.
Send it on every call as Authorization: Bearer <key>. A call with no key, or with a key that is unknown, revoked or expired, answers UNAUTHENTICATED (HTTP 401) before anything else.
Entry points
Every method answers on the three, with the same params and the same result.
| Entry point | How | Document |
| REST | POST /public/v1/api/<method>, the params as the body. The HTTP status carries the error class. | OpenAPI 3.1 |
| JSON-RPC 2.0 | POST https://developer.darwindata.ai/public/v1/json-rpc, one call per request. The answer is HTTP 200, error or not. | OpenRPC 1.3.2, or the method rpc.discover |
| JSON-RPC 2.0 over a WebSocket | wss://developer.darwindata.ai/public/v1/ws, one call per text frame, several at once, matched by id. |
The description these pages are built from: /public/v1/description.json.
Stability
experimentalCan change or go without notice.
stableA change keeps the calls that work today working.
deprecatedStill works, and will be removed. Stop using it.
Error classes
Every call can answer the protocol classes (a negative code) and these classes, before its method runs: UNAUTHENTICATED, FORBIDDEN, RATE_LIMITED, UNAVAILABLE. Each method lists the others it can answer.
| Class | Code | HTTP | Meaning |
PARSE_ERROR | -32700 | 400 | The text is not JSON.
|
INVALID_REQUEST | -32600 | 400 | The JSON is not a request: no id, a batch, a wrong jsonrpc.
|
METHOD_NOT_FOUND | -32601 | 404 | No method has this name.
|
INVALID_PARAMS | -32602 | 400 | The params do not match the input schema of the method.
|
INTERNAL | -32603 | 500 | A fault of ours.
|
UNAUTHENTICATED | 1401 | 401 | The credential is missing, expired or refused.
|
FORBIDDEN | 1403 | 403 | The caller may not read this resource.
|
NOT_FOUND | 1404 | 404 | The resource named in the params does not exist in the scope of the call.
|
NOT_READY | 1409 | 409 | The project has no sealed snapshot yet. Try again later: this is not an empty answer.
|
INVALID_QUERY | 1422 | 422 | The SQL is not one read-only SELECT, or it failed on the caller's own text.
|
QUERY_TIMEOUT | 1408 | 408 | The SQL is correct but ran out of the time budget.
|
QUERY_TOO_LARGE | 1413 | 413 | The SQL is correct but ran out of the memory of its connection. Narrow it.
|
RATE_LIMITED | 1429 | 429 | The caller sent more calls than its quota.
|
UNAVAILABLE | 1503 | 503 | A dependency of the service is down. Try again later.
|
projects/list experimental
The projects your key may read, in all its organizations.
Any key. The answer holds only what the key reads.
Answers the projects of every organization your key reads, from the oldest to the newest.
Page with page.limit and the nextCursor of the previous page. The last page has no
nextCursor. A project created after your first page comes on the last page.
The analytics methods read a project only when its state is computed: an assessment of the
project completed. While a new assessment runs, the project stays computed, and the analytics
methods read the previous assessment until the snapshot of the new one is sealed.
Params
| Name | Type | Required | Default | Description |
page | object | no | {"limit":100} | Which page to return. Omit it for the first page, at the default size.
|
page.limit | integer (uint32), 1 to 500 | no | 100 | How many items to return.
|
page.cursor | Cursor | no | | The nextCursor of the previous page. Omit it for the first page.
|
Result
ProjectSummaryList
Errors
Only the classes of every call.
Examples
A "$projectId" in the params stands for the id of a project your key reads.
The first page
REST:
curl -X POST https://developer.darwindata.ai/public/v1/api/projects/list \
-H 'Authorization: Bearer <key>' \
-H 'Content-Type: application/json' \
-d '{}'
JSON-RPC: send this body to https://developer.darwindata.ai/public/v1/json-rpc, or as a text frame on the WebSocket.
{
"jsonrpc": "2.0",
"id": 1,
"method": "projects/list",
"params": {}
}
Two projects per page
REST:
curl -X POST https://developer.darwindata.ai/public/v1/api/projects/list \
-H 'Authorization: Bearer <key>' \
-H 'Content-Type: application/json' \
-d '{"page":{"limit":2}}'
JSON-RPC: send this body to https://developer.darwindata.ai/public/v1/json-rpc, or as a text frame on the WebSocket.
{
"jsonrpc": "2.0",
"id": 1,
"method": "projects/list",
"params": {
"page": {
"limit": 2
}
}
}
projects/describe experimental
The relations projects/query can read, and the columns of one.
Scope projectAnalytics: the project must belong to an organization your key reads.
Answers what projects/query can read in a project: every relation, what one row of it is, and
worked queries.
Name a relation in relation to get its columns and their SQL types, read from the snapshot of
the project. The relations whose kind is fold are computed from the snapshot for the point of
view of the query, most of them aggregations: read them rather than rebuild a total from the
tables.
The catalogue is the same for every project. The columns need a sealed snapshot of the project:
before the first one, the answer is NOT_READY. They are built within 60 seconds; past it, the
answer is UNAVAILABLE: retry later.
Params
| Name | Type | Required | Default | Description |
projectId | ProjectId | yes | | The id of the project, a UUID. projects/list gives the ids your key may read.
|
relation | string | no | | A relation of the catalogue, e.g. fold_risks. Give it to get its columns and their types.
|
Result
ProjectDescription
Errors
NOT_READY, on top of the classes of every call.
Examples
A "$projectId" in the params stands for the id of a project your key reads.
The catalogue
REST:
curl -X POST https://developer.darwindata.ai/public/v1/api/projects/describe \
-H 'Authorization: Bearer <key>' \
-H 'Content-Type: application/json' \
-d '{"projectId":"$projectId"}'
JSON-RPC: send this body to https://developer.darwindata.ai/public/v1/json-rpc, or as a text frame on the WebSocket.
{
"jsonrpc": "2.0",
"id": 1,
"method": "projects/describe",
"params": {
"projectId": "$projectId"
}
}
The columns of the risks
REST:
curl -X POST https://developer.darwindata.ai/public/v1/api/projects/describe \
-H 'Authorization: Bearer <key>' \
-H 'Content-Type: application/json' \
-d '{"projectId":"$projectId","relation":"fold_risks"}'
JSON-RPC: send this body to https://developer.darwindata.ai/public/v1/json-rpc, or as a text frame on the WebSocket.
{
"jsonrpc": "2.0",
"id": 1,
"method": "projects/describe",
"params": {
"projectId": "$projectId",
"relation": "fold_risks"
}
}
projects/query experimental
One read-only SQL query over the analytics of a project.
Scope projectAnalytics: the project must belong to an organization your key reads.
Runs one read-only SQL query over the analytics of a project, and answers its rows as JSON
objects, one page at a time.
sql is one SELECT over the relations of projects/describe, or a UNION, EXCEPT or
INTERSECT of them, with an optional WITH. A statement that writes, a second statement, and
a read of a file outside the project's own analytics are refused with INVALID_QUERY. So is a
query that fails on its own text, and a single row larger than 4 MiB as JSON.
- The query reads the point of view of
entityId and its subtree, or of the whole project when
entityId is absent, with net or gross ownership.
- It reads the latest sealed snapshot of the project, which can belong to an assessment that still
runs. Before the first one, the answer is
NOT_READY.
The numbers are the ones the screens compute, with three differences:
- The risks a user excluded are not in
fold_risks and risk_rows. The screens keep them in
their totals, so a total here can be lower.
- An entity with no dependency data of its own has no row in
fold_dependencies. The screens
show a sector estimate for it.
- The relations carry no sourcing risk: the screens add it to the commodities.
Limits:
- The relations the query names are built first, within 60 seconds. Past it, the answer is
UNAVAILABLE: retry later.
- The query then has 30 seconds. Past it, the answer is
QUERY_TIMEOUT. A query that runs out of
memory answers QUERY_TOO_LARGE. Narrow the query in both cases, because a retry fails the same
way.
- A call waits 5 seconds at most for a free connection, then answers
UNAVAILABLE.
Page with page.limit and the nextCursor of the previous page. Send the same sql, entityId
and ownershipView with it. The last page has no nextCursor. The cursor counts rows: order the
rows on a unique key, or a row can move between two pages. A page stops early when its rows hold
more than 4 MiB as JSON: follow its nextCursor. When a new assessment replaces the snapshot
between two pages, the cursor answers INVALID_PARAMS: start again from the first page.
Params
| Name | Type | Required | Default | Description |
projectId | ProjectId | yes | | The id of the project, a UUID. projects/list gives the ids your key may read.
|
entityId | EntityId | no | | The entity whose subtree the query reads, a UUID. Omit it for the whole project.
|
ownershipView | OwnershipView | no | "net" | net (the default) or gross.
|
sql | string | yes | | One SELECT over the relations of projects/describe, or a UNION, EXCEPT or
INTERSECT of them, with an optional WITH. Anything else is refused. Order the rows on a
unique key to page them.
|
page | object | no | {"limit":100} | Which page of rows to return. Omit it for the first page, at the default size. Send the
same sql, entityId and ownershipView with a cursor.
|
page.limit | integer (uint32), 1 to 500 | no | 100 | How many items to return.
|
page.cursor | Cursor | no | | The nextCursor of the previous page. Omit it for the first page.
|
Result
RowList
Errors
NOT_FOUND, NOT_READY, INVALID_QUERY, QUERY_TIMEOUT, QUERY_TOO_LARGE, on top of the classes of every call.
Examples
A "$projectId" in the params stands for the id of a project your key reads.
The impact by IPBES pressure
REST:
curl -X POST https://developer.darwindata.ai/public/v1/api/projects/query \
-H 'Authorization: Bearer <key>' \
-H 'Content-Type: application/json' \
-d '{"projectId":"$projectId","sql":"SELECT ipbes_pressure, value FROM dash_ipbes ORDER BY value DESC"}'
JSON-RPC: send this body to https://developer.darwindata.ai/public/v1/json-rpc, or as a text frame on the WebSocket.
{
"jsonrpc": "2.0",
"id": 1,
"method": "projects/query",
"params": {
"projectId": "$projectId",
"sql": "SELECT ipbes_pressure, value FROM dash_ipbes ORDER BY value DESC"
}
}
The ten largest pressures, gross
REST:
curl -X POST https://developer.darwindata.ai/public/v1/api/projects/query \
-H 'Authorization: Bearer <key>' \
-H 'Content-Type: application/json' \
-d '{"projectId":"$projectId","ownershipView":"gross","sql":"SELECT pressure_indicator, unit, biome, scope, net FROM fold_pressures ORDER BY abs(net) DESC, pressure_indicator, biome, scope","page":{"limit":10}}'
JSON-RPC: send this body to https://developer.darwindata.ai/public/v1/json-rpc, or as a text frame on the WebSocket.
{
"jsonrpc": "2.0",
"id": 1,
"method": "projects/query",
"params": {
"projectId": "$projectId",
"ownershipView": "gross",
"sql": "SELECT pressure_indicator, unit, biome, scope, net FROM fold_pressures ORDER BY abs(net) DESC, pressure_indicator, biome, scope",
"page": {
"limit": 10
}
}
}
projects/export experimental
One read-only SQL query over the analytics of a project, as a parquet file.
Scope projectAnalytics: the project must belong to an organization your key reads.
Runs one read-only SQL query over the analytics of a project, writes all its rows to one parquet
file, and answers a URL to download it. Use it for a relation too large to page with
projects/query.
sql, entityId and ownershipView are those of projects/query, with the same rules and the
same three differences from the screens. There is no page and no 4 MiB limit on a row: the file
holds every row.
- The answer is
url, expiresAt, rows and bytes. Download the file with a plain GET on
url, with no header: the URL carries its own signature. It stops working at expiresAt, 15
minutes after the call. Call again for a new URL.
- Each call writes a new file. The storage removes it about one day later.
Limits:
- The relations the query names are built first, within 60 seconds. Past it, the answer is
UNAVAILABLE: retry later.
- The query then has 120 seconds. Past it, the answer is
QUERY_TIMEOUT. A query that runs out of
memory answers QUERY_TOO_LARGE. So does a file that grows past 1 GiB: the query stops there.
Narrow the query in both cases, because a retry fails the same way.
- A call waits 5 seconds at most for a free connection, then answers
UNAVAILABLE.
Params
| Name | Type | Required | Default | Description |
projectId | ProjectId | yes | | The id of the project, a UUID. projects/list gives the ids your key may read.
|
entityId | EntityId | no | | The entity whose subtree the query reads, a UUID. Omit it for the whole project.
|
ownershipView | OwnershipView | no | "net" | net (the default) or gross.
|
sql | string | yes | | One SELECT over the relations of projects/describe, or a UNION, EXCEPT or
INTERSECT of them, with an optional WITH. Anything else is refused.
|
Result
ProjectExport
Errors
NOT_FOUND, NOT_READY, INVALID_QUERY, QUERY_TIMEOUT, QUERY_TOO_LARGE, on top of the classes of every call.
Examples
A "$projectId" in the params stands for the id of a project your key reads.
Every dependency row of the project
REST:
curl -X POST https://developer.darwindata.ai/public/v1/api/projects/export \
-H 'Authorization: Bearer <key>' \
-H 'Content-Type: application/json' \
-d '{"projectId":"$projectId","sql":"SELECT * FROM dependency_rows"}'
JSON-RPC: send this body to https://developer.darwindata.ai/public/v1/json-rpc, or as a text frame on the WebSocket.
{
"jsonrpc": "2.0",
"id": 1,
"method": "projects/export",
"params": {
"projectId": "$projectId",
"sql": "SELECT * FROM dependency_rows"
}
}
Schemas
ProjectsListInput
The projects that the key may read, one page at a time.
| Name | Type | Required | Description |
page | object | no | Which page to return. Omit it for the first page, at the default size.
|
page.limit | integer (uint32), 1 to 500 | no | How many items to return.
|
page.cursor | Cursor | no | The nextCursor of the previous page. Omit it for the first page.
|
Cursor
A position in a list, as the previous page returned it. The caller never builds one.
string
ProjectSummaryList
One page of a list.
| Name | Type | Required | Description |
items | ProjectSummary[] | yes | The items of this page. Empty when the list is empty.
|
nextCursor | Cursor | no | Absent on the last page.
|
ProjectSummary
One project the key may read.
| Name | Type | Required | Description |
projectId | ProjectId | yes | The id of the project, a UUID.
|
name | string | yes | The name of the project, as Darwin shows it.
|
organization | OrganizationKey | yes | The key of the organization that owns the project.
|
state | ProjectState | yes | Whether the analytics methods can read the project now.
|
ProjectId
string (uuid)
OrganizationKey
The key of an organization, such as darwin.
string
ProjectState
Whether the analytics methods can read the project. They read the snapshot of the last
completed assessment.
computedAn assessment completed: the analytics methods can read the project. While a new
assessment runs, they read the previous one until the snapshot of the new one is sealed.
computingThe first assessment runs: nothing can be read yet.
notComputedNo assessment completed, and none runs: nothing can be read.
ProjectsDescribeInput
The project to describe, and optionally one of its relations.
| Name | Type | Required | Description |
projectId | ProjectId | yes | The id of the project, a UUID. projects/list gives the ids your key may read.
|
relation | string | no | A relation of the catalogue, e.g. fold_risks. Give it to get its columns and their types.
|
ProjectDescription
The catalogue of the relations, and the columns of one relation when the input names one.
| Name | Type | Required | Description |
relations | RelationSummary[] | yes | Every relation a query may read, the computed ones first.
|
examples | QueryExample[] | yes | Worked queries, each with the question it answers.
|
columns | Column[] | no | The columns of the relation of the input, in order. Absent when the input names none.
|
RelationSummary
One relation a query may name in FROM.
| Name | Type | Required | Description |
name | string | yes | The name to write in FROM.
|
kind | RelationKind | yes | |
about | string | no | What one row is. Absent for a table, whose columns say it.
|
RelationKind
foldA relation Darwin computes from the snapshot for the point of view of the query, most of
them aggregations. Read one rather than rebuild a total from the tables.
tableA table of the assessment, as Darwin stored it.
QueryExample
A worked query.
| Name | Type | Required | Description |
question | string | yes | The question the query answers.
|
sql | string | yes | The sql to send to projects/query.
|
Column
One column of a relation.
| Name | Type | Required | Description |
name | string | yes | The name to write in a query.
|
type | string | yes | The SQL type of the column, e.g. VARCHAR, DOUBLE, UUID.
|
ProjectsQueryInput
One read-only SQL query over the analytics of a project.
| Name | Type | Required | Description |
projectId | ProjectId | yes | The id of the project, a UUID. projects/list gives the ids your key may read.
|
entityId | EntityId | no | The entity whose subtree the query reads, a UUID. Omit it for the whole project.
|
ownershipView | OwnershipView | no | net (the default) or gross.
|
sql | string | yes | One SELECT over the relations of projects/describe, or a UNION, EXCEPT or
INTERSECT of them, with an optional WITH. Anything else is refused. Order the rows on a
unique key to page them.
|
page | object | no | Which page of rows to return. Omit it for the first page, at the default size. Send the
same sql, entityId and ownershipView with a cursor.
|
page.limit | integer (uint32), 1 to 500 | no | How many items to return.
|
page.cursor | Cursor | no | The nextCursor of the previous page. Omit it for the first page.
|
EntityId
string (uuid)
OwnershipView
Net or gross ownership.
netEach entity counts at the ownership share along the path. The screens' default.
grossEach entity counts at 100%, whatever the ownership.
RowList
One page of a list.
| Name | Type | Required | Description |
items | Row[] | yes | The items of this page. Empty when the list is empty.
|
nextCursor | Cursor | no | Absent on the last page.
|
Row
One row of the result: each column name, with its value.
object
ProjectsExportInput
One read-only SQL query over the analytics of a project, written whole to one parquet file.
| Name | Type | Required | Description |
projectId | ProjectId | yes | The id of the project, a UUID. projects/list gives the ids your key may read.
|
entityId | EntityId | no | The entity whose subtree the query reads, a UUID. Omit it for the whole project.
|
ownershipView | OwnershipView | no | net (the default) or gross.
|
sql | string | yes | One SELECT over the relations of projects/describe, or a UNION, EXCEPT or
INTERSECT of them, with an optional WITH. Anything else is refused.
|
ProjectExport
Where to download the file, until when, and what it holds.
| Name | Type | Required | Description |
url | string | yes | The URL of the parquet file. Send no header with it: the URL carries its own signature.
|
expiresAt | string (date-time) | yes | When the URL stops working, in RFC 3339.
|
rows | integer (uint64), from 0 | yes | The rows of the file.
|
bytes | integer (uint64), from 0 | yes | The size of the file, in bytes.
|