Resource Watch API Reference
This section of the documentation contains technical reference information for each of the endpoints exposed by the RW API.
Back to the documentation homepage
Authentication
JWT tokens
Most RW API endpoints are public, but some actions require user authentication. Each endpoint's documentation will specify whether authentication is required and under what conditions.
The RW API uses JSON Web Tokens to authenticate requests. Check out the Quickstart Guide for instructions on how to create an account and generate a token.
Authentication is performed using JWT tokens. For all authenticated requests, you must provide your JWT using the
header Authorization: Bearer <your token>
. Please note that your JWT tokens act like passwords, so you should never
share or expose them publicly. Doing so may allow other users to impersonate your RW API user account, and may grant
them permissions over your datasets, applications, etc.
If you lose your JWT, or if it becomes invalidated (which happens whenever the name, email, or applications associated with your account changes), you can always log in via the browser and generate a new token at https://api.resourcewatch.org/auth/generate-token.
API Keys
Besides JWT tokens, the RW API also uses API keys to identify the client application issuing the request. This is done for moderation and analytical purposes, ensuring it's available to everyone for fair use. Unlike the JWT tokens described above, API keys are not used to grant permissions over data. While it's not critical to keep them private, you should have a different API key for each application you create that uses the RW API.
An API key is generated automatically once you register a client application, which you can learn more about in the corresponding section of the reference docs.
Dataset
What is a dataset?
If you are new to the RW API, or want to learn more about the concept of a dataset, we strongly encourage you to read the dataset concept documentation first. It gives you a brief and clear description of what a dataset is, and what it can do for you.
Once you've read that section, you can come back here to learn more details about using the RW API's datasets feature. The RW API is home to many datasets uploaded by WRI, its partner organizations, or by API users like you. These datasets contain a lot of information about a wide range of topics that you may want to learn about or build on top of. To find out more about finding and accessing the datasets already available on the RW API, check out the documentation on getting datasets. A nice, visual way to explore existing datasets is by using the Resource Watch website.
You can also create you own datasets on the RW API, if you'd like to share your data with the world, or if you are looking to use the RW API and its features to gain insights into your data.
Getting all datasets
This endpoint will allow you to get the list of the datasets available in the API, and it's a great place for new users to start exploring the RW API. By default, this endpoint will give you a paginated list of 10 datasets. In the sections below, we'll explore how you can customize this endpoint call to match your needs.
For a detailed description of each field, check out the Dataset reference section.
Getting a list of datasets
curl -X GET https://api.resourcewatch.org/v1/dataset \
-H "x-api-key: <your-api-key>"
Response:
{
"data": [
{
"id": "00f2be42-1ee8-4069-a55a-16a988f2b7a0",
"type": "dataset",
"attributes": {
"name": "Glad points",
"slug": "Glad-points-1490086842129",
"type": null,
"subtitle": null,
"application": [
"data4sdgs"
],
"dataPath": null,
"attributesPath": null,
"connectorType": "document",
"provider": "csv",
"userId": "58333dcfd9f39b189ca44c75",
"connectorUrl": "https://gfw2-data.s3.amazonaws.com/alerts-tsv/glad_headers.csv",
"sources": [],
"tableName": "data",
"status": "pending",
"published": true,
"overwrite": false,
"env": "production",
"geoInfo": false,
"legend": {
"date": [],
"region": [],
"country": []
},
"clonedHost": {},
"errorMessage": null,
"updatedAt": "2017-01-13T10:45:46.368Z",
"widgetRelevantProps": [],
"layerRelevantProps": []
}
}
],
"links": {
"self": "https://api.resourcewatch.org/v1/dataset?page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/v1/dataset?page[number]=1&page[size]=10",
"last": "https://api.resourcewatch.org/v1/dataset?page[number]=99&page[size]=10",
"prev": "https://api.resourcewatch.org/v1/dataset?page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/v1/dataset?page[number]=2&page[size]=10"
},
"meta": {
"total-pages": 99,
"total-items": 990,
"size": 10
}
}
Pagination
Example request to load page 2 using 25 results per page
curl -X GET https://api.resourcewatch.org/v1/dataset?page[number]=2&page[size]=25 \
-H "x-api-key: <your-api-key>"
The Dataset service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your datasets list.
Search
Search for datasets
curl -X GET https://api.resourcewatch.org/v1/dataset?search=wind \
-H "x-api-key: <your-api-key>"
The dataset service offers a simple yet powerful search mechanism that will help you look for datasets. The query
argument search
allows you to specify a search string that will match:
- The dataset name.
- The dataset's metadata name.
- The dataset's metadata description.
- The relational graph node list.
Filters
Filtering datasets
curl -X GET https://api.resourcewatch.org/v1/dataset?name=birds&provider=cartodb \
-H "x-api-key: <your-api-key>"
Matching vocabulary tags
curl -X GET https://api.resourcewatch.org/v1/dataset?vocabulary[legacy]=umd \
-H "x-api-key: <your-api-key>"
The dataset list provides a wide range of parameters that you can use to tailor your dataset listing. Most of these parameters reflect fields you'll find in a dataset itself (which you can learn more about in the Dataset reference section), while others are convenience filters for things like user role or favourites.
Filtering datasets adheres to the conventions defined in the Filter guidelines for the RW API , so we strongly recommend reading that section before proceeding. In addition to these conventions, you can use the following fields as filters supported by the dataset list endpoint:
Filter | Description | Type | Expected values |
---|---|---|---|
name | Filter returned datasets by the name of the dataset. | String | any valid text |
slug | Filter returned datasets by the slug of the dataset. | String | any valid text |
type | Filter returned datasets by dataset type. | String | any valid text |
subtitle | Filter returned datasets by dataset subtitle. | String | any valid text |
application | Applications associated to this dataset. Read more about this field here. | Array | any valid text |
applicationConfig | If the dataset has applicationConfig data (i.e. contains a non-empty object in the applicationConfig field) |
Boolean | true or false |
dataPath | String | any valid text | |
attributesPath | String | any valid text | |
connectorType | Filter returned datasets by the type of connector used. | String | rest , document or wms |
provider | Dataset provider this include inner connectors and 3rd party ones | String | Check the available providers when creating a dataset |
connectorUrl | String | any valid text | |
sources | Array | any valid text | |
tableName | String | any valid text | |
userId | Filter results by the owner of the dataset. Does not support regexes. | String | valid user id |
status | Filter results by the current status of the dataset. | String | pending , saved or failed |
overwrite | If the data can be overwritten (only for being able to make dataset updates) | Boolean | true or false |
errorMessage | If this dataset is in error state, this field may contain additional details about the error. |
String | any valid text |
mainDateField | String | any valid text | |
published | If the dataset is published or not. | Boolean | true or false |
env | Environment to which the dataset belongs. Multiple values can be combined using , as a separator. Does not support regexes. Read more about this field in the Environments concept section. |
String | any valid text. Defaults to production . |
geoInfo | If it contains interceptable geographical info | Boolean | true or false |
protected | If the dataset is protected. | Boolean | true or false |
taskId | Id of the latest task associated with this dataset. Typically only present in document connectorType datasets |
String | any valid text |
legend.lat | String | any valid text | |
legend.long | String | any valid text | |
legend.date | Array | any valid text | |
legend.region | Array | any valid text | |
legend.country | Array | any valid text | |
legend.nested | Array | any valid text | |
legend.integer | Array | any valid text | |
legend.short | Array | any valid text | |
legend.byte | Array | any valid text | |
legend.double | Array | any valid text | |
legend.byte | Array | any valid text | |
legend.float | Array | any valid text | |
legend.half_float | Array | any valid text | |
legend.scaled_float | Array | any valid text | |
legend.boolean | Array | any valid text | |
legend.binary | Array | any valid text | |
legend.text | Array | any valid text | |
legend.keyword | Array | any valid text | |
clonedHost.hostProvider | String | any valid text | |
clonedHost.hostUrl | String | any valid text | |
clonedHost.hostId | String | any valid text | |
clonedHost.hostType | String | any valid text | |
clonedHost.hostPath | String | any valid text | |
widgetRelevantProps | Array | any valid text | |
layerRelevantProps | Array | any valid text | |
subscribable | If the dataset is subscribable (i.e. contains a non-empty object in the subscribable field) |
Boolean | true or false |
user.role | Filter results by the role of the owner of the dataset. If the requesting user does not have the ADMIN role, this filter is ignored. ** Please keep in mind that, due to the limitations of the underlying endpoint used to find user ids by role, the performance of the request while using this filter might be degraded.** | String | ADMIN , MANAGER or USER |
vocabulary[name] | Filter returned datasets by vocabulary tags. Does not support regexes. | String | any valid text |
collection | Filter returned datasets collection id. Does not support regexes. | String | any valid text |
favourite | Filter by favourited datasets. See this section for more info. Does not support regexes. | String | any valid text |
Sorting
Basics of sorting
Sorting datasets
curl -X GET https://api.resourcewatch.org/v1/dataset?sort=name \
-H "x-api-key: <your-api-key>"
Sorting datasets by multiple criteria
curl -X GET https://api.resourcewatch.org/v1/dataset?sort=name,description \
-H "x-api-key: <your-api-key>"
Sort by name descending, description ascending
curl -X GET https://api.resourcewatch.org/v1/dataset?sort=-name,+description \
-H "x-api-key: <your-api-key>"
Sorting datasets by the role of the user who owns the dataset
curl -X GET https://api.resourcewatch.org/v1/dataset?sort=user.role \
-H "x-api-key: <your-api-key>"
The Dataset service currently supports sorting using the sort
query parameter. Sorting dataset adheres to the
conventions defined in the Sorting guidelines for the RW API, so we strongly recommend reading
that section before proceeding. Additionally, you can check out
the Dataset reference section for a detailed description of the fields you can use
when sorting. In addition to all dataset model fields, you can sort the returned results by the name (using user.name
)
or role (using user.role
) of the user owner of the dataset. Keep in mind that sorting by user data is restricted to
ADMIN users.
Please also keep in mind that, due to the limitations of the underlying endpoint used to find user ids by name or role, the performance of the request while using this sort might be degraded.
Special sorting criteria
Sorting datasets with special criteria
curl -X GET https://api.resourcewatch.org/v1/dataset?sort=-most-favorited \
-H "x-api-key: <your-api-key>"
curl -X GET https://api.resourcewatch.org/v1/dataset?sort=relevance&status=saved&search=agriculture \
-H "x-api-key: <your-api-key>"
Special search criteria must be used as sole sorting criteria, as it's not possible to combine any of them with any other search criteria. The following criteria can be used for special sorting in datasets:
most-viewed
delegates sorting to the graph component, sorting by the datasets that have been queried more frequently. Supports ascending/descending order.most-favorited
: delegates sorting to the graph component, sorting by the datasets that have been more favorited. Supports ascending/descending order.relevance
: delegates sorting to the metadata component, sorting by the datasets which metadata better match the search criteria. Can only be used in conjunction with asearch
parameter. Does not support ascending order.
You can specify the sorting order by prepending the criteria with either -
for descending order or +
for ascending
order. By default, ascending order is assumed.
Include entities associated with the datasets
Loads metadata and widgets associated with each dataset:
curl -X GET https://api.resourcewatch.org/v1/dataset?includes=metadata,widget \
-H "x-api-key: <your-api-key>"
{
"data": [
{
"id": "06c44f9a-aae7-401e-874c-de13b7764959",
"type": "dataset",
"attributes": {
"name": "Historical Precipitation -- U.S. (Puget Sound Lowlands)",
"slug": "Historical-Precipitation-US-Puget-Sound-Lowlands-1490086842133",
...
"metadata": [
{
"id": "57a2251d5cd6980a00e054d9",
"type": "metadata",
"attributes": {
...
}
}
],
"widget": [
{
"id": "73f00267-fe34-42aa-a611-13b102f38d75",
"type": "widget",
"attributes": {
...
}
}
]
}
}
],
"links": {
"self": "https://api.resourcewatch.org/v1/dataset?includes=widget%2Cmetadata&page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/v1/dataset?includes=widget%2Cmetadata&page[number]=1&page[size]=10",
"last": "https://api.resourcewatch.org/v1/dataset?includes=widget%2Cmetadata&page[number]=223&page[size]=10",
"prev": "https://api.resourcewatch.org/v1/dataset?includes=widget%2Cmetadata&page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/v1/dataset?includes=widget%2Cmetadata&page[number]=2&page[size]=10"
},
"meta": {
"total-pages": 223,
"total-items": 2228,
"size": 10
}
}
Loading layers for the given dataset
curl -X GET https://api.resourcewatch.org/dataset?includes=layer \
-H "x-api-key: <your-api-key>"
Loading the information about the user who authored the dataset
curl -X GET https://api.resourcewatch.org/v1/dataset?includes=user \
-H "x-api-key: <your-api-key>"
When fetching datasets, you can request additional entities to be loaded. The following entities are available:
widget
- loads all widgets associated with each dataset.layer
- loads all layers associated with each dataset.vocabulary
- loads all vocabulary entities associated with each dataset.metadata
- loads all metadata associated with each dataset.user
- loads the name, email address and role of the author of the dataset. If you do not issue this request as anADMIN
user, or if no user data is available, theuser
object will be empty. Please keep in mind that, due to the limitations of the underlying endpoint used to find users by ids, the performance of the request while including user information might be degraded.
If you specified an env
filter and would like to
also filter the included entities, you can provide
the filterIncludesByEnv=true
query parameter. This is only supported for included widget
and layer
.
Note: If you include related entities (e.g. layers) with query filters, the filters will not cascade to the related entities.
Getting a dataset by id or slug
Getting a dataset by id:
curl -X GET "https://api.resourcewatch.org/v1/dataset/51943691-eebc-4cb4-bdfb-057ad4fc2145" \
-H "x-api-key: <your-api-key>"
Getting a dataset by slug:
curl -X GET "https://api.resourcewatch.org/v1/dataset/Timber-Production-RDC" \
-H "x-api-key: <your-api-key>"
Response (equal for both cases):
{
"data": {
"id": "51943691-eebc-4cb4-bdfb-057ad4fc2145",
"type": "dataset",
"attributes": {
"name": "Timber Production RDC",
"slug": "Timber-Production-RDC",
"type": null,
"subtitle": null,
"application": ["forest-atlas"],
"dataPath": null,
"attributesPath": null,
"connectorType": "document",
"provider": "csv",
"userId": "58750a56dfc643722bdd02ab",
"connectorUrl": "https://wri-forest-atlas.s3.amazonaws.com/COD/temp/annual%20timber%20production%20DRC%20%28test%29%20-%20Sheet1.csv",
"sources": [],
"tableName": "index_51943691eebc4cb4bdfb057ad4fc2145",
"status": "saved",
"overwrite": false,
"legend": {
"date": ["year"],
"region": [],
"country": [],
"long": "",
"lat": ""
},
"clonedHost": {},
"errorMessage": null,
"createdAt": "2017-01-25T21:48:27.535Z",
"updatedAt": "2017-01-25T21:48:28.675Z"
}
}
}
If you know the id or the slug
of a dataset, then you can access it directly. Both id and slug
are case-sensitive.
Using this endpoint, you can also include entities associated with the dataset, in the same way you do when loading multiple datasets.
Getting a dataset by its including its relationships:
curl -X GET https://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959?includes=metadata,vocabulary,widget,layer \
-H "x-api-key: <your-api-key>"
Getting multiple datasets by ids
This endpoint allows you to load multiple datasets by id in a single request.
Errors for getting multiple datasets by ids
Error code | Error message | Description |
---|---|---|
400 | ids: ids can not be empty. | The required ids field is missing in the request body. |
Getting multiple datasets by their ids:
curl -X POST https://api.resourcewatch.org/v1/dataset/find-by-ids \
-H "Content-Type: application/json" \
-H "x-api-key: <your-api-key>" -d \
'{
"ids": [
"0706f039-b929-453e-b154-7392123ae99e",
"0c630feb-8146-4fcc-a9be-be5adcb731c8",
]
}'
Response
{
"data": [
{
"id": "0706f039-b929-453e-b154-7392123ae99e",
"type": "dataset",
"attributes": {
"name": "Social Vulnerability Index (2006-2010) -- U.S. (New Hampshire)",
"slug": "Social-Vulnerability-Index-2006-2010-US-New-Hampshire-1490086842541",
"type": "tabular",
"subtitle": null,
...
}
},
{
"id": "0c630feb-8146-4fcc-a9be-be5adcb731c8",
"type": "dataset",
"attributes": {
"name": "USGS Land Cover - Impervious Surface (2001) -- U.S. (Alaska)",
"slug": "USGS-Land-Cover-Impervious-Surface-2001-US-Alaska-1490086842439",
"type": "raster",
"subtitle": null,
...
}
}
]
}
Creating a dataset
So you are ready to create your first dataset on the RW API? Great, welcome aboard! These instruction will help you create your dataset on the RW API, so you can start sharing your data with the world and taking full advantage of all the RW API features on your projects.
Before creating a dataset, there are a few things you must know and do:
- In order to be able to create a dataset, you need to be authenticated.
- Depending on your user account's role, you may have permission to create a dataset but not delete it afterwards - read more about this in the RW API role-based access control guidelines.
- All data uploaded to the RW API will be publicly visible and available to other users.
The first thing to consider when creating a dataset is where your data currently is - this will determine
the Dataset provider you will need to use and, with it, a set of things you need to
take into account - we'll cover each provider in detail shortly. When building your request to the RW API to create your
dataset, you will need to take into account both the general details that follow, plus the details for the provider
you
are using. Be sure to review both sections when creating your datasets, to avoid any pitfalls.
Creating a dataset is done using a POST request and passing the relevant data as body files. The supported body fields are as defined on the dataset reference section, but the minimum field list you must specify for all datasets is:
- name
- application
- connectorType
- provider
Additionally, depending on the data provider you will be using, other fields may be required - we'll cover those in detail in each provider's specific documentation.
A successful dataset creation request will return a 200 HTTP code, and the dataset details as stored on the RW API. PAy
special attention to the id
or the slug
, as those will allow you
to access your dataset later.
There's one aspect of the dataset creation process that you need to keep in mind: it is an asynchronous process.This
means that a successful call to the create dataset endpoint will start the process, but the dataset may not be
immediately available to be used. The status
field will tell you if the dataset creation process is in progress (
status set to pending
), if something went wrong (failed
, in which case the errorMessage
field will have a short
description of what went wrong) or if the dataset is available to be used (when status is saved
). The amount of time
it takes for a newly created dataset to go from pending
to saved
depends on the provider and amount of data. Just
keep in mind that you need to wait for the status to be set to saved
before starting to use your datasets. You
should check your dataset manually to see when the status
is
updated.
Errors for creating a dataset
Error code | Error message | Description |
---|---|---|
400 | <field> : <field> can not be empty |
Your are missing a required field value. |
400 | <field> : empty or invalid <field> |
The provided value for <field> is invalid. This is usually happens if an invalid value type is provided, but certain fields use more advanced validation rules, that may produce this error message if validation fails (ie: on a carto dataset, the connectorUrl must contain a valid carto URL). |
400 | provider: must be valid |
Your provider value is invalid. The <list of valid providers> will contain the list of providers that are supported for the connectorType you specified. |
401 | Unauthorized | You are not authenticated. If creating a BigQuery dataset, you may also see this message even if you are authenticated. Refer to the BigQuery documentation for more details. |
403 | Forbidden - User does not have access to this dataset's application | You are trying to create a dataset with one or more application values that are not associated with your user account. |
Carto datasets
Example of creating a dataset based on CartoDB data with the minimum fields required
curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"dataset": {
"name":"World Database on Protected Areas -- Global",
"connectorType":"rest",
"provider":"cartodb",
"connectorUrl":"https://wri-01.carto.com/tables/wdpa_protected_areas/table",
"application":[
"gfw",
"forest-atlas"
]
}
}'
To create a dataset connected to a Carto data source, besides the common required fields, you must provide the following required data:
Field | Description | Example value |
---|---|---|
connectorType |
The type of connector. Must be set to rest . |
rest |
provider |
The provider should be set to cartodb . |
cartodb |
connectorUrl |
The URL for the CartoDB table that this dataset will be using. | https://wri-01.carto.com/tables/wdpa_protected_areas/table |
The RW API will use the information above to directly query the Carto account specified on the connectorUrl
field
whenever this dataset is accessed on the RW API. This has a few implications that you should be aware of:
- The Carto URL provided will be publicly visible to all RW API users.
- The Carto account will see increased traffic.
- Any changes made to the data hosted on Carto will be automatically reflected on the data served by the RW API for this dataset.
- If you restructure or delete your Carto table, the corresponding RW API dataset will be in an invalid state, and you should delete it.
The tableName
value of a carto-based dataset will automatically be filled with the name of the carto table
corresponding to the dataset.
When creating a Carto based-dataset, the RW API will try to validate the connectorUrl
by trying to connect to the
corresponding Carto table - the result of this will determine if the dataset's status will be set to saved
or error
.
GFW datasets
Example of creating a dataset based on GFW data with the minimum fields required
curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"dataset": {
"name":"RADD Deforestation Alerts",
"connectorType":"rest",
"provider":"gfw",
"connectorUrl":"https://data-api.globalforestwatch.org/dataset/wur_radd_alerts/latest",
"application":[
"gfw",
"rw"
]
}
}'
To create a dataset connected to a GFW data source, besides the common required fields, you must provide the following required data:
Field | Description | Example value |
---|---|---|
connectorType |
The type of connector. Must be set to rest . |
rest |
provider |
The provider should be set to gfw . |
gfw |
connectorUrl |
The URL for the GFW table or file that this dataset will be using. | https://data-api.globalforestwatch.org/dataset/wur_radd_alerts/latest |
The RW API will use the information above to directly query the GFW dataset specified on the connectorUrl
field whenever this dataset is accessed on the RW API. This has a few implications that you should be aware of:
- The GFW URL provided will be publicly visible to all RW API users.
- The GFW REST API will see increased traffic.
- Any changes made to the data hosted on GFW will be automatically reflected on the data served by the RW API for this dataset.
- If you restructure or delete your GFW table or raster file, the corresponding RW API dataset will be in an invalid state, and you should delete it.
The tableName
value of a GFW-based dataset will automatically be filled with the name of the
GFW table or raster file corresponding to the dataset.
The latest
path parameter in connectionUrl
requests the most recent public version of
the requested dataset in GFW. Alternatively, you may request a dataset by the version number
if known.
When creating a GFW-based dataset, the RW API will try to validate the connectorUrl
by trying to connect to the corresponding GFW table or raster file - the result of this will determine if the dataset's status will be set to saved
or error
.
ArcGIS feature layer
Example of creating a dataset based on ArcGIS feature layer data with the minimum fields required
curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"dataset": {
"connectorType":"rest",
"provider":"featureservice",
"connectorUrl":"https://services.arcgis.com/uDTUpUPbk8X8mXwl/arcgis/rest/services/Public_Schools_in_Onondaga_County/FeatureServer/0?f=json",
"application":[
"prep"
],
"name":"Uncontrolled Public-Use Airports -- U.S."
}
}'
To create a dataset using ArcGIS feature layer as data source, besides the common required fields, you must provide the following required data:
Field | Description | Example value |
---|---|---|
connectorType |
The type of connector. Must be set to rest . |
rest |
provider |
The provider should be set to featureservice . |
featureservice |
connectorUrl |
The URL for the JSON data in ArcGIS services this dataset will be using. | https://services.arcgis.com/uuid/arcgis/rest/services/example/FeatureServer/0?f=json |
The RW API will use the information above to directly query the ArcGIS feature layer server specified on
the connectorUrl
field whenever this dataset is accessed on the RW API. This has a few implications that you should be
aware of:
- The ArcGIS feature layer URL provided will be publicly visible to all RW API users.
- The ArcGIS feature layer server will see increased traffic.
- Any changes made to the data hosted on ArcGIS feature layer will be automatically reflected on the data served by the RW API for this dataset.
- If you restructure or delete your ArcGIS feature layer dataset, the corresponding RW API dataset will be in an invalid state, and you should delete it.
The tableName
value of a ArcGIS-based dataset will automatically be filled with the name of the ArcGIS feature layer
table corresponding to the dataset.
When creating a ArcGIS-based dataset, the RW API will try to validate the connectorUrl
by trying to connect to the
corresponding ArcGIS Feature Layer - the result of this will determine if the dataset's status will be set to saved
or error
.
Google Earth Engine
Example of creating a dataset based on Google Earth Engine data with the minimum fields required
curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"dataset": {
"connectorType":"rest",
"provider":"gee",
"tableName": "JRC/GSW1_0/GlobalSurfaceWater"
"application":[
"rw"
],
"name":"Water occurrence"
}
}'
To create a dataset using Google Earth Engine (GEE) as data source, besides the common required fields, you must provide the following required data:
Field | Description | Example value |
---|---|---|
connectorType |
The type of connector. Must be set to rest . |
rest |
provider |
The provider should be set to gee . |
gee |
tableName |
Relative path of the dataset within GEE. | users/resourcewatch_wri/dataset_name |
The RW API will use the information above to directly query the GEE dataset specified on the tableName
field whenever
this dataset is accessed on the RW API. This has a few implications that you should be aware of:
- The GEE resource name provided will be publicly visible to all RW API users.
- Any changes made to the data hosted on GEE will be automatically reflected on the data served by the RW API for this dataset.
- If you restructure or delete your GEE dataset, the corresponding RW API dataset will be in an invalid state, and you should delete it.
When creating a GEE-based dataset, the RW API will try to validate it by connecting to the corresponding dataset GEE -
the result of this will determine if the dataset's status will be set to saved
or error
.
WMS
Example of creating a dataset based on WMS data with the minimum fields required
curl -X POST 'https://api.resourcewatch.org/v1/dataset' -d \
-H 'Authorization: Bearer <your-token>' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' -d \
'{
"dataset": {
"application": [
"rw"
],
"name": "Seasonal variability",
"connectorType": "wms",
"provider":"wms",
"connectorUrl":"https://gis-gfw.wri.org/arcgis/rest/services/prep/nex_gddp_indicators/MapServer/6?f=pjson"
}
}
'
To create a dataset using WMS as data source, you should provide the following data:
Field | Description | Example value |
---|---|---|
connectorType |
The type of connector. Must be set to wms . |
wms |
provider |
The provider should be set to wms . |
wms |
connectorUrl |
URL of the server hosting the data in WMS format. | https://maps.heigit.org/osm-wms/service?request=GetCapabilities&service=WMS |
The RW API will use the information above to directly query the WMS dataset specified on the connectorUrl
field
whenever this dataset is accessed on the RW API. This has a few implications that you should be aware of:
- The WMS server URL provided will be publicly visible to all RW API users.
- Any changes made to the data hosted on the WMS server data will be automatically reflected on the data served by the RW API for this dataset.
- If you restructure or delete your WMS server data, the corresponding RW API dataset will be in an invalid state, and you should delete it.
When creating a WMS-based dataset, no validation is done - the dataset is automatically created in a saved
state.
Document based datasets: JSON, CSV, TSV or XML
Creating a CSV dataset with data provided by externally hosted files:
curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"dataset": {
"connectorType":"document",
"provider":"csv",
"sources": [
"https://gfw2-data.s3.amazonaws.com/alerts-tsv/glad_headers_1.csv",
"https://gfw2-data.s3.amazonaws.com/alerts-tsv/glad_headers_2.csv",
"https://gfw2-data.s3.amazonaws.com/alerts-tsv/glad_headers_3.csv"
],
"application":[
"gfw"
],
"name":"Glad points"
}
}'
Creating a JSON dataset with data provided on the request body:
curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"dataset": {
"connectorType":"document",
"provider":"json",
"application":[
"your", "apps"
],
"data": {"myData":[
{"name":"nameOne", "id":"random1"},
{"name":"nameTow", "id":"random2"}
]},
"name":"Example JSON Dataset"
}
}'
This dataset hosts data from files in JSON, CSV, TSV or XML format.
Here's a breakdown of the fields you need to specify when creating a document type dataset, besides the common required fields:
Field | Description | Example value |
---|---|---|
connectorType |
The type of connector. Must be set to document . |
document |
provider |
The type of data you are uploading. Must be one of the following: csv , tsv , json or xml . |
csv , tsv , json or xml |
connectorUrl |
URL from which to source data. | https://gis-gfw.wri.org/arcgis/rest/services/prep/nex_gddp_indicators/MapServer/6?f=pjson |
sources |
List of URLs from which to source data. | ['https://gis-gfw.wri.org/arcgis/rest/services/prep/nex_gddp_indicators/MapServer/6?f=pjson','https://gis-gfw.wri.org/arcgis/rest/services/prep/nex_gddp_indicators/MapServer/7?f=pjson'] |
data |
JSON DATA only for json connector if connectorUrl not present. | [{"key":"value1"},{"key":"value2"}]] |
When creating a document based dataset, you have multiple ways of providing your data to the API, of which you should use only one:
- The
sources
field expects a list of URL containing files in the format matching yourprovider
value. This is the recommended way of uploading data. - The
connectorUrl
field is similar tosources
, but it only accepts a single value. Deprecation notice: The previously usedconnectorUrl
field should be considered deprecated when creating document-based datasets. - If creating a dataset based on JSON data, you can upload the data on the actual request you issue to the API, inside
the
data
field.
The data passed in sources
or connectorUrl
must be available on a publicly accessible URLs, specified in
the sources
array field or the connectorUrl
single value field. The URLs must be an accessible CSV, TSV or XML file,
non-compressed - zip, tar, tar.gz, etc are not supported. sources
allows you to specify multiple URLs for a single
dataset, provided all files have the same format and data structure. This is particularly useful when creating very
large datasets, as it will allow the creation process to be parallelized. No warranties are provided about the order in
which the files or their parts are imported.
Notice: If you want to create a dataset from a file you have, but that it's not available on a public URL, check out our docs for uploading a dataset.
Unlike with other dataset types, when the dataset is created, the data is copied from the provided source into the API's internal Elasticsearch instance, which is the source used for subsequent queries or other operations. This has a few implications that you should be aware of:
- The URLs provided in
sources
orconnectorUrl
will be publicly visible to all RW API users. - On dataset creation, those URLs will be visited as the API loads and copies your data.
- Queries to the dataset will use the API's internal copy of your data. If you wish to update that data, see the documentation below on how to update your data.
- If the URLs provided become unavailable after the creation process is over, the dataset will continue to work normally
- your data will still be available online.
Notice: When creating a document-based dataset, if any of the fields has a numerical name (for example, column: 3
), a
string named col_
will be appended to the beginning of the name of the column. This way, an uploaded column named 3
will become col_3
.
Tip: If you want to periodically and automatically update your document based dataset with new data, check out the dataset automatic synchronization functionality.
When creating a document-based dataset, the RW API will start a complex process that copies your data into the API's
internal database, and perform certain indexing actions. This process is called a Task, and is given a taskId
that
is stored on the dataset's field with the same name. Depending on the size of your dataset, this may take from a few
seconds to a few hours to complete. The result of this import process will determine if the dataset's status will be set
to saved
or error
. You can follow this process by using the taskId
value with
the Tasks API.
Using the legend fields to define field types
By default, when creating a document based dataset, the data is ingested by the API and the field types are automatically determined by the underlying Elasticsearch dynamic mapping API . However, in some scenarios, it may be desirable to specify some or all of these mappings manually, to match each field type to its Elasticsearch equivalent.
When defining manual mappings, you don't need to map every single field. When processing the data, if a field is found
for which there isn't a manual mapping, Elasticsearch will fallback to its dynamic mapping algorithm to try and guess
that field's type. This API only supports a single explicit mapping per field, meaning you cannot declare a given field
as both text
and keyword
for example.
Field mapping can only be defined on dataset creation. Should you want to change these mappings, you can only do so by creating a new dataset with the new mapping structure.
The legend
field allows explicitly identifying the following mappings:
Mapping | Notes |
---|---|
lat | If lat and long are both provided, a the_geom mapping is added |
long | If lat and long are both provided, a the_geom mapping is added |
date | Name of columns with date values (ISO Format) |
country | Name of columns with country values (ISO3 code) |
region | Name of columns with region values (ISO3 code) |
nested | Nested objects need to be explicitly identified in order to be indexed. |
integer | In beta, not fully supported |
short | In beta, not fully supported |
byte | In beta, not fully supported |
double | In beta, not fully supported |
float | In beta, not fully supported |
half_float | In beta, not fully supported |
scaled_float | In beta, not fully supported |
boolean | In beta, not fully supported |
binary | In beta, not fully supported |
text | In beta, not fully supported |
keyword | In beta, not fully supported |
For more details on the characteristics of each of the basic data types, refer to the Elasticsearch documentation .
Uploading a dataset file
Upload raw data for using in a dataset
curl -X POST https://api.resourcewatch.org/v1/dataset/upload \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-F provider=csv,
-F dataset=@<your-file>
Example response
{
"connectorUrl": "rw.dataset.raw/some-file.csv",
"fields": [
"Country (region)",
"Positive affect",
"Negative affect",
"Social support",
"Freedom",
"Corruption",
"Generosity"
]
}
Using the returned connectorUrl to create a new dataset
curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
'{
"dataset": {
"connectorType":"document",
"provider":"csv",
"connectorUrl":"rw.dataset.raw/some-file.csv",
"application":[
"your", "apps"
],
"name":"Example RAW Data Dataset"
}
}'
The upload
endpoint allows you to create datasets on the API from local files that aren't available online.
If your file is up to 4MB in size, you can upload it to the API by using the upload
endpoint.
This endpoint accepts a file in the "dataset" field of your POST request, and a provider
that matches your file type
and extension.
The supported formats/extensions are: csv, json, tsv, xml, tif, tiff and geo.tiff.
The request uploads the file to the API, and returns a specially crafted connectorUrl
value, and a list of fields
found in your file.
With this data, you can create a document type dataset by passing it to the connectorUrl
value of
a new document type dataset.
Errors for upload a dataset file
Error code | Error message | Description |
---|---|---|
400 | - no file to check - | A file was not provided, or was provided in the wrong request field. |
400 | - dataset: file dataset can not be a empty file - | A file was not provided, or was provided in the wrong request field. |
400 | provider: provider must be in [csv,json,tsv,xml,tif,tiff,geo.tiff]. | A file was not provided, or was provided in the wrong request field. |
400 | - dataset: file too large - | Your file is larger than 4MB. |
400 | - dataset: file |
The provider value must match the extension of the uploaded file. |
401 | Unauthorized | You need to be logged in to be able to upload a file. |
Updating a dataset
There are multiple options to update a dataset, depending on what modification you are trying to achieve, and the underlying data provider of the dataset itself. This section covers the different endpoints that allow you to modify a dataset, their details, and helps you pick the option that best fits your scenario. We recommend reviewing all of them before proceeding, so you can find the endpoint that best matches your needs.
Updating the fields of a dataset
Example request for updating the name of a dataset
curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id-or-slug> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": "Another name for the dataset"
}'
In order to modify the fields of a dataset, you can use the patch dataset endpoint.
This endpoint allows you to modify most of your dataset's details, like the name or publishing status, but can also be
used to modify internal fields of a dataset, like connectorType
.
When making these changes, be mindful that some of these fields are critical to the correct behavior of the dataset, and
providing incorrect values may break your dataset.
There are other endpoints documented in this page that allow you to perform certain update-like operations (ie. update
data on a document-type dataset), so refer to those first before using this endpoint.
Also important to keep in mind is the fact that this endpoint does not perform validation on things like connectorUrl
/sources
URLs.
All the fields in the dataset reference can be modified, except the following:
slug
userId
createdAt
updatedAt
Additionally, certain fields have special behavior associated with them:
status
can only be modified by users withADMIN
role or by other microservices.taskId
anderrorMessage
can only be modified by other microservices.published
can only be modified by users withADMIN
role.env
changes will not only affect the dataset, but also related widgets and layers. Refer to the PATCH/widget/change-environment/<dataset id>/<env>
and the the PATCH/layer/change-environment/<dataset id>/<env>
endpoints respectively for more details.
When passing new values for Object type fields, the new value will fully overwrite the previous one. It's up to you, as an API user, to build any merging logic into your application.
To perform this operation, the following conditions must be met:
- the user must be logged in and belong to the same application as the dataset
- the user must comply with the RW API role-based access control guidelines.
Use this endpoint when:
- Modifying the fields of a dataset, like name, and not the data itself.
- Modifying the source of data for any dataset that's not document based (
connectorType
values other thandocument
). - Making advanced changes to a dataset.
Errors for updating the fields of a dataset
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to update a dataset. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the dataset's owner (through the userId field of the dataset). |
403 | Forbidden | You are trying to update a dataset with one or more application values that are not associated with your user account. |
404 | Dataset with id |
A dataset with the provided id does not exist. |
Concatenate and append data to a document based dataset
Concatenate data using external data source:
curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset_id/concat \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"provider": "json",
"sources": ["<csv1Url>", "<csv2Url>", "<csv3Url>"],
"dataPath": "data... etc"
}'
Append data using external data source:
curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset_id/append \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"provider": "json",
"sources": ["<csvUrl>"],
"dataPath": "data... etc"
}'
Concatenate data using JSON array in post body:
curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset_id/concat \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"provider": "json",
"data": [{},{}]
}'
Using these endpoints, you can add more data to an already existing dataset. They are exclusively available for document
based datasets - you'll get a 404
error if you use them on a dataset of a different type. You can either provide the
URL for the file containing the data you wish to add, or simply provide that data in the body of your request, as a JSON
object.
These process are asynchronous and not instantaneous. Immediately when triggered, these requests will cause the
dataset's status
to be set to pending
, meaning you will not be able to issue new overwrite, concatenate or append
requests. Once the request has been fully processed, the status will be automatically set to saved
. Depending on
factors like API load or the size of the data being uploaded, this may take from a few minutes to a few hours to occur.
The API does not issue any notification when the asynchronous operation is finished.
In order to perform these operation, the following conditions must be met:
- the dataset's
overwrite
property must be set totrue
. - the dataset's
status
property must be set tosaved
. - the user must comply with the RW API role-based access control guidelines.
- the user must have at least one overlapping application with the ones associated with the dataset.
While they ultimately achieve a very similar end result, concatenate and append rely on different internal processes, each with its own characteristics.
- The concatenate process relies on a slower approach to ensure the operation is atomic. Until the operation is completed, you will see the dataset data as it was before the concatenate operation was triggered. If the operation fails, the old version of the data is kept accessible as it was before the concatenation process was started. There's a known issue where concatenating new data to already existing large datasets may result in failure.
- The append operation relies on a faster process that does not offer atomicity. The new data is simply added to the current dataset, and any queries done while this process is taking place may produce results based on the preexisting data mixed with parts of the newly added values. Should the operation fail halfway, your dataset may contain all the preexisting records as well as part (but not all) of the newly added ones.
Here's a more detailed description of the request's body fields:
Field | Description | Type | Values | Required |
---|---|---|---|---|
provider | Dataset provider this include inner connectors and 3rd party ones | String | A valid dataset provider | Yes |
sources | List of URLs from which to source data | Array | URL array | Yes, unless JSON data is provided using the data field |
data | JSON DATA only for json connector if connectorUrl not present | Array | [{},{},{}] | Yes for JSON if sources is not present |
dataPath | Path to the data in a JSON file-based datasets | String | '' | No |
Tip: If you want to periodically and automatically concatenate data to your document based dataset, check out the dataset automatic synchronization functionality.
Use this endpoint when:
- Adding new data to an existing document based dataset, without modifying/removing the existing one.
Errors for concatenating and appending data to a document based dataset
Error code | Error message | Description |
---|---|---|
401 | Dataset is not in saved status | The dataset's status value is not set to saved . Refer to dataset reference for more details on this field and its values. |
401 | Unauthorized | You need to be logged in to be able to update a dataset. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the dataset's owner (through the userId field of the dataset). |
403 | Forbidden | You are trying to update a dataset with one or more application values that are not associated with your user account. |
404 | Endpoint not found | A dataset with the provided id does not exist, or does not have connectorType with value document . |
409 | Dataset locked. Overwrite false. | The dataset you're trying to modify has overwrite value set to false , to explicitly prevent data modifications. |
Overwrite data for a document based dataset
Overwrite data using external data source:
curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset_id/data-overwrite \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"sources": ["<url of the data source>"],
"provider": "csv"
}'
Overwrite data using JSON array in post body:
curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset_id/data-overwrite \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"data": [{},{}],
"provider": "csv"
}'
Using this endpoint, you can add or completely replace the data of an already existing dataset.
It's exclusively available for document based datasets - you'll get a 404
error if you use it on a dataset of a
different type.
All previously existing data will be permanently deleted.
You can either provide the URL(s) for the file(s) containing the data you wish to add, or simply provide that data in
the body of your request, as a JSON object.
There are no requirements regarding similarity of the data structure between existing and new data - your overwrite data
can have a completely different data schema.
This process is asynchronous and not instantaneous. Immediately when triggered, this request will cause the
dataset's status
to be set to pending
, meaning you will not be able to issue new overwrite or concat requests, and
will not yet be able to access the new data yet. Once the request has been fully processed, the status will be
automatically set to saved
and the new data will be accessible. Depending on factors like API load or the size of the
data being uploaded, this may take from a few minutes to a few hours to occur. The API does not issue any notification
when the asynchronous operation is finished.
In order to perform this operation, the following conditions must be met:
- the dataset's
overwrite
property must be set totrue
. - the dataset's
status
property must be set tosaved
. - the user must comply with the RW API role-based access control guidelines.
- the user must have at least one overlapping application with the ones associated with the dataset.
Here's a more detailed description of the request's body fields:
Field | Description | Type | Values | Required |
---|---|---|---|---|
provider | Dataset provider this include inner connectors and 3rd party ones | String | A valid dataset provider | Yes |
sources | List of URLs from which to source data | Array | URL array | Yes, unless JSON data is provided using the data field |
data | JSON DATA only for json connector if connectorUrl not present | Array | [{},{},{}] | Yes for JSON if sources is not present |
legend | The schema of the new data. If none is provided, a guessing mechanism will be used. The existing legend value of the dataset will be ignored and overwritten in all overwrite operations. See the legend section above for more details. |
Object | No |
Tip: If you want to periodically and automatically overwrite the data on your document based dataset, check out the dataset automatic synchronization functionality.
Errors for overwriting data for a document based dataset
Error code | Error message | Description |
---|---|---|
401 | Dataset is not in saved status | The dataset's status value is not set to saved . Refer to dataset reference for more details on this field and its values. |
401 | Unauthorized | You need to be logged in to be able to update a dataset. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the dataset's owner (through the userId field of the dataset). |
403 | Forbidden | You are trying to update a dataset with one or more application values that are not associated with your user account. |
404 | Endpoint not found | A dataset with the provided id does not exist, or does not have connectorType with value document . |
409 | Dataset locked. Overwrite false. | The dataset you're trying to modify has overwrite value set to false , to explicitly prevent data modifications. |
Use this endpoint when:
- Fully replacing the data of an existing document based dataset, while keeping other values like id or name.
- Modifying the structure of the data for a document based dataset.
Cloning a dataset
Example request for cloning a dataset
curl -X POST https://api.resourcewatch.org/v1/dataset/5306fd54-df71-4e20-8b34-2ff464ab28be/clone \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
-H "Content-Type: application/json" -d \
'{
"dataset": {
"datasetUrl": "/query/5306fd54-df71-4e20-8b34-2ff464ab28be?sql=select%20%2A%20from%20data%20limit%2010",
"application": [
"your",
"apps"
],
"legend": {...},
"applicationConfig" : {...}
}
}'
This endpoint allows you to create a new, json based dataset, from the result of a RW API endpoint call. The basic usage
example would be to create a new dataset based on a custom query to an existing dataset - this is illustrated in the
example curl
call in this section. Other use cases could be converting the result of an analysis endpoint into a
dataset, or capturing the result of a query to a REST based dataset (cartodb, arcgis, etc) to an internal json
representation of the same data, that is kept in the API database.
In order to perform this operation, the following conditions must be met:
- the user must belong to the applications specified in the request body.
- the user must comply with the RW API role-based access control guidelines.
The request requires two fields to be present:
datasetUrl
: the URL from where to load the data to populate the new dataset. Must be RW API, relative path, like/query/5306fd54-df71-4e20-8b34-2ff464ab28be?sql=select%20%2A%20from%20data%20limit%2010
.application
: the array of applications to which the new dataset will belong.
Additionally, you can optionally specify these fields:
legend
: field structure and type of the new dataset. Refer to dataset reference for more details.applicationConfig
: application-specific configuration. Refer to dataset reference for more details. If not provided, it will be copied from the original dataset.published
: if the user hasADMIN
role, they can set this value totrue
.
For the fields in the following list, values will be copied from the original dataset to the new one, unless specified:
name
: copied from the original dataset, with a timestamp appended, to ensure uniqueness.subtitle
dataPath
: will always be set todata
, matching the expected response structure of RW API responses like/query
that encapsulate the "real" data in adata
json object.connectorType
: will be set todocument
provider
: will be set tojson
attributesPath
tableName
dataLastUpdated
overwrite
published
: if the user has roleADMIN
and does not explicitly setpublished
totrue
on the request body, this value is inherited. Otherwise, it's set tofalse
.
Datasets created through a cloning operation will have a specific clonedHost
object, with additional data. Refer
to dataset reference for more details on the content of this field.
The dataset cloning requests accepts an optional full
boolean query parameter that, when set to true
, will clone of
vocabulary-related data and metadata from the original dataset to the new one.
Errors for cloning a dataset
Error code | Error message | Description |
---|---|---|
400 | The required field identified in the error message is missing in the request body. | |
400 | - application: must be a non-empty array - | application must be specified as an array. |
401 | Unauthorized | You need to be logged in to be able to clone a dataset. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the dataset's owner (through the userId field of the dataset). |
403 | Forbidden - User does not have access to this dataset's application | You specified an application in your request body that is not associated with your user account. |
404 | Dataset with id |
A dataset with the provided id does not exist. |
Deleting a dataset
Example request for deleting a dataset
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
-H "Content-Type: application/json"
Use this endpoint if you wish to delete a dataset. Deleting a dataset of type document (connectorType
with
value document
) will cause the API's internal copy of said data to be deleted. Dataset types that proxy data from an
external source (ie. carto, gee, etc) will be deleted without modifying said external source.
When deleting a dataset that is associated with multiple application
values, the user issuing the request must be
associated with all of them in order for the dataset to be deleted. If that's not the case, the application
values
associated with the user will be removed from the dataset's application
list, and no further action will be taken -
the dataset itself and its associated resources will continue to exist. The dataset is only actually deleted if the user
has access to all of the application
to which the dataset belongs.
Besides deleting the dataset itself, this endpoint also deletes graph vocabularies, layers, widgets and metadata related to the dataset itself. These delete operations are issued in this order, and prior to deleting the dataset itself, but are not atomic - if one of them fails (for example, if attempting to delete a protected resource), the following ones are canceled, but the already deleted elements are not restored.
In order to delete a dataset, the following conditions must be met:
- the dataset's
protected
property must be set tofalse
. - the user must be logged in and belong to the same application as the dataset
- the user must comply with the RW API role-based access control guidelines.
Errors for deleting a dataset
Error code | Error message | Description |
---|---|---|
400 | Dataset is protected | You are attempting to delete a dataset that has protected set to prevent deletion. |
401 | Unauthorized | You need to be logged in to be able to delete a dataset. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the dataset's owner (through the userId field of the dataset) |
403 | Forbidden | You are trying to delete a dataset with one or more application values that are not associated with your user account. |
404 | Dataset with id |
A dataset with the provided id does not exist. |
Deleting datasets by user id
Example request for deleting datasets by user id
curl -X DELETE https://api.resourcewatch.org/v1/dataset/by-user/<user-id> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
-H "Content-Type: application/json"
Example response:
{
"deletedDatasets": [
{
"id": "aef2be42-1ee8-4069-a55a-16a988f2b7a0",
"type": "dataset",
"attributes": {
"name": "Glad points",
"slug": "Glad-points-1490086842129",
"type": null,
"subtitle": null,
"application": [
"data4sdgs"
],
"dataPath": null,
"attributesPath": null,
"connectorType": "document",
"provider": "csv",
"userId": "58333dcfd9f39b189ca44c75",
"connectorUrl": "https://gfw2-data.s3.amazonaws.com/alerts-tsv/glad_headers.csv",
"sources": [],
"tableName": "data",
"status": "pending",
"published": true,
"protected": false,
"overwrite": false,
"env": "production",
"geoInfo": false,
"legend": {
"date": [],
"region": [],
"country": []
},
"clonedHost": {},
"errorMessage": null,
"updatedAt": "2017-01-13T10:45:46.368Z",
"widgetRelevantProps": [],
"layerRelevantProps": []
}
}
],
"protectedDatasets": [
{
"id": "00f2be42-1ee8-4069-a55a-16a988f2b762",
"type": "dataset",
"attributes": {
"name": "Fires data",
"slug": "fires-data-1490086842163",
"type": null,
"subtitle": null,
"application": [
"data4sdgs"
],
"dataPath": null,
"attributesPath": null,
"connectorType": "document",
"provider": "csv",
"userId": "58333dcfd9f39b189ca44c75",
"connectorUrl": "https://gfw2-data.s3.amazonaws.com/alerts-tsv/fires.csv",
"sources": [],
"tableName": "data",
"status": "pending",
"published": true,
"protected": true,
"overwrite": false,
"env": "production",
"geoInfo": false,
"legend": {
"date": [],
"region": [],
"country": []
},
"clonedHost": {},
"errorMessage": null,
"updatedAt": "2017-01-13T10:45:46.368Z",
"widgetRelevantProps": [],
"layerRelevantProps": []
}
}
]
}
Use this endpoint if you wish to delete all datasets associated with a user. Deleting datasets of type document (connectorType
with
value document
) will cause the API's internal copy of said data to be deleted. Dataset types that proxy data from an
external source (ie. carto, gee, etc) will be deleted without modifying said external source.
Unlike what happens when deleting a single dataset by id, deleting all datasets for a user does not validate if the datasets
belong to different applications
and prevents their actual deletion based on that - datasets will be deleted even if they
are part of applications
that the user is not associated with.
Besides deleting the datasets themselves, this endpoint also deletes graph vocabularies, layers, widgets and metadata related with the datasets themselves. For each dataset, these delete operations are issued in this order, and prior to deleting the dataset itself, but are not atomic - if one of them fails, the following ones are canceled, but the already deleted elements are not restored. Any other datasets associated with the given user may or may not be deleted, as the operation occurs internally in an asynchronous fashion.
Any microservice or user with ADMIN role can use this endpoint. Regular users can use this endpoint to delete the datasets they own.
The response includes two lists of datasets:
- deletedDatasets
: an unpaginated list of all datasets that were deleted as part of this operation.
- protectedDatasets
: an unpaginated list of all datasets associated with the provided user, that have protected
status set to true
,
and thus were not deleted.
Errors for deleting datasets by user id
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to delete datasets. |
403 | Forbidden | You are trying to delete the datasets of an user that is not the same logged user, not an ADMIN user or a microservice |
Dataset automatic synchronization
curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
'{
"connectorType":"document",
"provider":"csv",
"connectorUrl":"<csvUrl>",
"application":[
"your", "apps"
],
"name":"Example SYNC Dataset",
"overwrite": true,
"sync": {
"action":"concat",
"cronPattern":"0 * * * * *",
"url":"<updateCsvUrl>"
}
}'
Certain datasets contain data that evolves frequently over time, and you, as the creator of this dataset, what to ensure that it's up-to-date. As we've seen before, if your data is hosted on one of the supported 3rd party data providers, like Carto or Arcgis, your data will be proxied, so users of the RW API will always see the latest version of your data. However, if you uploaded your data from a file, your data is copied to the RW API database at the time of the dataset's creation, so keeping it up-to-date requires a different approach. It's with scenario in mind that the RW API offers the automatic synchronization mechanism.
The automatic synchronization mechanism is available for document based datasets only, and you can configure it when creating or updating a dataset. When enabled, it will schedule an automatic, periodic task, that will update your document based dataset's data, based on data from an URL you provide. This means that, once configured, you just have to make sure the automatic synchronization mechanism can find the newest version of the data at the specified URL, and the RW API will take care of the actual data update process for you.
To configure automatic synchronization on dataset creation or update, you need to pass a sync
object on your calls to
the respective endpoints, next to the other fields. See the included example for a clearer idea of how creating a
dataset with automatic synchronization looks like.
There are 3 fields, all required, that you need to specify inside the sync
object:
action
: choose eitherconcat
oroverwrite
. See more details above about concatenating and overwriting dataset data. Append operations, as documented in the section above, is not supported.cronPattern
: cron expression representing when and how frequently the synchronization process should take place. The host executing these tasks use UTC timezone.url
: publicly available URL from where the automatic synchronization mechanism will load the data to replace/concatenate to your dataset.
Internally, the automatic synchronization mechanism will call either
the dataset concatenation
or dataset overwrite endpoint.
If that internal request fails - for example, if overwrite
is set to false
- the sync process will fail silently.
If you have the ADMIN
role, you can use the /v1/task
endpoint to see scheduled tasks and their error output, but
otherwise this failure will be invisible to end users.
On the other hand, if the request goes through, but the concatenation/overwrite process fails - for example, if the URL
provided is not available - then your dataset status
will be set to error
and the errorMessage
field will give you
a simple description of what happened.
To see the details (including the date) of the last operation performed on the dataset, use the link in the taskId
field.
Flush dataset cache
Flush dataset's cache
curl -X POST https://api.resourcewatch.org/v1/dataset/0c630feb-8146-4fcc-a9be-be5adcb731c8/flush \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Response:
OK
Flushes the cache for the specified dataset. Take into account that only the dataset itself, query results and fields will be flushed. Any other relation, like metadata, layers or widgets linked to the specified dataset will not be affected by this action.
In order to flush a dataset's cache, the following conditions must be met:
- the user must be logged in.
- the user must comply with the RW API role-based access control guidelines.
Errors for flushing a dataset's cache
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to delete a dataset. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the dataset's owner (through the userId field of the dataset) |
403 | Forbidden | You are trying to delete a dataset with one or more application values that are not associated with your user account. |
404 | Dataset with id |
A dataset with the provided id does not exist. |
Recover
Recover dataset
curl -X POST https://api.resourcewatch.org/v1/0c630feb-8146-4fcc-a9be-be5adcb731c8/recover \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Response:
OK
Resets a dataset's status
to saved
and clears its errors. Keep in mind that this does NOT modify the dataset in any
other way - if the underling dataset's data was inconsistent for any reason, this endpoint will not change it, and it's
up to you to fix it using a data-overwrite
or other endpoints.
In order to recover a dataset, the user must be logged in and have the ADMIN
role.
Errors for recovering a dataset
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged with to be able to delete a dataset. |
403 | Forbidden | You need to have the ADMIN role. |
404 | Dataset with id |
A dataset with the provided id does not exist. |
Dataset reference
This section gives you a complete view at the properties that are maintained as part of dataset. When interacting with a
dataset (on get, on create, etc) you will find most of these properties available to you, although they may be organized
in a slightly different structure (ie: on get, everything but the id
is nested inside an attributes
object).
You can find more details in the source code.
Field name | Type | Required | Default value | Description |
---|---|---|---|---|
id | String | Yes (autogenerated) | Unique Id of the dataset. Auto generated on creation. Cannot be modified by users. | |
name | String | Yes | Name of the dataset. | |
slug | String | Yes (autogenerated) | Slug of the dataset. Auto generated on creation. Cannot be modified by users. | |
type | String | No | null | Type of the dataset. |
subtitle | String | No | null | Subtitle of the dataset. |
application | Array | Yes | Applications associated with this dataset. Read more about this field here. | |
applicationConfig | Object | No | Key-value storage of application-specific data. Use the application value as key and a JSON Object as the value to store complex, extensible data. |
|
dataPath | String | No | null | Path to the data in a JSON file-based datasets. |
attributesPath | String | No | null | |
connectorType | String | Yes | Type of connector. wms for WMS-based datasets, rest for datasets that rely on external data sources (carto, arcgis, etc) or document for file-based datasets (JSON, CSV, etc). |
|
provider | String | Yes | Dataset provider. | |
userId | String | Yes (autopopulated) | Id of the user who created the dataset. Set automatically on creation. Cannot be modified by users. | |
connectorUrl | String | No | null | Path to the source of the data. On datasets with document connectorType, sources should be used instead. |
sources | Array | No | null | Path to the source files of the data. Only used on datasets with document connectorType. |
tableName | String | No | null | Additional value used to locate the dataset within a given underlying provider. Refer to the documentation of the different connector for more details. |
status | String | No | pending | Status of the dataset. saved means the dataset is available to use, pending means an operation is ongoing and the dataset is temporarily unavailable, error means the dataset is in an invalid state and requires further action before becoming available. |
overwrite | Boolean | No | false | If the data can be overwritten (only for being able to update dataset) |
errorMessage | String | No | null | If this dataset is in error state, this field may contain additional details about the error. |
mainDateField | String | No | null | |
published | Boolean | Yes | true | If the dataset is published or not. |
env | String | Yes | production | Environment to which the dataset belongs. Read more about this field in the Environments concept section. |
geoInfo | Boolean | Yes | false | If it contains interceptable geographical info |
protected | Boolean | Yes | false | If the dataset is protected. A protected dataset cannot be deleted. |
taskId | String | No | null | Id of the latest task associated with this dataset. Typically only present in document connectorType datasets |
subscribable | Object | No | Information about the dataset being subscribable for alerts. More info about this can be found on the Subscriptions section of the docs. | |
legend.lat | String | No | Dataset field representing a latitude value. | |
legend.long | String | No | Dataset field representing a longitude value. | |
legend.* | Array | No | Different keys corresponding to data types. Each key may have an array of strings, referencing dataset fields that match that data type. Used functionally for document-based datasets, but may also be set by the user as reference for other types. See this section for more details. | |
clonedHost.hostProvider | String | No | When cloning a dataset, this will retain the provider value of the original dataset. |
|
clonedHost.hostUrl | String | No | When cloning a dataset, this will retain the connectorUrl value of the original dataset. |
|
clonedHost.hostId | String | No | When cloning a dataset, this will retain the Id value of the original dataset. |
|
clonedHost.hostType | String | No | When cloning a dataset, this will retain the connectorType value of the original dataset. |
|
clonedHost.hostPath | String | No | When cloning a dataset, this will retain the tableName value of the original dataset. |
|
widgetRelevantProps | Array | No | Group of relevant props of a widget. | |
layerRelevantProps | Array | No | Group of relevant props of a layer. | |
dataLastUpdated | Date | No | User defined date of when a dataset was last updated. | |
userName | String | No (autogenerated) | null | Name of the user who created the dataset. This value is used only internally, and is never directly exposed through the API. Cannot be modified by users. |
userRole | String | No (autogenerated) | null | Role of the user who created the dataset. This value is used only internally, and is never directly exposed through the API. Cannot be modified by users. |
createdAt | Date | No (autogenerated) | Automatically maintained date of when the dataset was created. Cannot be modified by users. | |
updatedAt | Date | No (autogenerated) | Automatically maintained date of when the dataset was last updated. Cannot be modified by users. |
Fields
What are fields?
Fields are the properties of a dataset your will find when querying its data, use when filtering data through queries, or visualise when rendering a layer or a widget.
Fields are part of a dataset, and are determined by the structure of data provided by the dataset creator. Each field also includes information about its data type, derived automatically by the dataset provider (check out the specifics of each provider in the sections below). If you are uploading your own datasets to the RW API, you don't have to do anything else for your dataset to be available through the fields endpoints - there's no additional data you have to provide. Keep in mind the endpoints described in the sections below are read-only - if you want to change your dataset's fields, you need to upload the dataset's data again.
Fields are targeted at users consuming datasets available on the RW API, particularly if you want to build a flexible and scalable application. The fields endpoints aim at giving you a consistent and uniform view of the structure of data hosted in different dataset providers, that would otherwise be served in a heterogeneous structure.
How to get the dataset fields
Querying the fields of a dataset
curl -X GET https://api.resourcewatch.org/v1/fields/<dataset-id> \
-H "x-api-key: <your-api-key>"
Response example
{
"tableName": "public.cait_2_0_country_ghg_emissions_toplow2011",
"fields": {
"cartodb_id": {
"type": "number"
},
"the_geom": {
"type": "geometry"
},
"the_geom_webmercator": {
"type": "geometry"
},
"x": {
"type": "string"
},
"y": {
"type": "number"
},
"z": {
"type": "string"
}
}
}
Once the dataset has been created and its status is set to saved
, you will be able to use this endpoint to get details about a its fields. The resulting response contains two root fields
tableName
: a string containing the table name, as stored in the dataset object. The value and function of this field will depend on the dataset's provider, and you can refer to the dataset documentation for more details about this.fields
: a key-value pair of field names and their respective details.
While the aim of this endpoint is to provide an homogeneous view of data stored in different systems, you will still encounter slight variations in data, depending on the underlying type of the dataset you're querying. The example response on the right illustrates the typical basic response structure: tableName
with a string value, and a fields
map that matches each field's name to a type
. You'll find this structure throughout all responses, but you may also find additional details for each field, and the data types may vary in name. In the next sections we'll cover some of the specifics for each dataset type.
Carto
Example response for a Carto dataset
{
"tableName": "gadm28_adm1",
"fields": {
"cartodb_id": {
"type": "number",
"pgtype": "int4"
},
"the_geom": {
"type": "geometry",
"wkbtype": "Unknown",
"dims": 2,
"srid": 4326
},
"the_geom_webmercator": {
"type": "geometry",
"wkbtype": "Unknown",
"dims": 2,
"srid": 3857
},
"objectid": {
"type": "number",
"pgtype": "int8"
},
"iso": {
"type": "string",
"pgtype": "text"
},
"centroid": {
"type": "string",
"pgtype": "text"
},
"area_ha": {
"type": "number",
"pgtype": "float8"
},
"topojson": {
"type": "string",
"pgtype": "text"
},
"the_geom_simple": {
"type": "geometry",
"wkbtype": "Unknown",
"dims": 2,
"srid": 4326
},
"geojson": {
"type": "string",
"pgtype": "text"
}
}
}
Carto datasets provide a type
for each field, as well as additional details, depending on the field type. Most fields will have a pgtype
field, which will identify a sub-type of sorts - for example, type
number is matched with different pgtype
values in this example. This is related with the underling Carto implementation, that uses PostgreSQL, PostGIS and its own software stack. We recommend relying on the type
as much as possible.
Other, more complex, field types, like geometry
types, include additional details for their respective types. As before, this is related with the underlying Carto implementation tools, and not actively maintained or supported by the RW API.
For more information about the different types that can be found in Carto datasets please refer to PostgreSQL's documentation on Data Types or PostGIS's documentation.
GFW
Example fields response for a GFW dataset
{
"fields": [
{
"field_name": "umd_glad_landsat_alerts__date_conf",
"field_alias": null,
"field_description": null,
"field_values": null
},
{
"field_name": "umd_glad_landsat_alerts__date",
"field_alias": null,
"field_description": null,
"field_values": null
},
{
"field_name": "umd_glad_landsat_alerts__confidence",
"field_alias": null,
"field_description": null,
"field_values": [
"nominal",
"high",
"highest",
"not_detected"
]
},
{
"field_name": "gfw_integrated_alerts__date_conf",
"field_alias": null,
"field_description": null,
"field_values": null
},
{
"field_name": "gfw_integrated_alerts__date",
"field_alias": null,
"field_description": null,
"field_values": null
},
{
"field_name": "gfw_integrated_alerts__confidence",
"field_alias": null,
"field_description": null,
"field_values": [
"nominal",
"high",
"highest",
"not_detected"
]
},
{
"field_name": "umd_glad_sentinel2_alerts__date_conf",
"field_alias": null,
"field_description": null,
"field_values": null
},
{
"field_name": "umd_glad_sentinel2_alerts__date",
"field_alias": null,
"field_description": null,
"field_values": null
},
{
"field_name": "umd_glad_sentinel2_alerts__confidence",
"field_alias": null,
"field_description": null,
"field_values": [
"nominal",
"high",
"highest",
"not_detected"
]
},
{
"field_name": "wur_radd_alerts__date_conf",
"field_alias": null,
"field_description": null,
"field_values": null
},
{
"field_name": "wur_radd_alerts__date",
"field_alias": null,
"field_description": null,
"field_values": null
},
{
"field_name": "wur_radd_alerts__confidence",
"field_alias": null,
"field_description": null,
"field_values": [
"nominal",
"high",
"highest",
"not_detected"
]
}
]
}
The fields endpoint for GFW dataset returns an array of objects with each object containing field attributes including name, description and alias. Vector dataset fields include additional attributes indicating whether field is feature info and filter. Fields for raster dataset map to individual raster files associated with a dataset. For example, RADD Deforestation Alerts dataset has confidence field mapping to the primary raster dataset with possible values defined in field_values
attribute and additional fields such as is__landmark_indigenous_and_community_lands
, is__gfw_oil_palm
, etc that correspond to contextual raster datasets used to conduct analysis on the alerts data.
ArcGIS feature layer
Example response for a ArcGIS dataset
{
"tableName": "conservationMapServer3",
"fields": {
"objectid": {
"type": "esriFieldTypeOID"
},
"tcl_name": {
"type": "esriFieldTypeString"
},
"tcl_id": {
"type": "esriFieldTypeSmallInteger"
},
"area_ha": {
"type": "esriFieldTypeInteger"
},
"tx2_tcl": {
"type": "esriFieldTypeSmallInteger"
},
"gfwid": {
"type": "esriFieldTypeString"
},
"globalid": {
"type": "esriFieldTypeGlobalID"
},
"shape": {
"type": "esriFieldTypeGeometry"
},
"shape_Length": {
"type": "esriFieldTypeDouble"
},
"shape_Area": {
"type": "esriFieldTypeDouble"
}
}
}
ArcGIS uses its own type naming convention, as you see reflected in the included example. The RW API passes that information as-is to you. As different ArcGIS datasets rely on different ArcGIS server instances and versions, you may encounter variations in the types you'll find, depending on how ArcGIS evolves these types over type.
For more information about the different types that can be found in ArcGIS datasets please refer to ArcGIS's field data types documentation.
Google Earth Engine
Example response for a Google Earth Engine dataset
{
"data": {
"fields": {
"bands": [
{
"dataType": {
"precision": "INT",
"range": {
"max": 2147483647,
"min": -2147483648
}
},
"grid": {
"affineTransform": {
"scaleX": 0.00833333376795053,
"scaleY": -0.00833333376795053,
"translateX": -180.0000000000001,
"translateY": 90.00000782310963
},
"crsCode": "EPSG:4326",
"dimensions": {
"height": 18000,
"width": 43200
}
},
"id": "b1",
"pyramidingPolicy": "MEAN"
}
],
"geometry": {
"coordinates": [
[
[
"-Infinity",
"-Infinity"
],
[
"Infinity",
"-Infinity"
],
[
"Infinity",
"Infinity"
],
[
"-Infinity",
"Infinity"
],
[
"-Infinity",
"-Infinity"
]
]
],
"type": "Polygon"
},
"id": "users/resourcewatch/cli_030_global_aridity",
"name": "projects/earthengine-legacy/assets/users/resourcewatch/cli_030_global_aridity",
"properties": {
"title": "Image:cli_030 _global_aridity"
},
"sizeBytes": "413389345",
"title": "Image:cli_030 _global_aridity",
"type": "IMAGE",
"updateTime": "2017-10-06T18:58:39.646890Z"
},
"tableName": "users/resourcewatch/cli_030_global_aridity"
}
}
Google Earth Engine (GEE) is perhaps the biggest outlier when it comes to fields data. Because it relies on raster data, rather than tabular data, the data structure you'll find in a GEE dataset is very different, as you can see in the example on the side.
The response consists of loading the details for a single image, with the most meaningful information being the properties
(of an image) and bands
(of said image). Those will be the fields you'll be able to retrieve when using the query endpoints.
NEX-GDDP
Example response for a NEX-GDDP dataset
{
"fields": {
"tasavg": {
"type": "number",
"uom": "10^0"
},
"tasavg_q25": {
"type": "number",
"uom": "10^0"
},
"tasavg_q75": {
"type": "number",
"uom": "10^0"
},
"year": {
"type": "date"
}
},
"tableName": "tasavg/rcp45_30_y"
}
NEX-GDDP datasets have an additional uom
(unit of measure) field on some field types, but otherwise has no other info besides the basic details.
BigQuery
Example response for a BigQuery dataset
{
"tableName": "[bigquery-public-data:ghcn_m.ghcnm_tmin]",
"fields": [
{
"name": "id",
"type": "INTEGER",
"mode": "REQUIRED",
"description": "11 digit identifier, digits 1-3=Country Code, digits 4-8 represent the WMO id if the station is a WMO station. It is a WMO station if digits 9-11=\"000\"."
},
{
"name": "year",
"type": "INTEGER",
"mode": "NULLABLE",
"description": "4 digit year of the station record."
},
{
"name": "element",
"type": "STRING",
"mode": "NULLABLE",
"description": "element type, monthly mean temperature=\"TAVG\" monthly maximum temperature=\"TMAX\" monthly minimum temperature=\"TMIN\""
},
{
"name": "value1",
"type": "INTEGER",
"mode": "NULLABLE",
"description": "monthly value (MISSING=-9999). Temperature values are in hundredths of a degree Celsius, but are expressed as whole integers (e.g. divide by 100.0 to get whole degrees Celsius)."
},
{
"name": "qcflag3",
"type": "STRING",
"mode": "NULLABLE",
"description": "quality control flag, seven possibilities within quality controlled unadjusted (qcu) dataset, and 2 possibilities within the quality controlled adjusted (qca) dataset."
},
{
"name": "qcflag12",
"type": "STRING",
"mode": "NULLABLE",
"description": "quality control flag, seven possibilities within quality controlled unadjusted (qcu) dataset, and 2 possibilities within the quality controlled adjusted (qca) dataset."
},
{
"name": "dsflag12",
"type": "STRING",
"mode": "NULLABLE",
"description": "data source flag for monthly value, 21 possibilities"
}
]
}
BigQuery has a slight variation on the core structure returned by the fields endpoint for other dataset types. Instead of fields
having a key-value map, it has an array of objects, each describing a field. Each of these objects has a name
and type
property, identifying a field and its type, as well as a mode
and description
, respectively indicating if the field is nullable or required, and providing a human-friendly description of the field's content or purpose.
Loca
Example response for a Loca dataset
{
"fields": {
"xs": {
"type": "number",
"uom": "10^0"
},
"xs_q25": {
"type": "number",
"uom": "10^0"
},
"xs_q75": {
"type": "number",
"uom": "10^0"
},
"year": {
"type": "date"
}
},
"tableName": "loca_xs/rcp85_30_y"
}
Loca datasets have an additional uom
(unit of measure) field on some field types, but otherwise has no other info besides the basic details.
Document-based dataset types (csv, tsv, json and xml)
Example response for a document-based dataset
{
"tableName": "index_1c9a1e4f455b4c03ac88dd2242a2e4b1_1602065490373",
"fields": {
"cartodb_id": {
"type": "long"
},
"commodity": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"data_id": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"gcm_type": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"impactparameter": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"iso": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"region": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"scenario": {
"type": "text",
"fields": {
"keyword": {
"type": "keyword",
"ignore_above": 256
}
}
},
"value": {
"type": "float"
},
"year": {
"type": "long"
}
}
}
Document based datasets from the 4 different types of sources (json, xml, csv and tsv) all share a common internal storage engine, based on Elasticsearch. So, when querying for fields of a document-based dataset, you'll find information matching the field mechanism used by Elasticsearch. This is particularly evident on text fields, where the keyword
information is present. During most uses cases, we don't anticipate this information being needed, as relying on the type
value should cover the majority of your needs.
Dataset types not supported by the fields endpoint
The following dataset types have not been integrated with the fields endpoint, so you will get a 404 response when querying for their fields:
wms
rasdaman
vector
Errors for getting a dataset fields
Error code | Error message | Description |
---|---|---|
404 | Endpoint not found | You are querying for fields of a dataset which type is not integrated with the fields endpoint |
404 | Dataset not found | A dataset with the provided id does not exist. |
Query
In order to retrieve data from datasets, you can send queries to the API using a syntax very similar to SQL. Using these endpoints, you can also download the results of a particular query. If you are new to the RW API, or want to learn more about the concept of a querying datasets, we strongly encourage you to read the query concept documentation first. It gives you a brief and clear description of what a query is, and what it is useful for.
Please note that some SQL features might not be supported. Check here for a reference of the SQL features' support for each dataset provider.
Querying datasets
Structure of the endpoint for executing a query:
curl -i -X GET 'https://api.resourcewatch.org/v1/query/<dataset.id>?sql=SELECT * FROM <dataset.tableName>' \
-H "x-api-key: <your-api-key>"
In order to query a dataset, you'll need two pieces of information:
- The id of the dataset you're trying to query.
- The SQL query that represents the data you are trying to retrieve.
The dataset documentation covers different ways that you can use to browse the existing dataset catalog or upload your own, all of which will give you the details of a dataset, including the dataset id you'll need to query it.
The SQL query will have to be custom built by you to fit your needs, but a good starting point for newcomers would be
something like SELECT * FROM <dataset.tableName> limit 10
.
Notice: the limit
parameter restricts our results to 10 rows, and is not required. However, for our learning
purposes, this is useful, as it keeps the API responses small and fast.
Most of the SQL query is up to you to define, based on your needs and
the support provided for the dataset type you are using. The FROM
clause, however, does use a special value - the dataset's tableName
value, which you can also get from
the dataset documentation described above.
Example endpoint for executing a query:
curl -i -X GET 'https://api.resourcewatch.org/v1/query/098b33df-6871-4e53-a5ff-b56a7d989f9a?sql=SELECT cartodb_id, iso, name_0, name_1, type_1 FROM gadm28_adm1 limit 10' \
-H "x-api-key: <your-api-key>"
With both pieces of information at hand, you can now send your query to the API and get the response. The example cURL
to the side shows how that would look like.
Query response body
Example response:
{
"data": [
{
"cartodb_id": 1830,
"iso": "MEX",
"name_0": "Mexico",
"name_1": "Ciudad de México",
"type_1": "Distrito Federal"
},
{
"cartodb_id": 1109,
"iso": "HTI",
"name_0": "Haiti",
"name_1": "L'Artibonite",
"type_1": "Département"
},
...
],
"meta": {
"cloneUrl": {
"http_method": "POST",
"url": "/dataset/098b33df-6871-4e53-a5ff-b56a7d989f9a/clone",
"body": {
"dataset": {
"datasetUrl": "/query/098b33df-6871-4e53-a5ff-b56a7d989f9a?sql=SELECT%20*%20FROM%20gadm28_adm1%20limit%2010",
"application": [
"your",
"apps"
]
}
}
}
}
}
The following table describes the response body fields:
Field | Type | Description |
---|---|---|
data | Array | Array of objects that correspond to the result of the query execution. The data structure varies according to SELECT clause of your query, or the structure of dataset being queried. |
meta | Object | Object with metadata regarding the query executed. |
meta.cloneUrl | Object | Object with information for creating a new dataset from the current query execution. |
meta.cloneUrl.http_method | String | The HTTP method that should be used for the request to create a new dataset from the current query execution. Read the documentation on cloning a dataset for more info. |
meta.cloneUrl.url | String | The API endpoint path that should be used for the request to create a new dataset from the current query execution. |
meta.cloneUrl.body | Object | The body request data that should be provided for creating a new dataset from the current query execution. |
Query endpoint parameters
Example of requesting the query results as CSV data:
curl -i -X GET 'https://api.resourcewatch.org/v1/query/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date from gadm28_adm1 limit 2&format=csv' \
-H "x-api-key: <your-api-key>"
Example response:
"alert__date",
"_id"
"2019-04-12",
"AW6O0fqMLu2ttL7ZDM4P"
"2015-08-22",
"AW6O0fqMLu2ttL7ZDM4T"
Example of requesting to freeze the query results:
curl -i -X GET 'https://api.resourcewatch.org/v1/query/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date from gadm28_adm1 limit 2&freeze=true' \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"url": "https://storage.googleapis.com/query-freeze/1589458072773.json"
}
The following parameters can be provided as query parameters, in order to customize the output of the response returned:
Query parameter | Description | Type | Required |
---|---|---|---|
sql | The SQL query to be executed. This parameter changes the data returned in the query response body. | String | Yes |
format | The format of the returned response. By default, JSON format is assumed (json ), but you can also request the response as CSV (csv ), in which case the returned response will contain the CSV contents of the response. This parameter will only be considered for document-based datasets. |
String | No |
freeze | The freeze parameter, when provided as true , will create a file with the results of the execution of the query and return the URL for that file. Please note that you should be authenticated in order to request freezing the results of query executions. |
Boolean | No |
geostore | Read more about the geostore query parameter here. | String | No |
Filter query results by geostore
Example query providing a geostore id as query parameter to filter the results:
curl -i -X GET 'https://api.resourcewatch.org/v1/query/1d7085f7-11c7-4eaf-a29a-5a4de57d010e?sql=SELECT * FROM dis_001_significant_earthquakes LIMIT 5&geostore=972c24e1da2c2baacc7572ee9501abdc' \
-H "x-api-key: <your-api-key>"
Some dataset providers support receiving a geostore
query parameter. When providing this parameter, you can request
geo-referenced data that fits within the bounding box of the geostore with id provided. You can obtain the id of the
geostore using the RW API Geostore API. If the data is not geo-referenced, or if the dataset
provider does not support the geostore
query parameter, it will be ignored.
The following providers support this parameter:
- CartoDB (
carto
) - Global Forest Watch (
gfw
) - ArcGIS (
featureservice
) - Google Earth Engine (
gee
) - BigQuery (
bigquery
) - Rasdaman (
rasdaman
) - NEX-GDDP (
nexgddp
) - Loca (
loca
)
Alternative ways for querying datasets
While the GET request described above is the recommended way of querying datasets, there are other ways to query the RW API datasets that may be more suited for specific use cases.
Using the dataset slug instead of the id
Example query not using the dataset id in the request path, and using the dataset slug in the FROM clause:
curl -i -X GET 'https://api.resourcewatch.org/v1/query/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date from gadm28_adm1 limit 2' \
-H "x-api-key: <your-api-key>"
curl -i -X GET 'https://api.resourcewatch.org/v1/query/Glad-Alerts-Daily-Geostore-User-Areas_3?sql=SELECT alert__date from gadm28_adm1 limit 2' \
-H "x-api-key: <your-api-key>"
When referencing a dataset's id in a query, you have the option to use the dataset's slug instead, obtaining the same result. This is also applicable to the alternative query methods described in the sections below.
POST requests
The same query executed as GET, and as a POST request providing the SQL as request body param:
curl -i -X GET 'https://api.resourcewatch.org/v1/query/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date from gadm28_adm1 limit 2' \
-H "x-api-key: <your-api-key>"
curl -i -X POST 'https://api.resourcewatch.org/v1/query/9be3bf63-97fc-4bb0-b913-775ccae3cf9e' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"sql": "SELECT alert__date from gadm28_adm1 limit 2"
}'
Using the GET request is the recommended approach, as it allows HTTP caching of your result - subsequent requests for the same query will see a great performance increase, even if they are made by a different application or client.
Alternatively, you can also query a dataset using a POST request. POST requests are not cached, so you will not benefit from these speed improvements. However, GET requests can sometimes hit URL length restrictions, should your query string be too long. Using a POST request is the recommended solution for these cases. See the example on the side to see how you can query a dataset with a POST request.
Dataset id as the FROM clause
Three different but equivalent syntaxes for the same query:
curl -i -X GET 'https://api.resourcewatch.org/v1/query/098b33df-6871-4e53-a5ff-b56a7d989f9a?sql=SELECT cartodb_id, iso, name_0, name_1, type_1 FROM gadm28_adm1 limit 10' \
-H "x-api-key: <your-api-key>"
curl -i -X GET 'https://api.resourcewatch.org/v1/query?sql=SELECT cartodb_id, iso, name_0, name_1, type_1 FROM 098b33df-6871-4e53-a5ff-b56a7d989f9a limit 10' \
-H "x-api-key: <your-api-key>"
curl -i -X POST 'https://api.resourcewatch.org/v1/query' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"sql": "SELECT cartodb_id, iso, name_0, name_1, type_1 FROM 098b33df-6871-4e53-a5ff-b56a7d989f9a limit 10"
}'
The examples we've seen so far expect the URL to have
the /query/<dataset id or slug>?sql=SELECT * FROM <dataset.tableName>
format. However, you can also use the equivalent
/query?sql=SELECT * FROM <dataset id>
syntax. You can also use this alternative syntax with POST requests.
Redundant FROM clause (document based datasets only)
Example query providing a document-based dataset id in the request path or as the FROM clause:
curl -i -X GET 'https://api.resourcewatch.org/v1/query?sql=SELECT alert__date FROM 9be3bf63-97fc-4bb0-b913-775ccae3cf9e limit 10' \
-H "x-api-key: <your-api-key>"
curl -i -X GET 'https://api.resourcewatch.org/v1/query/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date FROM data limit 10' \
-H "x-api-key: <your-api-key>"
When querying a document based dataset using either GET or POST /query/<dataset id or slug>
request, the FROM
clause
is required but ignored, meaning you don't have to provide the dataset's tableName
as you normally would. The example
on the side illustrates this.
Downloading data from a dataset
Structure of the endpoint for downloading the results of a query:
curl -i -X GET 'https://api.resourcewatch.org/v1/download/<dataset.id>?sql=SELECT * FROM <dataset.tableName>' \
-H "x-api-key: <your-api-key>"
Example endpoint for downloading the results of a query:
curl -i -X GET 'https://api.resourcewatch.org/v1/download/098b33df-6871-4e53-a5ff-b56a7d989f9a?sql=SELECT cartodb_id, iso, name_0, name_1, type_1 FROM gadm28_adm1 limit 10' \
-H "x-api-key: <your-api-key>"
The download endpoint allows you to download the results of the execution of a query over a dataset. This endpoint is greatly based on the query datasets endpoint, so we strongly suggest you read that section of the documentation.
Note: Some dataset providers do not support downloading query results. You can download query results for the following dataset providers:
- Google Earth Engine
- Document-based datasets
- Carto
- GFW
- BigQuery
- ArcGIS FeatureService
Like when querying datasets, in order to download the results of the execution of query, you'll need two pieces of information:
- The id of the dataset you're trying to download the query execution results.
- The SQL query that represents the data you are trying to download.
The dataset documentation covers different ways that you can use to browse the existing dataset catalog or upload your own, all of which will give you the details of a dataset, including the dataset id you'll need to query it.
The SQL query will have to be custom built by you to fit your needs, but a good starting point for newcomers would be
something like SELECT * FROM <dataset.tableName> limit 10
.
Notice: the limit
parameter restricts our results to 10 rows, and is not required. However, for our learning
purposes, this is useful, as it keeps the API responses small and fast.
As with the query endpoint, the FROM
clause should reference the dataset's tableName
value, which you can also get
from the dataset documentation described above. And also, don't forget that you can check
the support provided for the dataset type you are using if you are
having trouble writing your SQL query.
Download response body
Example of downloading query results (by default, CSV data is assumed):
curl -i -X GET 'https://api.resourcewatch.org/v1/download/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date, alert__count from gadm28_adm1 limit 2' \
-H "x-api-key: <your-api-key>"
Example CSV response:
"alert__date",
"alert__count",
"_id"
"2019-04-12",
5,
"AW6O0fqMLu2ttL7ZDM4P"
"2015-08-22",
6,
"AW6O0fqMLu2ttL7ZDM4T"
Example of downloading query results requesting format as JSON:
curl -i -X GET 'https://api.resourcewatch.org/v1/download/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date, alert__count from gadm28_adm1 limit 2&format=json' \
-H "x-api-key: <your-api-key>"
Example JSON response:
{
"data": [
{
"alert__date": "2019-04-12",
"alert__count": 5,
"_id": "AW6O0fqMLu2ttL7ZDM4P"
},
{
"alert__date": "2015-08-22",
"alert__count": 6,
"_id": "AW6O0fqMLu2ttL7ZDM4T"
}
]
}
The response body of executing the download endpoint will contain the data to be downloaded. You can use the format
query parameter to customize the format of the data returned. By default, format=csv
will be assumed, so you will
receive the corresponding query results the actual CSV data in the response body. If you provide format=json
, the
returned result will be a JSON object with a data
index containing the results of the execution of the query provided.
Download execution errors
Calling the download endpoint might sometimes result in an error being returned. The following table describes the possible errors that can occur when downloading query execution results:
Error code | Error message | Description |
---|---|---|
400 | SQL or FS required | The required sql field is missing either as query string parameter or in the request body. |
400 | - format: format must be in [json,csv]. - | If provided, format must be either csv or json . |
500 | Internal server error | The error message might vary in this case. |
Download endpoint parameters
Example of requesting to freeze the download results:
curl -i -X GET 'https://api.resourcewatch.org/v1/download/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date from gadm28_adm1 limit 2&freeze=true' \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"url": "https://storage.googleapis.com/query-freeze/1589458072773.json"
}
You can use the following query parameters to customize the output of the download query execution results endpoint:
Query parameter | Description | Type | Required |
---|---|---|---|
sql | The SQL query to be executed. This parameter changes the data returned in the query response body. | String | Yes |
format | The format of the returned response. By default, CSV format is assumed (csv ), but you can also request the response as JSON (json ). Check the section on the download endpoint response body for some examples of how the format query parameter can be used. |
String | No |
freeze | The freeze parameter, when provided as true , will create a file with the results of the execution of the query and return the URL for that file. Please note that you should be authenticated in order to request freezing the results of query executions. |
Boolean | No |
geostore | Read more about the geostore query parameter here. | String | No |
Filter download results by geostore
Example download request providing a geostore id as query parameter to filter the results:
curl -i -X GET 'https://api.resourcewatch.org/v1/download/1d7085f7-11c7-4eaf-a29a-5a4de57d010e?sql=SELECT * FROM dis_001_significant_earthquakes LIMIT 5&geostore=972c24e1da2c2baacc7572ee9501abdc' \
-H "x-api-key: <your-api-key>"
Some dataset providers support receiving a geostore
query parameter. When providing this parameter, you can request
geo-referenced data that fits within the bounding box of the geostore with id provided. You can obtain the id of the
geostore using the RW API Geostore API. If the data is not geo-referenced, or if the dataset
provider does not support the geostore
query parameter, it will be ignored.
The following providers support this parameter:
- CartoDB (
carto
) - Global Forest Watch (
gfw
) - ArcGIS (
featureservice
) - Google Earth Engine (
gee
) - BigQuery (
bigquery
) - Rasdaman (
rasdaman
) - NEX-GDDP (
nexgddp
) - Loca (
loca
)
Alternative ways for downloading query execution results
As in the case of querying datasets, there are some alternative ways that you can use for downloading query execution results. While the GET request described above is the recommended way of downloading query results, there are other ways to download query results that may be more suited for specific use cases.
Using the dataset slug instead of the id
Example request for downloading the query execution results not using the dataset id in the request path, and using the dataset slug in the FROM clause:
curl -i -X GET 'https://api.resourcewatch.org/v1/download/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date from gadm28_adm1 limit 2' \
-H "x-api-key: <your-api-key>"
curl -i -X GET 'https://api.resourcewatch.org/v1/download/Glad-Alerts-Daily-Geostore-User-Areas_3?sql=SELECT alert__date from gadm28_adm1 limit 2' \
-H "x-api-key: <your-api-key>"
When referencing a dataset's id in th SQL query, you have the option to use the dataset's slug instead, obtaining the same result. This is also applicable to the alternative download methods described in the sections below.
POST requests
The same download request executed as GET, and as a POST request providing the SQL as request body param:
curl -i -X GET 'https://api.resourcewatch.org/v1/download/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date from gadm28_adm1 limit 2' \
-H "x-api-key: <your-api-key>"
curl -i -X POST 'https://api.resourcewatch.org/v1/download/9be3bf63-97fc-4bb0-b913-775ccae3cf9e' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"sql": "SELECT alert__date from gadm28_adm1 limit 2"
}'
Using the GET request is the recommended approach, as it allows HTTP caching of your result - subsequent requests for the same download endpoint call will see a great performance increase, even if they are made by a different application or client.
Alternatively, you can also download the query results using a POST request. POST requests are not cached, so you will not benefit from these speed improvements. However, GET requests can sometimes hit URL length restrictions, should your SQL query string be too long. Using a POST request is the recommended solution for these cases. See the example on the side to see how you can download the query execution results with a POST request.
Dataset id as the FROM clause
Three different but equivalent syntaxes for the same call to the download endpoint:
curl -i -X GET 'https://api.resourcewatch.org/v1/download/098b33df-6871-4e53-a5ff-b56a7d989f9a?sql=SELECT cartodb_id, iso, name_0, name_1, type_1 FROM gadm28_adm1 limit 10' \
-H "x-api-key: <your-api-key>"
curl -i -X GET 'https://api.resourcewatch.org/v1/download?sql=SELECT cartodb_id, iso, name_0, name_1, type_1 FROM 098b33df-6871-4e53-a5ff-b56a7d989f9a limit 10' \
-H "x-api-key: <your-api-key>"
curl -i -X POST 'https://api.resourcewatch.org/v1/download' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"sql": "SELECT cartodb_id, iso, name_0, name_1, type_1 FROM 098b33df-6871-4e53-a5ff-b56a7d989f9a limit 10"
}'
The examples we've seen so far expect the URL to have
the /download/<dataset id or slug>?sql=SELECT * FROM <dataset.tableName>
format. However, you can also use the
equivalent /download?sql=SELECT * FROM <dataset id>
syntax. This alternative syntax is also available for POST
requests.
Redundant FROM clause (document-based datasets only)
Example download providing a document-based dataset id in the request path or as the FROM clause:
curl -i -X GET 'https://api.resourcewatch.org/v1/download?sql=SELECT alert__date FROM 9be3bf63-97fc-4bb0-b913-775ccae3cf9e limit 10' \
-H "x-api-key: <your-api-key>"
curl -i -X GET 'https://api.resourcewatch.org/v1/download/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date FROM data limit 10' \
-H "x-api-key: <your-api-key>"
When downloading the query results for a document based dataset using either GET or
POST /download/<dataset id or slug>
request, the FROM
clause is required but ignored, meaning you don't have to
provide the dataset's tableName
as you normally would. The example on the side illustrates this.
Deleting data from a dataset
Example requests to delete data from a dataset:
curl -i -X GET 'https://api.resourcewatch.org/v1/query/:dataset_id?sql=DELETE FROM index_bf86b945c4ec41d2b5b7af00f3f61423' \
-H "x-api-key: <your-api-key>"
curl -i -X GET 'https://api.resourcewatch.org/v1/query/:dataset_id?sql=DELETE FROM index_bf86b945c4ec41d2b5b7af00f3f61423 WHERE x = "y"' \
-H "x-api-key: <your-api-key>"
Write queries such as INSERT
or UPDATE
are not supported in the RW API. You can use dataset endpoints
to append
or overwrite a given dataset's data, but you cannot use
SQL to write data into the datasets.
Most providers do not support DELETE
queries either. However, in the case of document-based datasets (i.e. where
the connectorType
is document
), you can delete the dataset's data via SQL DELETE
query. Executing a DELETE
query
requires authentication, and additionally, one of the following conditions must be met:
- have role
MANAGER
and own the dataset; - have role
ADMIN
and belong to all the apps to which the dataset is associated.
If the query is successfully executed, the request will return an HTTP response with status code 204 No Content
.
Please note that executing a delete query is an asynchronous process - as in the case of appending or overwriting a
dataset's data, the dataset will have its status updated to pending
, and updated once again to saved
once the
deletion process is completed.
Delete query execution errors
Error code | Error message | Description |
---|---|---|
403 | Forbidden | Not authorized to execute DELETE query - the logged user provided does not meet at least one of the conditions required to be able to delete the dataset data. |
400 | Unsupported query element detected | The SQL query provided is not valid, or the syntax provided is not supported. |
Supported SQL syntax reference
This section details the support for SQL syntax for the different dataset providers RW API supports. Keep in mind that
your HTTP request parameters (like sql
) should always be escaped according to the official HTTP specification. You can
use this online tool as an example of proper URL parameter encoding.
CartoDB datasets
This section describes the SQL support for querying datasets with provider cartodb
.
CartoDB geo-spatial query support
CartoDB datasets can be queried using PostGIS functions. This means if your dataset contains geo-referenced data, you can execute PostGIS functions on the data to extract the information you need. The table below displays some examples of supported PostGIS functions:
Supported | Feature | Example URL |
---|---|---|
YES | PostGIS: ST_MetaData | SELECT ST_METADATA(the_raster_webmercator) FROM sp_richness LIMIT 5 |
YES | PostGIS: ST_BandMetaData | SELECT ST_BANDMETADATA(the_raster_webmercator) FROM sp_richness LIMIT 5 |
YES | PostGIS: ST_SummaryStats | SELECT ST_SUMMARYSTATS(the_raster_webmercator, true) FROM sp_richness LIMIT 5 |
YES | PostGIS: ST_Histogram | SELECT ST_HISTOGRAM(the_raster_webmercator) FROM sp_richness LIMIT 5 |
YES | PostGIS: ST_ValueCount | SELECT ST_VALUECOUNT(the_raster_webmercator) FROM sp_richness LIMIT 5 |
YES | Using PostGIS functions in WHERE clause | SELECT * FROM sp_richness WHERE ST_METADATA(the_raster_webmercator) IS NOT NULL LIMIT 5 |
NO | Using PostGIS functions in GROUP BY clause | SELECT * FROM sp_richness GROUP BY ST_SUMMARYSTATS(the_raster_webmercator, true) IS NOT NULL LIMIT 5 |
YES | Using PostGIS functions in ORDER BY clause | SELECT * FROM sp_richness ORDER BY ST_METADATA(the_raster_webmercator) IS NOT NULL LIMIT 5 |
GFW Datasets
This section describes the SQL support for querying datasets with provider gfw
.
Note: This table was generated automatically with the help of this repository. If you are maintaining the docs, please do not edit manually these tables.
ArcGIS Feature Service datasets
This section describes the SQL support for querying datasets with connector type rest
and provider featureservice
.
Note: This table was generated automatically with the help of this repository. If you are maintaining the docs, please do not edit manually these tables.
GEE datasets
This section describes the SQL support for querying datasets with connector type rest
and providers gee
.
Note: This table was generated automatically with the help of this repository. If you are maintaining the docs, please do not edit manually these tables.
Document-based datasets
This section describes the SQL support for querying datasets with connector type document
and
providers csv
, tsv
, json
or xml
.
While the API has it's own query handling mechanism, it mostly relies on Opendistro for Elasticsearch 1.x SQL support, meaning its limitations will also apply to queries done to document-based datasets.
Note: This table was generated automatically with the help of this repository. If you are maintaining the docs, please do not edit manually these tables.
Troubleshooting SQL queries for document-based datasets
This SQL syntax supported when running queries for document-based datasets has some known limitations:
- Very large SQL queries may run into some parsing issues.
- Sorting by aggregated fields is not supported. For instance, the following statement is not
supported:
GROUP BY age ORDER BY COUNT(*)
. - Using aggregation functions on top of scalar functions is also not possible. For instance, the following statement is
not supported:
SELECT MAX(abs(age))
. - Sub-queries are only supported to a small degree, but the usage of
GROUP BY
orHAVING
in the sub-query is not supported. For instance, the following statement is supported:SELECT * FROM (SELECT first_name, last_name FROM emp WHERE last_name NOT LIKE '%a%') WHERE first_name LIKE 'A%' ORDER BY 1
, but statements with a higher level of complexity than applying simple conditions or orderings in the sub-query might not be supported. - The usage of scalar functions on nested fields in
ORDER BY
orWHERE
clauses is limited. For instance, the following statement is not supported:ORDER BY YEAR(dep.start_date)
.
You can read more about the limitations of using SQL with document-based datasets here.
Rasdaman datasets
SQL-like queries can be employed for accessing data stored in Rasdaman datasets. Subsets on the original axes of the data may be provided in the WHERE statement. So far, only operations that result in a single scalar can be obtained from Rasdaman - averages, minimums, maximums.
curl -XGET 'https://api.resourcewatch.org/v1/query?sql=SELECT avg(Green) from 18c0b71d-2f55-4a45-9e5b-c35db3ebfe94 where Lat > 0 and Lat < 45' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <token>'
NEX-GDDP and Loca datasets
Example of a query for a NEX-GDDP/Loca dataset, providing lat and lon as query parameters:
curl -X GET 'https://api.resourcewatch.org/v1/query/aaadd6c3-93ea-44bc-ba8b-7af3f40d39e1?sql=SELECT * FROM data&lat=30&lon=9' \
-H "x-api-key: <your-api-key>"
Example of a query for a NEX-GDDP/Loca dataset, providing a geostore id:
curl -X GET 'https://api.resourcewatch.org/v1/query/aaadd6c3-93ea-44bc-ba8b-7af3f40d39e1?sql=SELECT * FROM data&geostore=972c24e1da2c2baacc7572ee9501abdc' \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"tasmin": 243.6352,
"tasmin_q25": 243.4849,
"tasmin_q75": 243.8861,
"year": "1971-01-01T00:00:00-01:00"
},
{
"tasmin": 244.0795,
"tasmin_q25": 243.7174,
"tasmin_q75": 244.3168,
"year": "1981-01-01T00:00:00-01:00"
},
{
"tasmin": 244.4218,
"tasmin_q25": 243.9681,
"tasmin_q75": 244.5883,
"year": "1991-01-01T00:00:00-01:00"
},
{
"tasmin": 244.697,
"tasmin_q25": 244.2883,
"tasmin_q75": 244.8852,
"year": "2001-01-01T00:00:00-01:00"
},
{
"tasmin": 244.7719,
"tasmin_q25": 244.3449,
"tasmin_q75": 245.0115,
"year": "2011-01-01T00:00:00-01:00"
}
]
}
Like with the other supported providers, you can use a SQL-like syntax to query datasets stored both in NASA NEX-GDDP or
in Loca. However, these datasets always contain geo-referenced data, and so they expect that you always provide either
a lat
+ lon
pair, or a geostore
id, in order to filter the returned data. If you don't provide either a geostore
id or a lat+lon pair, the request will fail with status code 400 Bad Request
, with the following
message: No coordinates provided. Include geostore or lat & lon
.
The examples on the side allow you to understand how you can provide either the geostore
id or the lat
+ lon
combination.
WMS datasets
Queries to WMS datasets are no longer supported.
Layer
What is a layer?
By now, you are probably already familiar with datasets and querying them (if you are not, now is a good time to get up to speed on those). Many of the datasets you'll find on the RW API - and perhaps the datasets you are uploading too - contain georeferenced information. If that's the case, then you may want to render your data as a web map layer, and the RW API's layer endpoints can help you with that.
As we've seen in the layer concept docs, a RW API layer may store data in different formats, depending on the needs of its author. This is done using the several open format fields a layer has. To keep this documentation easy to understand, we'll spit our approach to layers into two sections:
- We'll first discuss the details of the endpoints that allow you to CRUD layers, without focusing on the actual data contained in it.
- In an future version of these docs, we'll dive deeper into some of the most common structures used to store data in the layer's open format fields.
After viewing the documentation below, consider looking at the webmap tutorial for a step-by-step guide to rendering an actual layer on a web application.
Getting all layers
Getting a list of layers
curl -X GET "https://api.resourcewatch.org/v1/layer" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "e5c3e7c5-19ae-4ca0-a461-71f1f67aa553",
"type": "layer",
"attributes": {
"slug": "total-co2-emissions-by-year",
"userId": "5858f37140621f11066fb2f7",
"application": [
"rw"
],
"name": "Total CO2 emissions by year",
"default": false,
"dataset": "11de2bc1-368b-42ed-a207-aaff8ece752b",
"env": "production",
"provider": "cartodb",
"iso": [],
"description": null,
"layerConfig": {
"account": "rw",
"body": {
"maxzoom": 18,
"minzoom": 3,
"layers": [
{
"type": "mapnik",
"options": {
"sql": "SELECT * cait_2_0_country_ghg_emissions_filtered",
"cartocss": "",
"cartocss_version": "2.3.0"
}
}
]
}
},
"legendConfig": {
"marks": {
"type": "rect",
"from": {
"data": "table"
}
}
},
"applicationConfig": {},
"staticImageConfig": {}
}
}
],
"links": {
"self": "https://api.resourcewatch.org/v1/layer?page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/v1/layer?page[number]=1&page[size]=10",
"last": "https://api.resourcewatch.org/v1/layer?page[number]=634&page[size]=10",
"prev": "https://api.resourcewatch.org/v1/layer?page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/v1/layer?page[number]=2&page[size]=10"
},
"meta": {
"total-pages": 63,
"total-items": 628,
"size": 10
}
}
This endpoint allows you to list existing layers and their properties. The result is a paginated list of 10 layers,
followed by metadata on total number of layers and pages, as well as useful pagination links. By default, only layers
with env
value production
are displayed. In the sections below, we’ll explore how you can customize this endpoint
call to match your needs.
Getting all layers for a dataset
Return the layers associated with a dataset
curl -X GET "https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer" \
-H "x-api-key: <your-api-key>"
When handling layers, it's common to want to limit results to those layers associated with a given dataset. Besides the filters covered below, there's an additional convenience endpoint to get the layers associated with a dataset, as shown in this example.
Getting all layers for multiple datasets
Return all layers associated with two datasets
curl -X POST "https://api.resourcewatch.org/layer/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"ids": ["<dataset 1 id>", "<dataset 2 id>"]
}'
{
"data": [
{
"id": "0dc39924-5736-4898-bda4-49cdc2f3b208",
"type": "layer",
"attributes": {
"name": "NOAA NEXt-Generation RADar (NEXRAD) Products (Locations)",
"slug": "noaa-next-generation-radar-nexrad-products-locations",
"dataset": "0b9e546c-f42a-4b26-bad3-7d606f58961c",
"description": "",
"application": [
"prep"
],
"iso": [
"USA"
],
"provider": "arcgis",
"userId": "legacy",
"default": true,
"protected": false,
"published": false,
"env": "production",
"layerConfig": {
"body": {
"useCors": false,
"layers": [
0
],
"url": "https://gis.ncdc.noaa.gov/arcgis/rest/services/cdo/nexrad/MapServer"
},
"type": "dynamicMapLayer"
},
"legendConfig": {
"type": "basic",
"items": [
{
"name": "NEXRAD",
"color": "#FF0000",
"icon": "http://gis.ncdc.noaa.gov/arcgis/rest/services/cdo/nexrad/MapServer/0/images/47768c7d812818af98d8da03a04d4fe4"
}
]
},
"interactionConfig": {},
"applicationConfig": {},
"staticImageConfig": {},
"createdAt": "2016-09-07T14:50:22.578Z",
"updatedAt": "2017-12-18T12:08:25.703Z"
}
},
{
"id": "0b021478-f4d3-4a1e-ae88-ab97f0085bc9",
"type": "layer",
"attributes": {
"name": "Projected change in average precipitation (in)",
"slug": "projected-change-in-average-precipitation-between-u-s",
"dataset": "d443beca-d199-4872-9d7d-d82c45e43151",
"description": "Projected change in average precipitation for the A2 emissions scenario.",
"application": [
"prep"
],
"iso": [
"USA"
],
"provider": "arcgis",
"userId": "legacy",
"default": true,
"protected": false,
"published": false,
"env": "production",
"layerConfig": {
"body": {
"use-cors": false,
"layers": [
12
],
"url": "https://gis-gfw.wri.org/arcgis/rest/services/prep/nca_figures/MapServer"
},
"zoom": 4,
"center": {
"lat": 39.6395375643667,
"lng": -99.84375
},
"type": "dynamicMapLayer",
"bbox": [
-125.61,
24.73,
-66.81,
49.07
]
},
"legendConfig": {
"type": "choropleth",
"items": [
{
"value": "< -90",
"color": "#8C5107"
},
{
"value": "-90 - -60",
"color": "#BF822B"
}
]
},
"interactionConfig": {},
"applicationConfig": {},
"staticImageConfig": {},
"createdAt": "2016-09-15T13:47:39.829Z",
"updatedAt": "2018-03-02T20:54:17.260Z"
}
}
]
}
This endpoint allows authenticated users to load all layers belonging to multiple datasets in a single request.
Return all layers associated with two datasets, that are associated with either
rw
orprep
applications
curl -X POST "https://api.resourcewatch.org/layer/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"ids": ["<dataset 1 id>", "<dataset 2 id>"],
"app" "rw,prep"
}'
Return all layers associated with two datasets, that are associated with both
rw
andprep
applications simultaneously
curl -X POST "https://api.resourcewatch.org/layer/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"ids": ["<dataset 1 id>", "<dataset 2 id>"],
"app" "rw@prep"
}'
Besides the required ids
array, your request body may optionally include a app
string value if you'd like to filter
the returned layers by their application
:
- Use a single value, like
rw
, if you want to show only layers that haverw
as one of their applications. - Use a comma separated list, like
rw,prep
, if you want to show only layers that haverw
orprep
as one of their applications. - Use a @ separated list, like
rw@prep
, if you want to show only layers that have bothrw
andprep
as their applications. - Note that the the filters do not need to match on the full application list. For example, the filters
rw,prep
andrw@prep
will both match a layer with the application list["rw", "prep", "gfw"]
.
Please note that, unlike getting all layers or getting all layers for a dataset, this endpoint does not come with paginated results, nor does it support pagination, filtering or sorting or including related entities described in their respective sections.
Pagination
Example request to load page 2 using 25 results per page
curl -X GET "https://api.resourcewatch.org/v1/layer?page[number]=2&page[size]=25" \
-H "x-api-key: <your-api-key>"
The Layers service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your layers list.
Filters
Return the layers filtered by those whose name contains emissions
curl -X GET "https://api.resourcewatch.org/v1/layer?name=emissions" \
-H "x-api-key: <your-api-key>"
Return the layers filtered by dataset
curl -X GET "https://api.resourcewatch.org/v1/layer?dataset=11de2bc1-368b-42ed-a207-aaff8ece752b" \
-H "x-api-key: <your-api-key>"
curl -X GET "https://api.resourcewatch.org/v1/dataset/11de2bc1-368b-42ed-a207-aaff8ece752b/layer" \
-H "x-api-key: <your-api-key>"
> Filter layers by published status
```shell
curl -X GET "https://api.resourcewatch.org/v1/layer?published=false" \
-H "x-api-key: <your-api-key>"
Filter layers by environment
curl -X GET "https://api.resourcewatch.org/v1/layer?env=staging" \
-H "x-api-key: <your-api-key>"
Return the layers filtered by those whose applications contain rw
curl -X GET "https://api.resourcewatch.org/v1/layer?app=rw" \
-H "x-api-key: <your-api-key>"
The layer list endpoint provides a wide range of filters that you can use to tailor your layer listing. Filtering layers adheres to the conventions defined in the Filter guidelines for the RW API, so we strongly recommend reading that section before proceeding. In addition to these conventions, you will be able to use the great majority of the layer fields you'll find on the layer reference section, with the following exceptions:
id
userName
userRole
: filtering by the role of the owning user can be done using theuser.role
query argument. If the requesting user does not have the ADMIN role, this filter is ignored. Please keep in mind that, due to the limitations of the underlying endpoint used to find user ids by role, the performance of the request while using this filter might be degraded.- Filtering by fields of type
Object
is not supported.
Additionally, you can use the following filters:
collection
: filters by a collection id. Requires being authenticated.favourite
: if defined, only the layers set by the user as favorites will be returned. Requires being authenticated.
Sorting
Sorting layers
curl -X GET "https://api.resourcewatch.org/v1/layer?sort=name" \
-H "x-api-key: <your-api-key>"
Sorting layers by multiple criteria
curl -X GET "https://api.resourcewatch.org/v1/layer?sort=name,slug" \
-H "x-api-key: <your-api-key>"
Explicit order of sorting
curl -X GET "https://api.resourcewatch.org/v1/layer?sort=-name,+slug" \
-H "x-api-key: <your-api-key>"
Sorting layers by the role of the user who owns the layer
curl -X GET "https://api.resourcewatch.org/v1/layer?sort=user.role" \
-H "x-api-key: <your-api-key>"
The Layer service currently supports sorting using the sort
query parameter. Sorting layer adheres to the conventions
defined in the Sorting guidelines for the RW API, so we strongly recommend reading that section
before proceeding. Additionally, you can check out the Layer reference section for a
detailed description of the fields you can use when sorting. In addition to all layer model fields, you can sort the
returned results by the name (using user.name
) or role (using user.role
) of the user owner of the layer. Keep in
mind that sorting by user data is restricted to ADMIN users.
Please also keep in mind that, due to the limitations of the underlying endpoint used to find user ids by name or role, the performance of the request while using this sort might be degraded.
Include entities associated with the layers
When fetching layers, you can request additional entities to be loaded. The following entities are available:
Vocabulary
Loads vocabulary associated with each layer:
curl -X GET "https://api.resourcewatch.org/v1/layer?includes=vocabulary" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "e5c3e7c5-19ae-4ca0-a461-71f1f67aa553",
"type": "layer",
"attributes": {
"slug": "total-co2-emissions-by-year",
"userId": "5858f37140621f11066fb2f7",
"application": [
"rw"
],
"name": "Total CO2 emissions by year",
"default": false,
"dataset": "11de2bc1-368b-42ed-a207-aaff8ece752b",
"env": "production",
"provider": "cartodb",
"iso": [],
"description": null,
"layerConfig": {
"account": "rw",
"body": {
"maxzoom": 18,
"minzoom": 3,
"layers": [
{
"type": "mapnik",
"options": {
"sql": "SELECT * cait_2_0_country_ghg_emissions_filtered",
"cartocss": "",
"cartocss_version": "2.3.0"
}
}
]
}
},
"legendConfig": {
"marks": {
"type": "rect",
"from": {
"data": "table"
}
}
},
"applicationConfig": {},
"staticImageConfig": {},
"vocabulary": [
{
"id": "resourcewatch",
"type": "vocabulary",
"attributes": {
"tags": [
"inuncoast",
"rp0002",
"historical",
"nosub"
],
"name": "resourcewatch",
"application": "rw"
}
}
]
}
}
]
}
Loads all vocabulary entities associated with each layer. Internally this uses
the dataset/<dataset_id>/layer/<layer_id>/vocabulary
endpoint, and thus it's affected by its behavior - particularly, only vocabularies associated with the rw
application
will be listed. There's currently no way to modify this behavior.
User
Loads the name and email address of the author of the layer. If you request this issue as an authenticated user
with ADMIN
role, you will additionally get the author's role.
If the data is not available (for example, the user has since been deleted), no user
property will be added to the
layer object.
Please keep in mind that, due to the limitations of the underlying endpoint used to find users by ids, the performance of the request while including user information might be degraded.
curl -X GET "https://api.resourcewatch.org/v1/layer?includes=user" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "e5c3e7c5-19ae-4ca0-a461-71f1f67aa553",
"type": "layer",
"attributes": {
"slug": "total-co2-emissions-by-year",
"userId": "5858f37140621f11066fb2f7",
"application": [
"rw"
],
"name": "Total CO2 emissions by year",
"default": false,
"dataset": "11de2bc1-368b-42ed-a207-aaff8ece752b",
"env": "production",
"provider": "cartodb",
"iso": [],
"description": null,
"layerConfig": {
"account": "rw",
"body": {
"maxzoom": 18,
"minzoom": 3,
"layers": [
{
"type": "mapnik",
"options": {
"sql": "SELECT * cait_2_0_country_ghg_emissions_filtered",
"cartocss": "",
"cartocss_version": "2.3.0"
}
}
]
}
},
"legendConfig": {
"marks": {
"type": "rect",
"from": {
"data": "table"
}
}
},
"applicationConfig": {},
"staticImageConfig": {},
"user": {
"name": "John Doe",
"email": "john.doe@vizzuality.com"
}
}
}
]
}
Requesting multiple additional entities
You can request multiple related entities in a single request using commas to separate multiple keywords
curl -X GET "https://api.resourcewatch.org/v1/layer?includes=user,vocabulary" \
-H "x-api-key: <your-api-key>"
Getting a layer by id or slug
Getting a layer by id:
curl -X GET "https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer_id>" \
-H "x-api-key: <your-api-key>"
curl -X GET "https://api.resourcewatch.org/v1/layer/<layer_id>" \
-H "x-api-key: <your-api-key>"
Getting a layer by slug:
curl -X GET "https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer_slug>" \
-H "x-api-key: <your-api-key>"
curl -X GET "https://api.resourcewatch.org/v1/layer/<layer_slug>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": {
"id": "e5c3e7c5-19ae-4ca0-a461-71f1f67aa553",
"type": "layer",
"attributes": {
"slug": "total-co2-emissions-by-year",
"userId": "5858f37140621f11066fb2f7",
"application": [
"rw"
],
"name": "Total CO2 emissions by year",
"default": false,
"dataset": "11de2bc1-368b-42ed-a207-aaff8ece752b",
"env": "production",
"provider": "cartodb",
"iso": [],
"description": null,
"layerConfig": {
"account": "rw",
"body": {
"maxzoom": 18,
"minzoom": 3,
"layers": [
{
"type": "mapnik",
"options": {
"sql": "SELECT * cait_2_0_country_ghg_emissions_filtered",
"cartocss": "",
"cartocss_version": "2.3.0"
}
}
]
}
},
"legendConfig": {
"marks": {
"type": "rect",
"from": {
"data": "table"
}
}
},
"applicationConfig": {},
"staticImageConfig": {}
}
},
"meta": {
"status": "saved",
"published": true,
"updatedAt": "2017-01-23T16:51:42.571Z",
"createdAt": "2017-01-23T16:51:42.571Z"
}
}
If you know the id or the slug
of a layer, then you can access it directly. Both id and slug
are case-sensitive.
Include entities associated with the layer
You can load related user
and vocabulary
data in the same request.
See this section for more details.
Creating a layer
To create a layer, you need to provide at least the following details:
curl -X POST "https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-d \
'{
"application": [
"rw"
],
"name": "Water stress",
"description": "water stress"
}'
Response:
{
"data": {
"id": "bd8a36df-2e52-4b2d-b7be-a48bdcd7c769",
"type": "layer",
"attributes": {
"name": "Water stress",
"slug": "Water-stress_7",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"description": "water stress",
"application": [
"rw"
],
"iso": [],
"userId": "5dbadb06df2dc74d2ad054fb",
"default": false,
"protected": false,
"published": true,
"env": "production",
"layerConfig": {},
"legendConfig": {},
"interactionConfig": {},
"applicationConfig": {},
"staticImageConfig": {},
"createdAt": "2020-06-04T14:28:24.575Z",
"updatedAt": "2020-06-04T14:28:24.575Z"
}
}
}
In this section we'll guide you through the process of creating a layer in the RW API. Layer creation is available to all registered API users, and will allow you to store your own layer visualisation settings on the API, for reusing and sharing.
Before creating a layer, there are a few things you must know and do:
- In order to be able to create a layer, you need to be authenticated.
- Depending on your user account's role, you may have permission to create a layer but not delete it afterwards - read more about this in the RW API role-based access control guidelines.
- The layers you create on the RW API will be publicly visible and available to other users.
Creating a layer is done using a POST request and passing the relevant data as body fields. The supported body fields are as defined on the layer reference section, but the minimum field list you must specify for all layers is:
- name
- description
- application
There's also a dependency on a dataset id, as it is required to build the POST URL. As noted on the layer concept documentation, a layer is meant to hold the rendering details of a layer, but not the actual data - that should be part of the dataset. While this is not enforced - it's up to your rendering tool to load the data, and it can do it from a RW API dataset or from anywhere else - it's common and best practice to have the data for a layer be sourced from the dataset that's associated with it.
When a layer is created, a vocabulary tag for it is automatically created, associated with the dataset tag.
The layer service was built to be very flexible, and not be restricted to specific layer rendering libraries or tools. This gives you the freedom to use virtually any rendering technology you want, but it also means you'll have to make additional decisions on how to structure your data into the different open format fields provided by a RW API layer. In a future release of these docs, we'll show you some examples of how existing applications use different rendering tools with the layer endpoints, to give you an idea on how you can structure your own data, and also as a way to help you get started creating your first layers for your own custom applications. Until then, the tutorials section of the documentation shows an example of how existing raster tile layers may be structured and how the information in the layer response can be utilized by a third-party visualization library.
Layer thumbnails
Preview of the thumbnail of a layer
curl -X GET "https://resourcewatch.org/embed/layer/<layer_id>" \
-H "x-api-key: <your-api-key>"
When a layer is created or updated, the RW API will automatically try to generate a thumbnail preview of it. This is
done using the renderer that's part of the Resource Watch website, and will only produce a
thumbnail if your layer uses the same approach as the RW website for declaring its layers. Searching for layers
belonging to the rw
application will give you an idea of how this is achieved.
The thumbnail process is asynchronous, meaning it may take up to one minute for your newly created or updated layer to
have a valid and/or up to date thumbnailUrl
value. If the thumbnail generation process fails (for example, if you
decide to use a different rendering tool and data structure), the thumbnail generation will fail silently, but will not
affect the actual layer creation or update process.
Errors for creating a layer
Error code | Error message | Description |
---|---|---|
400 | <field> : <field> can not be empty |
Your are missing a required field value. |
400 | - <field> : must be a <restriction> |
The value provided for the mentioned field does not match the requirements. |
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to create a layer with one or more application values that are not associated with your user account. |
404 | Dataset not found | The provided dataset id does not exist. |
404 | Error: StatusCodeError: 404 - {\"errors\":[{\"status\":404,\"detail\":\"Dataset not found\"}]} | The provided dataset exists but is not present on the graph. |
Updating a layer
Example PATCH request that updates a layer's name:
curl -X PATCH "https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name":"foo"
}'
The update layer endpoint allows you to modify the details of an existing layer. As noted on the layer concept documentation, the layer object stores the details of how layer is meant to be rendered, but does not contain the actual data. As such, if you are looking to update the data that's being displayed on your map, this is probably not the endpoint you're looking for - you may want to update your dataset instead. Use this endpoint if you want to modify things like legend details, color schemes, etc - this will depend on your rendering implementation.
Unless specified otherwise in their description, all the fields present in the layer reference section can be updated using this endpoint. When passing new values for Object type fields, the new value will fully overwrite the previous one. It’s up to you, as an API user, to build any merging logic into your application.
To perform this operation, the following conditions must be met:
- the user must be logged in and belong to the same application as the layer
- the user must comply with the RW API role-based access control guidelines.
Layer thumbnails
When a layer is updated, a new thumbnail is generated. Refer to this section for details on this process.
Errors for updating a layer
Error code | Error message | Description |
---|---|---|
400 | - <field> : must be a <restriction> |
The value provided for the mentioned field does not match the requirements. |
401 | Unauthorized | You need to be logged in to be able to update a layer. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the layer's owner (through the userId field of the layer). |
403 | Forbidden | You are trying to update a layer with one or more application values that are not associated with your user account. |
404 | Layer with id |
A layer with the provided id does not exist. |
404 | Dataset not found | A dataset with the provided id does not exist. |
Deleting a layer
Example DELETE request that deletes a layer:
curl -X DELETE "https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Response:
{
"data": {
"id": "bd8a36df-2e52-4b2d-b7be-a48bdcd7c769",
"type": "layer",
"attributes": {
"name": "Water stress",
"slug": "Water-stress_7",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"description": "water stress",
"application": [
"rw"
],
"iso": [],
"userId": "5dbadb06df2dc74d2ad054fb",
"default": false,
"protected": false,
"published": true,
"env": "production",
"layerConfig": {},
"legendConfig": {},
"interactionConfig": {},
"applicationConfig": {},
"staticImageConfig": {},
"createdAt": "2020-06-04T14:28:24.575Z",
"updatedAt": "2020-06-04T14:28:24.575Z"
}
}
}
Use this endpoint if you'd like to delete a layer from the RW API. As a layer object does not store the actual data being displayed, this will only delete the layer settings, but the actual data will continue to be available at its source.
Besides deleting the layer itself, this endpoint also deletes graph vocabularies and metadata related to the layer itself. These delete operations are issued after the layer itself is deleted. The process is not atomic, and the output of the API request is based solely on the result of the deletion of the layer itself. For example, is the metadata service is temporarily unavailable when you issue your delete layer request, the layer itself will be deleted, but the associated metadata will continue to exist. The response will not reflect the failure to delete metadata in any way.
In order to delete a layer, the following conditions must be met:
- the layer's
protected
property must be set tofalse
. - the user must be logged in and belong to the same application as the layer.
- the user must comply with the RW API role-based access control guidelines.
Errors for deleting a layer
Error code | Error message | Description |
---|---|---|
400 | Layer is protected | You are attempting to delete a layer that has protected set to prevent deletion. |
401 | Unauthorized | You need to be logged in to be able to delete a layer. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the layer's owner (through the userId field of the layer) |
404 | Dataset not found | A dataset with the provided id does not exist. |
404 | Layer with id |
A layer with the provided id does not exist. |
Deleting layers by user id
Example request for deleting layers by user id
curl -X DELETE "https://api.resourcewatch.org/v1/layer/by-user/<user_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Response:
{
"deletedLayers": [
{
"id": "bd8a36df-2e52-4b2d-b7be-a48bdcd7c769",
"type": "layer",
"attributes": {
"name": "Water stress",
"slug": "Water-stress_7",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"description": "water stress",
"application": [
"rw"
],
"iso": [],
"userId": "5dbadb06df2dc74d2ad054fb",
"default": false,
"protected": false,
"published": true,
"env": "production",
"layerConfig": {},
"legendConfig": {},
"interactionConfig": {},
"applicationConfig": {},
"staticImageConfig": {},
"createdAt": "2020-06-04T14:28:24.575Z",
"updatedAt": "2020-06-04T14:28:24.575Z"
}
}
],
"protectedLayers": [
{
"id": "1a8a36df-2e52-4b2d-b7be-a48bdcd7c769",
"type": "layer",
"attributes": {
"name": "Fire impact",
"slug": "fire_impact_7",
"dataset": "1ae6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"description": "fire impact",
"application": [
"rw"
],
"iso": [],
"userId": "5dbadb06df2dc74d2ad054fb",
"default": false,
"protected": true,
"published": true,
"env": "production",
"layerConfig": {},
"legendConfig": {},
"interactionConfig": {},
"applicationConfig": {},
"staticImageConfig": {},
"createdAt": "2020-06-04T14:28:24.575Z",
"updatedAt": "2020-06-04T14:28:24.575Z"
}
}
]
}
Use this endpoint if you'd like to delete all layers from associated with a user. As a layer object does not store the actual data being displayed, this will only delete the layer settings, but the actual data will continue to be available at its source.
Besides deleting the layers themselves, this endpoint also deletes graph vocabularies and metadata related to the layers. These delete operations are issued after each layer itself is deleted. The process is not atomic, and the output of the API request is based solely on the result of the deletion of the layer themselves. For example, is the metadata service is temporarily unavailable when you issue your delete layers request, the layers themselves will be deleted, but the associated metadata will continue to exist. The response will not reflect the failure to delete metadata in any way.
Any microservice or user with ADMIN role can use this endpoint. Regular users can use this endpoint to delete the layers they own.
The response includes two lists of layers:
deletedLayers
: an unpaginated list of all datasets that were layers as part of this operation.protectedLayers
: an unpaginated list of all layers associated with the provided user, that haveprotected
status set totrue
, and thus were not deleted.
Errors for deleting layers by user id
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to delete layers. |
403 | Forbidden | You are trying to delete the layers of an user that is not the same logged user, not an ADMIN user or a microservice |
Layer reference
This section gives you a complete view at the properties that are maintained as part of layer. When interacting with a
layer (on get, on create, etc) you will find most of these properties available to you, although they may be organized
in a slightly different structure (ie: on get, everything but the id
is nested inside an attributes
object).
You can find more details in the source code.
Field name | Type | Required | Default value | Description |
---|---|---|---|---|
id | String | Yes (autogenerated) | Unique Id of the layer. Auto generated on creation. Cannot be modified by users. | |
name | String | Yes | Name of the layer. | |
dataset | String | Yes | Id of the dataset to which the layer corresponds. Set on layer creation, cannot be modified. | |
slug | String | Yes (autogenerated) | Slug of the layer. Auto generated on creation. Cannot be modified by users. | |
description | String | No | User defined description of the layer. | |
application | Array | Yes | Applications associated with this layer. Read more about this field here. | |
iso | Array | No | List of ISO3 codes of the countries that relate to the layer. If empty (or contains a single element: 'global') then the layer is a global layer. | |
provider | String | No | Layer provider. It typically identifies the source service for the data displayed in the layer. | |
type | String | No | Layer type. | |
userId | String | Yes (autopopulated) | Id of the user who created the layer. Set automatically on creation. Cannot be modified by users. | |
default | Boolean | No | false | If the layer should be used as the dataset's default layer. |
protected | Boolean | Yes | false | If the layer is protected. A protected layer cannot be deleted. |
published | Boolean | Yes | true | If the layer is published or not. |
env | String | Yes | production | Environment to which the layer belongs. Read more about this field in the Environments concept section. |
applicationConfig | Object | No | Schema-less object meant to host application-specific data or behavior configuration. | |
layerConfig | Object | No | Schema-less object meant to define layer specific data, like source of data, styling and animation settings. | |
legendConfig | Object | No | Schema-less object meant to define how a layer legend should be represented visually. | |
staticImageConfig | Object | No | ||
interactionConfig | Object | No | Schema-less object meant to define interactive layer element behavior, ie.: how tooltips behave on click. | |
userName | String | No (autogenerated) | null | Name of the user who created the layer. This value is used only internally, and is never directly exposed through the API. Cannot be modified by users. |
userRole | String | No (autogenerated) | null | Role of the user who created the layer. This value is used only internally, and is never directly exposed through the API. Cannot be modified by users. |
createdAt | Date | No (autogenerated) | Automatically maintained date of when the layer was created. Cannot be modified by users. | |
updatedAt | Date | No (autogenerated) | Automatically maintained date of when the layer was last updated. Cannot be modified by users. |
Widget
What is a widget?
In a nutshell, a RW API widget is a toolset to help you render your data in a visually more appealing way. The widget concept documentation will give you a more detailed description of this, and we encourage you to read it before proceeding. We also recommend you take a look at our section about Vega if you plan on reusing existing widgets or upload widgets that are reusable by other users. The RW API does not require you to use Vega, but we highly recommend that you do, as it's the technology used by many of the widgets you'll find on the RW API.
Getting all widgets
Getting a list of widgets
curl -X GET "https://api.resourcewatch.org/v1/widget" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "51851e22-1eda-4bf5-bbcc-cde3f9a3a943",
"type": "widget",
"attributes": {
"name": "Example Widget",
"dataset": "be76f130-ed4e-4972-827d-aef8e0dc6b18",
"slug": "example-widget",
"userId": "5820ad9469a0287982f4cd18",
"description": "",
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"rw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": null,
"widgetConfig": "{}",
"template": false,
"layerId": null,
"createdAt": "2017-02-08T15:30:34.505Z",
"updatedAt": "2017-02-08T15:30:34.505Z"
}
},
{
...
}
],
"links": {
"first": "https://api.resourcewatch.org/v1/widget?page%5Bnumber%5D=1",
"prev": "https://api.resourcewatch.org/v1/widget?page%5Bnumber%5D=1",
"next": "https://api.resourcewatch.org/v1/widget?page%5Bnumber%5D=2&page%5Bsize%5D=10",
"last": "https://api.resourcewatch.org/v1/widget?page%5Bnumber%5D=64&page%5Bsize%5D=10",
"self": "https://api.resourcewatch.org/v1/widget?page%5Bnumber%5D=1&page%5Bsize%5D=10"
},
"meta": {
"total-pages": 38,
"total-items": 372,
"size": 10
}
}
This endpoint allows you to list existing widgets and their properties. The result is a paginated list of 10 widgets,
followed by metadata on total number of widgets and pages, as well as useful pagination links. By default, only widgets
with env
value production
are displayed. In the sections below, we’ll explore how you can customize this endpoint
call to match your needs.
Getting all widgets for a dataset
Return the widgets associated with a dataset
curl -X GET "https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "73f00267-fe34-42aa-a611-13b102f38d75",
"type": "widget",
"attributes": {
"name": "Precipitation Change in Puget Sound",
"dataset": "06c44f9a-aae7-401e-874c-de13b7764959",
"slug": "precipitation-change",
"userId": "58333dcfd9f39b189ca44c75",
"description": "NOAA nCLIMDIV Precipitation: Historical Precipitation",
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"prep"
],
"verified": false,
"default": true,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": "query/06c44f9a-aae7-401e-874c-de13b7764959?sql=select annual as x, year as y from index_06c44f9aaae7401e874cde13b7764959%20order%20by%20year%20asc",
"widgetConfig": {
...
},
"template": false,
"layerId": null,
"createdAt": "2016-08-03T16:17:06.863Z",
"updatedAt": "2017-03-21T16:07:57.631Z"
}
},
{
...
}
],
"links": {
"self": "https://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959/widget?page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959/widget?page[number]=1&page[size]=10",
"last": "https://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959/widget?page[number]=2&page[size]=10",
"prev": "https://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959/widget?page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959/widget?page[number]=2&page[size]=10"
},
"meta": {
"total-pages": 2,
"total-items": 18,
"size": 10
}
}
When handling widgets, it's common to want to limit results to those widgets associated with a given dataset. Besides the filters covered below, there's an additional convenience endpoint to get the widgets associated with a dataset, as shown in this example.
Getting all widgets for multiple datasets
Return all widgets associated with two datasets
curl -X POST "https://api.resourcewatch.org/widget/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"ids": ["<dataset 1 id>", "<dataset 2 id>"]
}'
Example response:
{
"data": [
{
"id": "73f00267-fe34-42aa-a611-13b102f38d75",
"type": "widget",
"attributes": {
"name": "Precipitation Change in Puget Sound",
"dataset": "06c44f9a-aae7-401e-874c-de13b7764959",
"slug": "precipitation-change",
"userId": "58333dcfd9f39b189ca44c75",
"description": "NOAA nCLIMDIV Precipitation: Historical Precipitation",
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"prep"
],
"verified": false,
"default": true,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": "query/06c44f9a-aae7-401e-874c-de13b7764959?sql=select annual as x, year as y from index_06c44f9aaae7401e874cde13b7764959%20order%20by%20year%20asc",
"widgetConfig": {
...
}
}
},
{
...
}
]
}
This endpoint allows users to load all widgets belonging to multiple datasets in a single request.
Return all widgets associated with two datasets, that are associated with either
rw
orprep
applications
curl -X POST "https://api.resourcewatch.org/widget/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"ids": ["<dataset 1 id>", "<dataset 2 id>"],
"app": "rw,prep"
}'
Return all widgets associated with two datasets, that are associated with both
rw
andprep
applications simultaneously
curl -X POST "https://api.resourcewatch.org/widget/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-d '{
"ids": ["<dataset 1 id>", "<dataset 2 id>"],
"app": "rw@prep"
}'
Besides the required ids
array, your request body may optionally include a app
string value if you'd like to filter
the returned widgets by their application
:
- Use a single value, like
rw
, if you want to show only widgets that haverw
as one of their applications. - Use a comma separated list, like
rw,prep
, if you want to show only widgets that haverw
orprep
as one of their applications. - Note that the the filters do not need to match on the full application list. For example, the filters
rw,prep
andrw@prep
will both match a widget with the application list["rw", "prep", "gfw"]
.
Please note that, unlike getting all widgets or getting all widgets for a dataset, this endpoint does not come with paginated results, nor does it support pagination , filtering or sorting or including related entities described in their respective sections.
Pagination
Example request to load page 2 using 25 results per page
curl -X GET "https://api.resourcewatch.org/v1/widget?page[number]=2&page[size]=25" \
-H "x-api-key: <your-api-key>"
The Widgets service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your widgets list.
Filters
Return the widgets filtered by those whose name contains emissions
curl -X GET "https://api.resourcewatch.org/v1/widget?name=emissions" \
-H "x-api-key: <your-api-key>"
Return the widgets filtered by dataset
curl -X GET "https://api.resourcewatch.org/v1/widget?dataset=11de2bc1-368b-42ed-a207-aaff8ece752b" \
-H "x-api-key: <your-api-key>"
curl -X GET "https://api.resourcewatch.org/v1/dataset/11de2bc1-368b-42ed-a207-aaff8ece752b/widget" \
-H "x-api-key: <your-api-key>"
Filter widgets by default value
curl -X GET "https://api.resourcewatch.org/v1/widget?default=false" \
-H "x-api-key: <your-api-key>"
Filter widgets by environment
curl -X GET "https://api.resourcewatch.org/v1/widget?env=staging" \
-H "x-api-key: <your-api-key>"
Return the widgets filtered by those whose applications contain both
rw
andprep
applications simultaneously
curl -X GET "https://api.resourcewatch.org/v1/widget?app=rw@prep" \
-H "x-api-key: <your-api-key>"
The widget list endpoint provides a wide range of filters that you can use to tailor your widget listing. Filtering widgets adheres to the conventions defined in the Filter guidelines for the RW API, so we strongly recommend reading that section before proceeding. In addition to these conventions, you'll be able to use the great majority of the widget fields you'll find on the widget reference, with the following exceptions:
id
userName
userRole
: filtering by the role of the owning user can be done using theuser.role
query argument. Please keep in mind that, due to the limitations of the underlying endpoint used to find user ids by role, the performance of the request while using this filter might be degraded.
Additionally, you can use the following filters:
collection
: filters by a collection id. Requires being authenticated.favourite
: if any value is defined for this query param, only the widgets set by the user as favorites will be returned. Requires being authenticated.
Sorting
Sorting widgets
curl -X GET "https://api.resourcewatch.org/v1/widget?sort=name" \
-H "x-api-key: <your-api-key>"
Sorting widgets by multiple criteria
curl -X GET "https://api.resourcewatch.org/v1/widget?sort=name,slug" \
-H "x-api-key: <your-api-key>"
Explicit order of sorting
curl -X GET "https://api.resourcewatch.org/v1/widget?sort=-name,+slug" \
-H "x-api-key: <your-api-key>"
Sorting widgets by the role of the user who owns the widget
curl -X GET "https://api.resourcewatch.org/v1/widget?sort=user.role" \
-H "x-api-key: <your-api-key>"
The Widget service currently supports sorting using the sort
query parameter. Sorting widgets adheres to the
conventions defined in the Sorting guidelines for the RW API, so we strongly recommend reading
that section before proceeding. Additionally, you can check out the Widget reference
section for a detailed description of the fields you can use when sorting. In addition to all widget model fields, you
can sort the returned results by the name (using user.name
) or role (using user.role
) of the user owner of the
widget. Keep in mind that sorting by user data is restricted to ADMIN users.
Please also keep in mind that, due to the limitations of the underlying endpoint used to find user ids by name or role, the performance of the request while using this sort might be degraded.
Include entities associated with the widgets
When loading widget data, you can optionally pass an includes
query argument to load additional data.
Include Vocabulary
Loads related vocabularies. If none are found, an empty array is returned.
curl -X GET "https://api.resourcewatch.org/v1/widget?includes=vocabulary" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "51851e22-1eda-4bf5-bbcc-cde3f9a3a943",
"type": "widget",
"attributes": {
"name": "Example widget",
"dataset": "be76f130-ed4e-4972-827d-aef8e0dc6b18",
"slug": "example-widget",
"userId": "5820ad9469a0287982f4cd18",
"description": null,
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"rw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": null,
"widgetConfig": "{}",
"template": false,
"layerId": null,
"createdAt": "2017-02-08T15:30:34.505Z",
"updatedAt": "2017-02-08T15:30:34.505Z",
"vocabulary": [
{
"id": "resourcewatch",
"type": "vocabulary",
"attributes": {
"tags": [
"inuncoast",
"rp0002",
"historical",
"nosub"
],
"name": "resourcewatch",
"application": "rw"
}
}
]
}
}
]
}
Include User
curl -X GET "https://api.resourcewatch.org/v1/widget?includes=user" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "51851e22-1eda-4bf5-bbcc-cde3f9a3a943",
"type": "widget",
"attributes": {
"name": "Example widget",
"dataset": "be76f130-ed4e-4972-827d-aef8e0dc6b18",
"slug": "example-widget",
"userId": "5820ad9469a0287982f4cd18",
"description": "",
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"rw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": null,
"widgetConfig": "{}",
"template": false,
"layerId": null,
"createdAt": "2017-02-08T15:30:34.505Z",
"updatedAt": "2017-02-08T15:30:34.505Z",
"user": {
"name": "John Sample",
"email": "john.sample@vizzuality.com"
}
}
}
]
}
Loads the name and email address of the author of the widget. If the user issuing the request has role ADMIN
, the
response will also display the role of the widget's author. If the data is not available (for example, the user has
since been deleted), no user
property will be added to the widget object.
Please keep in mind that, due to the limitations of the underlying endpoint used to find users by ids, the performance of the request while including user information might be degraded.
Include Metadata
curl -X GET "https://api.resourcewatch.org/v1/widget?includes=metadata" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "51851e22-1eda-4bf5-bbcc-cde3f9a3a943",
"type": "widget",
"attributes": {
"name": "Example widget",
"dataset": "be76f130-ed4e-4972-827d-aef8e0dc6b18",
"slug": "example-widget",
"userId": "5820ad9469a0287982f4cd18",
"description": "",
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"rw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": null,
"widgetConfig": "{}",
"template": false,
"layerId": null,
"createdAt": "2017-02-08T15:30:34.505Z",
"updatedAt": "2017-02-08T15:30:34.505Z",
"metadata": [
{
"id": "5aeb1c74a096b50010f3843f",
"type": "metadata",
"attributes": {
"dataset": "86777822-d995-49cd-b9c3-d4ea4f82c0a3",
"application": "rw",
"resource": {
"id": "51851e22-1eda-4bf5-bbcc-cde3f9a3a943",
"type": "widget"
},
"language": "en",
"info": {
"caption": "t",
"widgetLinks": []
},
"createdAt": "2018-05-03T14:28:04.482Z",
"updatedAt": "2018-06-07T11:30:40.054Z",
"status": "published"
}
}
]
}
}
]
}
Loads the metadata available for the widget. If none are found, an empty array is returned.
Requesting multiple additional entities
curl -X GET "https://api.resourcewatch.org/v1/widget?includes=metadata,user,vocabulary" \
-H "x-api-key: <your-api-key>"
You can request multiple related entities in a single request using commas to separate multiple keywords
Getting a widget by id
Getting a widget by id:
curl -X GET "https://api.resourcewatch.org/v1/widget/<widget_id>" \
-H "x-api-key: <your-api-key>"
curl -X GET "https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget_id>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": {
"id": "51851e22-1eda-4bf5-bbcc-cde3f9a3a943",
"type": "widget",
"attributes": {
"name": "Example widget",
"dataset": "be76f130-ed4e-4972-827d-aef8e0dc6b18",
"slug": "example-widget",
"userId": "5820ad9469a0287982f4cd18",
"description": "",
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"rw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": null,
"widgetConfig": "{}",
"template": false,
"layerId": null,
"createdAt": "2017-02-08T15:30:34.505Z",
"updatedAt": "2017-02-08T15:30:34.505Z"
}
}
}
If you know the id
of a widget, then you can access it directly. Ids are case-sensitive.
Overwrite the query url of a widget response
Getting a widget by id with a custom query url value:
curl -X GET "https://api.resourcewatch.org/v1/widget/<widget_id>?queryUrl=/v1/query?sql=Select%20*%20from%20data" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": {
"id": "51851e22-1eda-4bf5-bbcc-cde3f9a3a943",
"type": "widget",
"attributes": {
"name": "Example widget",
"dataset": "be76f130-ed4e-4972-827d-aef8e0dc6b18",
"slug": "example-widget",
"userId": "5820ad9469a0287982f4cd18",
"description": null,
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"rw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": "/v1/query?sql=Select * from data",
"widgetConfig": {
"data": {
"url": "/v1/query?sql=Select * from data"
}
},
"template": false,
"layerId": null,
"createdAt": "2017-02-08T15:30:34.505Z",
"updatedAt": "2017-02-08T15:30:34.505Z"
}
}
}
When getting a single widget, you can optionally provide a queryUrl
query parameter. If provided, this parameter will
overwrite the following response values:
data.attributes.queryUrl
data.attributes.widgetConfig.data.url
data.attributes.widgetConfig.data[0].url
This overwrite will only happen if a previous value already existed for the respective field. Also, keep in mind that these changes will NOT be persisted to the database, and will only affect the current request's response.
Customize the query url of a widget response
Getting a widget by id with a custom query url parameters:
curl -X GET "https://api.resourcewatch.org/v1/widget/<widget_id>?geostore=ungeostore" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": {
"id": "51851e22-1eda-4bf5-bbcc-cde3f9a3a943",
"type": "widget",
"attributes": {
"name": "Example widget",
"dataset": "be76f130-ed4e-4972-827d-aef8e0dc6b18",
"slug": "example-widget",
"userId": "5820ad9469a0287982f4cd18",
"description": null,
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"rw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": "<previous queryUrl value>?geostore=ungeostore",
"widgetConfig": {
"data": {
"url": "<previous widgetConfig.data.url value>?geostore=ungeostore"
}
},
"template": false,
"layerId": null,
"createdAt": "2017-02-08T15:30:34.505Z",
"updatedAt": "2017-02-08T15:30:34.505Z"
}
}
}
Getting a widget by id with a custom query url value parameters:
curl -X GET "https://api.resourcewatch.org/v1/widget/<widget_id>?queryUrl=/v1/query?sql=Select%20*%20from%20data&geostore=ungeostore" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": {
"id": "51851e22-1eda-4bf5-bbcc-cde3f9a3a943",
"type": "widget",
"attributes": {
"name": "Example widget",
"dataset": "be76f130-ed4e-4972-827d-aef8e0dc6b18",
"slug": "example-widget",
"userId": "5820ad9469a0287982f4cd18",
"description": null,
"source": null,
"sourceUrl": null,
"authors": null,
"application": [
"rw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"queryUrl": "/v1/query?sql=Select * from data&geostore=ungeostore",
"widgetConfig": {
"data": {
"url": "/v1/query?sql=Select * from data&geostore=ungeostore"
}
},
"template": false,
"layerId": null,
"createdAt": "2017-02-08T15:30:34.505Z",
"updatedAt": "2017-02-08T15:30:34.505Z"
}
}
}
When getting a single widget, you can optionally provide additional custom query parameter. These parameters will be appended to the following response values:
data.attributes.queryUrl
data.attributes.widgetConfig.data.url
data.attributes.widgetConfig.data[0].url
The widget service assumes these values are URLs, and will append your custom query parameters as such:
- If the value already has a
?
character present, your custom query parameters will be appended with&
preceding them. - If no
?
is present, the first custom query parameter will be appended with a?
, and the following with a&
before them.
This overwrite will only happen if a previous value already existed for the respective field. Also, keep in mind that these changes will NOT be persisted to the database, and will only affect the current request's response. You can combine these custom query parameters with an overwritten query url, as seen on the included example.
Include entities associated with the widget
You can load related user
, vocabulary
and metadata
data in the same request.
See this section for more details.
Creating a widget
To create a widget, you need to provide at least the following details:
curl -X POST "https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"application":[
"gfw"
],
"name":"Example Widget"
}'
curl -X POST "https://api.resourcewatch.org/v1/widget" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"application":[
"gfw"
],
"name":"Example Widget",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90"
}'
Response
{
"data": {
"id": "7946bca1-6c2a-4329-a127-558ef9551eba",
"type": "widget",
"attributes": {
"name": "Example Widget",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"slug": "Example-Widget_2",
"userId": "5dbadb0adf2dc74d2ad05dfb",
"application": [
"gfw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"template": false,
"createdAt": "2020-06-11T14:13:19.677Z",
"updatedAt": "2020-06-11T14:13:19.677Z"
}
}
}
In this section we'll guide you through the process of creating a widget in the RW API. Widget creation is available to all registered API users, and will allow you to store your own widget visualisation settings on the API, for reusing and sharing.
Before creating a widget, there are a few things you must know and do:
- In order to be able to create a widget, you need to be authenticated.
- Depending on your user account's role, you may have permission to create a widget but not delete it afterwards - read more about this in the RW API role-based access control guidelines.
- The widgets you create on the RW API will be publicly visible and available to other users.
Creating a widget is done using a POST request and passing the relevant data as body files. The supported body fields are as defined on the widget reference section, but the minimum field list you must specify for all widgets is:
- name
- application
- dataset - which can be specified either through the URL or the POST body.
The widget service was built to be very flexible, and not be restricted to specific widget rendering libraries or tools.
While we recommend using Vega, it's up to you to decide which
library to use, and how to save your custom data within a widget's widgetConfig
field. While there is no hard limit on
this, widgets that rely on excessively large widgetConfig
objects have been known to cause issues, so we recommend
being mindful of this.
Widget thumbnails
Preview of the thumbnail of a widget
curl -X GET "https://resourcewatch.org/embed/widget/<widget_id>" \
-H "x-api-key: <your-api-key>"
When a widget is created or updated, the RW API will automatically try to generate a thumbnail preview of it. This is
done using the renderer that's part of the Resource Watch website, and will only produce a
thumbnail if your widget uses the same approach as the RW website for declaring its widgets. Searching for widgets
belonging to the rw
application will give you an idea of how this is achieved.
The thumbnail process is asynchronous, meaning it may take up to one minute for your newly created or updated widget to
have a valid and/or up to date thumbnailUrl
value. If the thumbnail generation process fails (for example, if you
decide to use a different rendering tool and data structure), the thumbnail generation will fail silently, but will not
affect the actual widget creation or update process.
Errors for creating a widget
Error code | Error message | Description |
---|---|---|
400 | <field> : <field> can not be empty |
Your are missing a required field value. |
400 | - <field> : must be a <restriction> |
The value provided for the mentioned field does not match the requirements. |
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to create a widget with one or more application values that are not associated with your user account. |
404 | Dataset not found | The provided dataset id does not exist. |
Updating a widget
To update a widget, you have to do one of the following PATCH requests:
curl -X PATCH "https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget_id_or_slug>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name":"New Example Widget Name"
}'
curl -X PATCH "https://api.resourcewatch.org/v1/widget/<widget_id_or_slug>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name":"New Example Widget Name",
"dataset":"<dataset-id>
}'
Response
{
"data": {
"id": "7946bca1-6c2a-4329-a127-558ef9551eba",
"type": "widget",
"attributes": {
"name": "New Example Widget Name",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"slug": "Example-Widget_2",
"userId": "5dbadb0adf2dc74d2ad05dfb",
"application": [
"gfw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"template": false,
"createdAt": "2020-06-11T14:13:19.677Z",
"updatedAt": "2020-06-11T14:13:19.677Z"
}
}
}
The update widget endpoint allows you to modify the details of an existing widget. As noted on the widget concept documentation, the widget object stores the details of how widget is meant to be rendered, but may not contain the actual data. As such, if you are looking to update the data that's being displayed on your widget, this is probably not the endpoint you're looking for - you may want to update your dataset instead. Use this endpoint if you want to modify things like legend details, color schemes, etc - this will depend on your rendering implementation.
Unless specified otherwise in their description, all the fields present in
the widget reference section can be updated using this endpoint. When passing new
values for Object type fields, like widgetConfig
, the new value will fully overwrite the previous one. It’s up to you,
as an API user, to build any merging logic into your application.
To perform this operation, the following conditions must be met:
- the user must be logged in and belong to the same application as the widget
- the user must match one of the following:
- have role
ADMIN
- have role
MANAGER
orUSER
and be the widget's owner (through theuserId
field of the widget) and belong to all the applications associated with the widget.
- have role
Widget thumbnails
When a widget is updated, a new thumbnail is generated. Refer to this section for details on this process.
Errors for updating a widget
Error code | Error message | Description |
---|---|---|
400 | - <field> : must be a <restriction> |
The value provided for the mentioned field does not match the requirements. |
401 | Unauthorized | You need to be logged in to be able to update a widget. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER or USER and be the widget's owner (through the userId field of the widget) and belong to all the applications associated with the widget. |
403 | Forbidden | You are trying to update a widget with one or more application values that are not associated with your user account. |
404 | Widget with id |
A widget with the provided id does not exist. |
404 | Dataset not found | A dataset with the provided id does not exist. |
Cloning a widget
To clone a widget, you should use one of the following POST requests:
curl -X POST "https://api.resourcewatch.org/v1/widget/<widget_id_or_slug>/clone" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
curl -X POST "https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget_id_or_slug>/clone" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Response
{
"data": {
"id": "7946bca1-6c2a-4329-a127-558ef9551eba",
"type": "widget",
"attributes": {
"name": "Example Widget",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"slug": "Example-Widget_2",
"userId": "5dbadb0adf2dc74d2ad05dfb",
"application": [
"gfw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"template": false,
"createdAt": "2020-06-11T14:13:19.677Z",
"updatedAt": "2020-06-11T14:13:19.677Z"
}
}
}
This endpoint allows you to duplicate an existing widget. The newly created widget is identical to the old one, except:
- The
userId
will be the id of the user who issued the clone request name
anddescription
will be the same but can optionally be modified by the clone request (see the provided example)createdAt
andupdatedAt
will have the current time.
To perform this operation, the following conditions must be met:
- the user must be logged in and belong to the same application as the widget
- the user must match one of the following:
- have role
ADMIN
orMANAGER
- have role
USER
and be the widget's owner (through theuserId
field of the widget) and belong to all the applications associated with the widget.
- have role
Cloning a widget while optionally setting a new name or description:
curl -X POST "https://api.resourcewatch.org/v1/widget/<widget_id_or_slug>/clone" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": "name for the cloned widget",
"description": "description of the cloned widget"
}'
curl -X POST "https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget_id_or_slug>/clone" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": "name for the cloned widget",
"description": "description of the cloned widget"
}'
Response
{
"data": {
"id": "7946bca1-6c2a-4329-a127-558ef9551eba",
"type": "widget",
"attributes": {
"name": "name for the cloned widget",
"description": "description of the cloned widget",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"slug": "Example-Widget_2",
"userId": "5dbadb0adf2dc74d2ad05dfb",
"application": [
"gfw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"template": false,
"createdAt": "2020-06-11T14:13:19.677Z",
"updatedAt": "2020-06-11T14:13:19.677Z"
}
}
}
Widget thumbnails
When a widget is cloned, a new thumbnail is generated. Refer to this section for details on this process.
Errors for cloning a widget
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to clone a widget. |
403 | Forbidden | You need to either have the ADMIN or MANAGER role, or have role USER and be the widget's owner (through the userId field of the widget) and belong to all the applications associated with the widget. |
404 | Widget with id |
A widget with the provided id or slug does not exist. |
Deleting a widget
Example DELETE request that deletes a widget:
curl -X DELETE "https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
curl -X DELETE "https://api.resourcewatch.org/v1/widget/<widget_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Response
{
"data": {
"id": "7946bca1-6c2a-4329-a127-558ef9551eba",
"type": "widget",
"attributes": {
"name": "name for the cloned widget",
"description": "description of the cloned widget",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"slug": "Example-Widget_2",
"userId": "5dbadb0adf2dc74d2ad05dfb",
"application": [
"gfw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"template": false,
"createdAt": "2020-06-11T14:13:19.677Z",
"updatedAt": "2020-06-11T14:13:19.677Z"
}
}
}
Use this endpoint if you'd like to delete a widget from the RW API. As a widget object may not store the actual data being displayed, this may only delete the widget settings, but the actual data may continue to be available at its source.
Besides deleting the widget itself, this endpoint also deletes graph vocabularies and metadata related to the widget itself. These delete operations are issued after the widget itself is deleted. The process is not atomic, and the response is based solely on the result of the deletion of the widget itself, not related resources. For example, is the metadata service is temporarily unavailable when you issue your delete widget request, the widget itself will be deleted, but the associated metadata will continue to exist. The response will not reflect the failure to delete metadata in any way.
In order to delete a widget, the following conditions must be met:
- the widget's
protected
property must be set tofalse
. - the user must be logged in and belong to the same application as the widget.
- the user must comply with the RW API role-based access control guidelines.
Errors for deleting a widget
Error code | Error message | Description |
---|---|---|
400 | Widget is protected | You are attempting to delete a widget that has protected set to prevent deletion. |
401 | Unauthorized | You need to be logged in to be able to delete a widget. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the widget's owner (through the userId field of the widget) |
404 | Dataset not found | A dataset with the provided id does not exist. |
404 | widget with id |
A widget with the provided id does not exist. |
Deleting widgets by user id
Example request that deletes widgets by user id
curl -X DELETE "https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
curl -X DELETE "https://api.resourcewatch.org/v1/widget/<widget_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Response
{
"deletedLayers": [
{
"id": "7946bca1-6c2a-4329-a127-558ef9551eba",
"type": "widget",
"attributes": {
"name": "water widget",
"description": "description of the water widget",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"slug": "water_widget",
"userId": "5dbadb0adf2dc74d2ad05dfb",
"application": [
"gfw"
],
"verified": false,
"default": false,
"protected": false,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"template": false,
"createdAt": "2020-06-11T14:13:19.677Z",
"updatedAt": "2020-06-11T14:13:19.677Z"
}
}
],
"protectedLayers": [
{
"id": "6a46bca1-6c2a-4329-a127-558ef9551eba",
"type": "widget",
"attributes": {
"name": "fires widget",
"description": "description of the fires widget",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"slug": "fires_widget",
"userId": "5dbadb0adf2dc74d2ad05dfb",
"application": [
"gfw"
],
"verified": false,
"default": false,
"protected": true,
"defaultEditableWidget": false,
"published": true,
"freeze": false,
"env": "production",
"template": false,
"createdAt": "2020-06-11T14:13:19.677Z",
"updatedAt": "2020-06-11T14:13:19.677Z"
}
}
]
}
Use this endpoint if you'd like to delete all widgets from associated with a user. As a widget object does not store the actual data being displayed, this will only delete the widget settings, but the actual data will continue to be available at its source.
Besides deleting the widgets themselves, this endpoint also deletes graph vocabularies and metadata related to the widgets. These delete operations are issued after each widget itself is deleted. The process is not atomic, and the output of the API request is based solely on the result of the deletion of the widget themselves. For example, is the metadata service is temporarily unavailable when you issue your delete widgets request, the widgets themselves will be deleted, but the associated metadata will continue to exist. The response will not reflect the failure to delete metadata in any way.
Any microservice or user with ADMIN role can use this endpoint. Regular users can use this endpoint to delete the widgets they own.
The response includes two lists of widgets:
deletedWidgets
: an unpaginated list of all datasets that were widgets as part of this operation.protectedWidgets
: an unpaginated list of all widgets associated with the provided user, that haveprotected
status set totrue
, and thus were not deleted.
Errors for deleting widgets by user id
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to delete widgets. |
403 | Forbidden | You are trying to delete the widgets of an user that is not the same logged user, not an ADMIN user or a microservice |
Widget reference
This section gives you a complete view at the properties that are maintained as part of widget. When interacting with a
widget (on get, on create, etc) you will find most of these properties available to you, although they may be organized
in a slightly different structure (ie: on get, everything but the id
is nested inside an attributes
object).
You can find more details in the source code.
Field name | Type | Required | Default value | Description |
---|---|---|---|---|
id | String | Yes (autogenerated) | Unique Id of the widget. Auto generated on creation. Cannot be modified by users. | |
dataset | String | Yes | Id of the dataset to which the widget corresponds. Set on widget creation, cannot be modified. | |
name | String | Yes | Name of the widget. | |
slug | String | Yes (autogenerated) | Slug of the widget. Auto generated on creation. Cannot be modified by users. | |
userId | String | Yes (autopopulated) | Id of the user who created the widget. Set automatically on creation. Cannot be modified by users. | |
description | String | No | User defined description of the widget. | |
source | String | No | Description of the source of the widget's data, as it's meant to be displayed to the end user. | |
sourceUrl | String | No | URL of the source of the data, as it's meant to be displayed to the end user. | |
authors | String | No | Author or authors of the data displayed on the widget, as it's meant to be displayed to the end user. | |
queryUrl | String | No | URL of the RW API query or external URL containing the data displayed on the widget | |
thumbnailUrl | String | No | URL of a example thumbnail of the rendered widget. | |
env | String | Yes | production | Environment to which the widget belongs. Read more about this field in the Environments concept section. |
widgetConfig | Object | No | Schema-less object meant to host widget behavior configuration. | |
application | Array | Yes | Applications associated with this widget. Read more about this field here. | |
layerId | String | No | Id of the layer to which the widget corresponds. | |
verified | Boolean | Yes | false | |
default | Boolean | No | false | If the widget should be used as the dataset's default widget. |
protected | Boolean | Yes | false | If the widget is protected. A protected widget cannot be deleted. |
defaultEditableWidget | Boolean | Yes | false | Used by the RW frontend to determine if a widget is the default widget displayed on the Explore detail page for a given dataset. |
template | Boolean | Yes | false | If true, this widget is not necessarily meant to be rendered as-is, but rather as a template for other widgets to be generated from. |
published | Boolean | Yes | true | If the widget is published or not. |
freeze | Boolean | Yes | false | If true, the widget is meant to represent data from a specific snapshot taken at a given moment in time, as opposed to using a potentially mutable dataset. This data capturing functionality must be implemented by consuming applications, as this value has no logic associated with it on the API side. |
userName | String | No (autogenerated) | null | Name of the user who created the widget. This value is used only internally, and is never directly exposed through the API. Cannot be modified by users. |
userRole | String | No (autogenerated) | null | Role of the user who created the widget. This value is used only internally, and is never directly exposed through the API. Cannot be modified by users. |
createdAt | Date | No (autogenerated) | Automatically maintained date of when the widget was created. Cannot be modified by users. | |
updatedAt | Date | No (autogenerated) | Automatically maintained date of when the widget was last updated. Cannot be modified by users. |
Collections
What is a collection?
A collection is a way of aggregating WRI API resources like datasets, layers and widgets. A collection can reference one or more resources of different types.
Collection endpoints require authentication, and the collections are associated with the owner who initially created the collection.
Creating a collection
To create an empty collection, you can do a POST with the following body:
curl -X POST https://api.resourcewatch.org/v1/collection \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": "Collection name"
}'
Example response:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"env": "production",
"attributes": {
"name": "Collection name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"resources": []
}
}
]
}
You can also add a resource in the body of the request when creating a new collection, with the following body:
curl -X POST https://api.resourcewatch.org/v1/collection \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": "Collection name",
"resources": [
{
"type": "dataset",
"id": "06c44f9a-aae7-401e-874c-de13b7764959"
}
]
}'
Example response:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "Collection name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": [
{
"type": "dataset",
"id": "06c44f9a-aae7-401e-874c-de13b7764959"
}
]
}
}
]
}
To create a collection, you should send a POST request to the /v1/collection
endpoint, providing an authentication token that identifies the user making the request. You also need to (or can) provide the following fields in the request body:
Field name | Description | Required | Type |
---|---|---|---|
name | Name of collection. | Yes | String |
application | The application this collection belongs to (defaults to 'rw' ). Read more about this field here. |
No | String |
env | Environment to which the collection belongs. Read more about this field in the Environments concept section. | No | String |
resources | Array of resources in the collection. | No | Array of Objects |
Updating a collection
To update a collection, you should perform a PATCH request including the collection ID in the url. Here's an example:
curl -X PATCH https://api.resourcewatch.org/v1/collection/:id \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": "New name"
}'
Example response:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "New name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": []
}
}
]
}
You can update the name of a collection, you can send a PATCH request to the /v1/collection/:id
endpoint, providing an authentication token that identifies the user making the request.
Keep in mind that you will only be able to update collections that are owned by your user.
Adding a resource to an existing collection
To add a resource to a collection, you have to do a POST with the following body:
curl -X POST https://api.resourcewatch.org/v1/collection/:id/resource \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"type": "dataset",
"id": "06c44f9a-aae7-401e-874c-de13b7764959"
}'
Example response:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "New name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": [
{
"type": "dataset",
"id": "06c44f9a-aae7-401e-874c-de13b7764959"
}
]
}
}
]
}
You can do a POST request to the /v1/collection/:id/resource
to push a new resource to an existing collection. You also need to define the following fields in the request body:
Field | Description | Type |
---|---|---|
type | Type of resource being added | Text (dataset, layer, widget) |
id | Id of the resource | Text |
Getting collections
To get all collections of the logged user, you have to do a GET request:
curl -X GET https://api.resourcewatch.org/v1/collection \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "Collection name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": [{
"type": "dataset",
"id": "123456789"
}]
}
}
]
}
By making a GET request to the /v1/collection
endpoint, you can obtain the collections of the logged user.
To get all collections of the logged user, including the associated resources:
curl -X GET https://api.resourcewatch.org/v1/collection \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "Collection name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": [{
"type": "dataset",
"id": "123456789",
"attributes": {
...
}
}]
}
}
]
}
You can optionally add the include=true
query parameter to load the associated resources.
Pagination
Example request to load page 2 using 25 results per page
curl -X GET https://api.resourcewatch.org/v1/collection?page[number]=2&page[size]=25 \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
The Collections service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your collections list.
In the specific case of the Collections service, the default value for the page[size]
query parameter is 9999999, instead of 10. However (as recommended in the pagination guidelines), you should not rely on the default page size and always provide a value tailored to your needs.
Filters
Filtering collections by environment
curl -X GET https://api.resourcewatch.org/v1/collection?env=custom \
-H "x-api-key: <your-api-key>"
The /v1/collection
endpoint provides the following parameters to tailor the returned listing:
Field | Description | Type | Example |
---|---|---|---|
env | Environment to which the collection belongs. Multiple values can be combined using , as a separator. Does not support regexes. Read more about this field in the Environments concept section. |
String | any valid text. Defaults to production . |
userId | List collections for different user than the one making the request. Only available for ADMIN users or requests from other microservices. |
String | any valid user id. |
Sorting
Sorting collections
curl -X GET "https://api.resourcewatch.org/v1/collection?sort=name" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Sorting collections by multiple criteria
curl -X GET "https://api.resourcewatch.org/v1/collection?sort=name,application" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Explicit order of sorting
curl -X GET "https://api.resourcewatch.org/v1/collection?sort=-name,+application" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
The Collections service currently supports sorting using the sort
query parameter. Sorting collections adheres to the conventions defined in the Sorting guidelines for the RW API, so we strongly recommend reading that section before proceeding. Additionally, you can check out the Collection reference section for a detailed description of the fields you can use when sorting.
Get a collection by id
To get the collection by id, you have to do a GET request:
curl -X GET https://api.resourcewatch.org/v1/collection/:id \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "Collection name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": []
}
}
]
}
This endpoint returns the collection with id of the param. If the collection belongs to other user or does not exist, the endpoint returns 400.
Delete a collection
To delete the collection by id, you have to do a DELETE request:
curl -X DELETE https://api.resourcewatch.org/v1/collection/:id \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
In case of success, the deleted collection is returned in the response body:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "Collection name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": []
}
}
]
}
This endpoint deletes the collection with id of the param. If the collection belongs to other user or does not exist, the endpoint returns 400.
Delete a collection resource
To delete the resource you have to do a DELETE request:
curl -X DELETE https://api.resourcewatch.org/v1/collection/:id/resource/:resourceType/:resourceId \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
In case of success, the updated collection is returned in the response body:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "Collection name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": []
}
}
]
}
Using this endpoint you can also delete a resource in a collection with the id, resource type and resource id of the param. If the collection belongs to other user or not exist, the endpoint returns 400.
Delete a collection by user id
To delete the collection by user id, you have to do a DELETE request:
curl -X DELETE https://api.resourcewatch.org/v1/collection/by-user/:userId \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
In case of success, the deleted collections are returned in the response body:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "Collection name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": []
}
}
]
}
This endpoint deletes the collections owned by the user with id userId
. Any ADMIN user can use this endpoint to delete data for any user, while users with USER or MANAGER roles can only delete their own data.
Errors for deleting a collection by user id
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to delete collections. |
403 | Forbidden | You need to either have the ADMIN role, or call this endpoint with your own user id |
Finding collections by ids
To find collections by ids, you have to do a POST request:
curl -X POST https://api.resourcewatch.org/v1/collection/find-by-ids \
-H "Content-Type: application/json" \
-H "x-api-key: <your-api-key>" -d \
'{
"ids": ["5f56170c1fca55001ad51779"],
"userId": "5dd7b92abf56ca0011875ae2"
}'
Example response:
{
"data": [
{
"id": "5f56170c1fca55001ad51779",
"type": "collection",
"attributes": {
"name": "Collection name",
"ownerId": "5dd7b92abf56ca0011875ae2",
"application": "rw",
"env": "production",
"resources": []
}
}
]
}
You can also filter the returned results by application:
curl -X POST https://api.resourcewatch.org/v1/collection/find-by-ids?application=gfw \
-H "Content-Type: application/json" \
-H "x-api-key: <your-api-key>" -d \
'{
"ids": ["5f56170c1fca55001ad51779"],
"userId": "5dd7b92abf56ca0011875ae2"
}'
Example response:
{
"data": []
}
You can find collections providing an array of ids by making a POST request to the /v1/collection/find-by-ids
endpoint. You must provide in the body of the request the ids
of the collections you wish to fetch, as well as the id of the user (userId
) who owns these collections.
You can filter the returned results by application by providing the application
query parameter.
Finding collections by id does not require authentication.
Collection reference
Field name | Description | Type |
---|---|---|
name | Name of collection. | String |
ownerId | Id of the user owner of this collection. | String |
application | The application this collection belongs to (defaults to 'rw' ). Read more about this field here. |
String |
env | Environment to which the collection belongs. Read more about this field in the Environments concept section. | String |
resources | Array of resources in the collection. | Array of Objects |
--- type | The type of resource. | String (dataset, layer, widget) |
--- id | The id of the resource. | String |
Jiminy
Example jiminy GET request providing the SQL as query param:
curl -X GET 'https://api.resourcewatch.org/v1/jiminy?sql=SELECT col_1, col_2 FROM <dataset.id> limit <number>' \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Example jiminy POST request providing the SQL in the request body:
curl -X POST 'https://api.resourcewatch.org/v1/jiminy' \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"sql": "SELECT col_1, col_2 FROM <dataset.id> limit <number>"
}'
Example with real data:
curl -X GET 'https://api.resourcewatch.org/v1/jiminy?sql=SELECT iso, name_0, name_1, type_1 FROM 098b33df-6871-4e53-a5ff-b56a7d989f9a limit 10' \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
The jiminy
endpoint of the RW API makes use of the Jiminy library in order to
infer which type of charts can be obtained from a the execution of a SQL query on a given dataset. For a better
understanding of this endpoint, it is recommended to read beforehand on how
to query datasets.
To use this endpoint and infer the charts that you can build from a result set, you must provide a valid SQL query. This
query should contain the name of the columns for which you want to infer the chart types - the usage of the wildcard
selector (SELECT *
) in the SQL query is not supported by this endpoint.
Note: You must set a limit value to the SQL query provided. If you do not set it and the dataset contains a lot of data, this endpoint will try to obtain all data at once, which can result in performance issues.
Likewise with query
and download
endpoints, you can either provide the SQL as query param in a GET request, or in
the body of the request as a POST request - read more here.
Using the GET request is the recommended approach, as it allows HTTP caching of your result - subsequent requests for
the same jiminy
endpoint call will see a great performance increase, even if they are made by a different application
or client. Alternatively, you can also call the jiminy
endpoint using a POST request. POST requests are not cached, so
you will not benefit from these speed improvements. However, GET requests can sometimes hit URL length restrictions,
should your SQL query string be too long. Using a POST request is the recommended solution for these cases.
Jiminy response body
Example of successful response:
{
"data": {
"general": [
"bar",
"pie",
"scatter"
],
"byColumns": {
"iso": [
"bar",
"pie"
],
"name_0": [
"bar",
"pie"
],
"name_1": [
"bar",
"pie"
],
"type_1": [
"bar",
"pie"
]
},
"byType": {
"bar": {
"general": [
"iso",
"name_0",
"name_1",
"type_1"
],
"columns": {
"iso": [],
"name_0": [],
"name_1": [],
"type_1": []
}
},
"line": {
"general": [],
"columns": {
"iso": [],
"name_0": [],
"name_1": [],
"type_1": []
}
},
"pie": {
"general": [
"iso",
"name_0",
"name_1",
"type_1"
],
"columns": {
"iso": [],
"name_0": [],
"name_1": [],
"type_1": []
}
},
"scatter": {
"general": [
"iso",
"name_0",
"name_1",
"type_1"
],
"columns": {
"iso": [
"name_0",
"name_1",
"type_1"
],
"name_0": [
"iso",
"name_1",
"type_1"
],
"name_1": [
"iso",
"name_0",
"type_1"
],
"type_1": [
"iso",
"name_0",
"name_1"
]
}
},
"1d_scatter": {
"general": [],
"columns": {
"iso": [],
"name_0": [],
"name_1": [],
"type_1": []
}
},
"1d_tick": {
"general": [],
"columns": {
"iso": [],
"name_0": [],
"name_1": [],
"type_1": []
}
}
}
}
}
For a successful response, the response body is a JSON object containing a single index data
, which describes the type
of charts that can be obtained from the query provided. The following fields are usually present in the data
object:
Field | Type | Description | Example |
---|---|---|---|
data.general | Array | An array of distinct charts that can be used to represent the data of the query. | ["bar", "pie"] |
data.byColumns | Object | An object where the keys are the columns provided in the SQL query. For each the, its value is an array with the names of the charts that might be used to represent the data from the column in the key. | { "iso": ["bar", "pie"], "name_0": ["bar", "pie"] }, |
data.byType | Object | An object where the keys are all the charts supported by Jiminy. The values will contain the column names of the query execution that might be used to display the chart type in the key. If the chart type was not included in the data.general field of the response body, its content will likely be empty. |
{ "bar": { "general": ["iso", "name_0", "name_1", "type_1"], "columns": { "iso": [], "name_0": [], "name_1": [], "type_1": [] } } } |
Jiminy execution errors
The jiminy
endpoint might sometimes return an error response. The following table describes the possible errors that
can occur when calling this endpoint:
Error code | Error message | Description |
---|---|---|
400 | SQL o FS required | The required sql field is missing either as query string parameter or in the request body. |
500 | Internal server error | The error message might vary in this case. |
Jiminy endpoint parameters
The jiminy
endpoint makes use of a single query parameter, which is required for a successful call of the endpoint:
Query parameter | Description | Type | Required |
---|---|---|---|
sql | The SQL query which will be the basis for inferring the chart types. | String | Yes |
Metadata
What is metadata?
If you are new to the RW API, or want to learn more about the concept of metadata, we strongly encourage you to read the metadata concept documentation first. It gives you a brief and clear description of what metadata is, and why it is useful.
Once you've read that section, you can come back here to learn more details about using the RW API Metadata feature, which aims to provide summary information about Datasets, Layers, and Widgets.
Metadata objects describe things like the name, spatial and temporal coverage, usage rights, and contact information of datasets as well as their associated layers and widgets, uploaded by WRI, its partner organizations, or by API users like you.
They are particularly useful for allowing users to find relevant datasets, layers and widgets, understand their context, and for providing useful extra information, such as descriptions, licensing, and citations.
As such, if you really want people to be able to use your datasets, widgets or layers, it is crucial that it has metadata!
To find out more about accessing metadata objects already available on the RW API, check out the documentation on getting metadata objects. If you'd like to share your data with the world, you can also create your own metadata on the RW API, as well as update and delete existing metadata objects.
Metadata objects
RW API's approach to metadata is designed to offer flexibility; both in terms of the information contained and languages. Hence, when working with metadata objects it is important to understand a few key concepts.
The first of which is that metadata objects contain information about another RW API entity - a dataset, a layer or a
widget. Thus, each metadata object belongs to a single resource
, identified by its type
and id
. As
this type
+ id
pair directly or indirectly (as widgets and layers themselves are associated with a dataset)
references a dataset, and for convenience, each metadata object also has the dataset identifier to which it's
associated.
Another important concept to keep in mind is that each metadata object concerns a single combination of language
and application
. If you want to provide translations of your metadata, or if you'd like it to tailor a resource's
metadata to better fit different applications, you should create multiple metadata objects for the different
combinations of application and language.
Building on top of the two concepts above, it's important to highlight that while each resource can have multiple
metadata, it cannot have multiple metadata for the same combination of language
and application
. For example,
metadata about a tree cover dataset for the Global Forest Watch application might
be available in both English and Spanish (each a different metadata object), and these may be different compared to
metadata objects in the same languages associated with Resource Watch application. This
example would then represent a total of 4 different metadata objects, all associated with the same dataset.
When it comes to its internal structure, metadata objects have a balance of structured and free-format fields that promote a common base across all objects, while allowing different applications and use cases to have their own specific structure and details. You can learn more about the available fields in the metadata reference section.
Last but not least, it's important to keep in mind that the behavior of metadata objects and endpoints aims to be, as much as possible, independent from the target resource it references. In the detailed endpoint documentation below we'll cover the different endpoints in depth, and highlight the differences in behavior when handling different resource types, but you can safely assume that, for most of it, behavior described for a type of resource will be the same for all 3 types.
Metadata endpoints overview
As covered above, each metadata object directly concerns a single dataset, widget or layer. The endpoint structure
mostly reflects that, with each metadata action (getting, creating, modifying or deleting metadata) being available
through 3 different endpoints, one for each type of resource (for
example, /v1/dataset/<dataset-id>/metadata
, /v1/dataset/<dataset-id>/layer/<layer_id>/metadata
and /v1/dataset/<dataset-id>/widget/<widget_id>/metadata
). These endpoints will be documented as a single element, as
they behave in exactly the same way, with the only difference between them being the actual endpoint URL. Any
differences that may exist will be pointed out, but those will be rare. The only exceptions are the endpoints to load
all metadata (which ignores resource type) and to clone a dataset's metadata, which doesn't have a widget or layer
equivalent.
Getting metadata
There are 2 main ways to retrieve metadata objects from the RW API: using the "get all" endpoint (and optionally adding some filters), or loading metadata by their resource id (either a single element at a time, or multiple in one go) and type.
Remembering that each resource may have many metadata objects associated with it. In
general, you will usually want to use the filter parameters application
and language
, which may be one or many of
valid RW API applications and languages.
Getting all metadata
Getting a list of all metadata
curl -L -X GET 'https://api.resourcewatch.org/v1/metadata?application=rw,gfw&language=en,es&type=dataset&limit=1' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Getting a list of all metadata with optional parameters
curl -L -X GET 'https://api.resourcewatch.org/v1/metadata?application=rw,gfw&language=en,es&type=dataset&limit=1' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Example response
{
"data": [
{
"id": "57cfffd6129c3c100054c383",
"type": "metadata",
"attributes": {
"dataset": "0ffe5ad6-c920-421b-b69c-bc8893155df4",
"application": "gfw",
"resource": {
"id": "0ffe5ad6-c920-421b-b69c-bc8893155df4",
"type": "dataset"
},
"language": "en",
"name": "",
"description": "",
"source": "",
"citation": "",
"license": "",
"info": {
"organization": "",
"license": "",
"source": "",
"citation": "",
"description": "",
"short-description": "",
"subtitle": "",
"title": ""
},
"createdAt": "2016-12-13T10:02:28.337Z",
"updatedAt": "2016-12-13T10:03:02.445Z",
"status": "published"
}
}
]
}
This endpoint will allow you to get the list of the metadata available in the API, and it's the only endpoint that will allow you to load metadata for multiple resources at once.
It's worth pointing out that, unlike other similar endpoints on the RW API, this endpoint does NOT have pagination by default. If you query it without any of the optional parameters, you will get a list of all metadata objects for all datasets, widgets and layers. This is strongly discouraged, and you should not rely on this behavior - when using this endpoint, you should aim to use a combination of parameters to narrow down your response pool. You should also * expect a future update to this endpoint to introduce pagination* on all responses, so try to keep this in mind when using this endpoint on your application.
For a detailed description of each field, check out the Metadata reference section.
In the sections below, we’ll explore the optional parameters supported by this, which we strongly recommend you use.
Application and language filters
Getting a list of all metadata belonging to the RW application, written in either English or Spanish
curl -L -X GET 'https://api.resourcewatch.org/v1/metadata?application=rw&language=en,es' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
You can filter by application
and language
of the metadata by passing query arguments with the same name in your
call to this endpoint. You can filter by multiple values at the same time, separating them using using commas.
Type filter
Getting a list of all metadata for widgets
curl -L -X GET 'https://api.resourcewatch.org/v1/metadata?type=widget' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Using the type
query parameter you can specify the type of the metadata resource to load. Expected values
are dataset
, widget
or layer
, and any other values will produce no results.
Limit
Getting a list of up to 10 metadata
curl -L -X GET 'https://api.resourcewatch.org/v1/metadata?limit=10' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Using the limit
query parameter you can specify the maximum number of metadata to load in a single response.
Sorting
Sorting metadata
curl -X GET https://api.resourcewatch.org/v1/metadata?sort=name \
-H "x-api-key: <your-api-key>"
Sorting metadata by multiple criteria
curl -X GET https://api.resourcewatch.org/v1/metadata?sort=name,description \
-H "x-api-key: <your-api-key>"
Sort by name descending, description ascending
curl -X GET https://api.resourcewatch.org/v1/metadata?sort=-name,+description \
-H "x-api-key: <your-api-key>"
The Metadata service currently supports sorting using the sort
query parameter. Sorting metadata adheres to the
conventions defined in the Sorting guidelines for the RW API, so we strongly recommend reading
that section before proceeding. Additionally, you can check out
the Metadata reference section for a detailed description of the fields you can
use when sorting.
Getting metadata for a dataset, layer or widget
Getting metadata associated with a dataset
curl -L -X GET 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Getting metadata associated with a layer
curl -L -X GET 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer_id>/metadata' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Getting metadata associated with a widget
curl -L -X GET 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget_id>/metadata' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Example response
{
"data": [
{
"id": "595f836c0d9ed1000bc29a91",
"type": "metadata",
"attributes": {
"dataset": "f2fe7588-6d1b-400e-b79c-0c86bf1273ea",
"application": "rw",
"resource": {
"id": "f2fe7588-6d1b-400e-b79c-0c86bf1273ea",
"type": "dataset"
},
"language": "en",
"name": "Urban Population with Access to an Improved Water Source",
"description": "The Percentage of Urban Population with Access to an Improved Water Source is derived by ...",
"source": "UN WHO/WHO UNICEF JMP WSS",
"info": {
"data_download_link": "null",
"frequency_of_updates": "Annual",
"date_of_content": "1990-present",
"spatial_resolution": "Tabular: National",
"geographic_coverage": "Global",
"link_to_linense": "http://data.worldbank.org/summary-terms-of-use",
"license": "Open: You are free to copy, distribute, adapt, display, or include ...",
"citation": "World Bank. 2015. \"World Development Indicators: Improved Water Source (% of Population with Access).\" Retrieved from http://data.worldbank.org/indicator/SH.H2O.SAFE.ZS. Accessed through Resource Watch on [date]. www.resourcewatch.org.",
"cautions": "The data on access to an improved water source measure the ...",
"source_organization_link": "null",
"source_organization": "United Nations World Health Organization (UN WHO)/World Health Organization and United Nations Children's Fund Joint Monitoring Programme for Water Supply and Sanitation (WHO UNICEF JMP WSS)",
"function": "This data set displays the percentage of urban population with access to an improved drinking water source in a dwelling or located within a convenient distance from the user's dwelling.",
"functions": "This data set displays the percentage of urban population with access to an improved drinking water source in a dwelling or located within a convenient distance from the user's dwelling.",
"name": "Urban Population with Access to an Improved Water Source",
"technical_title": "Percentage of Urban Population with Access to an Improved Water Source (WHO/UNICEF)"
},
"columns": {
"year": {
"description": "Measured year",
"alias": "Year"
},
"value": {
"alias": "Value"
},
"country": {
"alias": "Country Name"
},
"iso": {
"alias": "ISO-3 Country Code"
}
},
"createdAt": "2017-07-07T12:49:48.721Z",
"updatedAt": "2017-08-28T14:30:17.701Z",
"status": "published"
}
}
]
}
These endpoints allow you to get metadata for a single dataset, widget or layer. By default, metadata for all languages and applications is returned, but you can use optional query parameters to filter that result.
Application and language filters
Getting a list of all metadata for a given dataset, belonging to the RW application and written in either English or Spanish
curl -L -X GET 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata?application=rw&language=en,es' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
You can filter by application
and language
of the metadata by passing query arguments with the same name in your
call to this endpoint. You can filter by multiple values at the same time, separating them using using commas.
Limit
Getting a list of all metadata for a given dataset, up to 10 results
curl -L -X GET 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata?limit=10' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
Using the limit
query parameter you can specify the maximum number of metadata to load in a single response.
Getting metadata for multiple datasets, layers or widgets
Getting metadata associated with multiple datasets
curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset/metadata/find-by-ids \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"ids": [<dataset ids>]
}'
Getting metadata associated with multiple widgets
curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset/layer/metadata/find-by-ids \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"ids": [<layer ids>]
}'
Getting metadata associated with multiple widgets
curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset/widget/metadata/find-by-ids \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"ids": [<widget ids>]
}'
Response
{
"data": [
{
"id": "595f836c0d9ed1000bc29a91",
"type": "metadata",
"attributes": {
"dataset": "f2fe7588-6d1b-400e-b79c-0c86bf1273ea",
"application": "rw",
"resource": {
"id": "f2fe7588-6d1b-400e-b79c-0c86bf1273ea",
"type": "dataset"
},
"language": "en",
"name": "Urban Population with Access to an Improved Water Source",
"description": "The Percentage of Urban Population with Access to an Improved Water Source is derived by ...",
"source": "UN WHO/WHO UNICEF JMP WSS",
"info": {
"data_download_link": "null",
"frequency_of_updates": "Annual",
"date_of_content": "1990-present",
"spatial_resolution": "Tabular: National",
"geographic_coverage": "Global",
"link_to_linense": "http://data.worldbank.org/summary-terms-of-use",
"license": "Open: You are free to copy, distribute, adapt, display, or include ...",
"citation": "World Bank. 2015. \"World Development Indicators: Improved Water Source (% of Population with Access).\" Retrieved from http://data.worldbank.org/indicator/SH.H2O.SAFE.ZS. Accessed through Resource Watch on [date]. www.resourcewatch.org.",
"cautions": "The data on access to an improved water source measure the ...",
"source_organization_link": "null",
"source_organization": "United Nations World Health Organization (UN WHO)/World Health Organization and United Nations Children's Fund Joint Monitoring Programme for Water Supply and Sanitation (WHO UNICEF JMP WSS)",
"function": "This data set displays the percentage of urban population with access to an improved drinking water source in a dwelling or located within a convenient distance from the user's dwelling.",
"functions": "This data set displays the percentage of urban population with access to an improved drinking water source in a dwelling or located within a convenient distance from the user's dwelling.",
"name": "Urban Population with Access to an Improved Water Source",
"technical_title": "Percentage of Urban Population with Access to an Improved Water Source (WHO/UNICEF)"
},
"columns": {
"year": {
"description": "Measured year",
"alias": "Year"
},
"value": {
"alias": "Value"
},
"country": {
"alias": "Country Name"
},
"iso": {
"alias": "ISO-3 Country Code"
}
},
"createdAt": "2017-07-07T12:49:48.721Z",
"updatedAt": "2017-08-28T14:30:17.701Z",
"status": "published"
}
}
]
}
This group of endpoints allows you to access metadata for multiple resources of the same type with a single request. The result will be a flat list of metadata elements, not grouped by their associated resource - it's up to your application to implement this logic if it needs it.
Application and language filters
Getting a list of all metadata for multiple widgets, belonging to the RW application and written in either English or Spanish
curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset/widget/metadata/find-by-ids?application=rw&language=en,es \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"ids": [<widget ids>]
}'
You can filter by application
and language
of the metadata by passing query arguments with the same name in your
call to this endpoint. You can filter by multiple values at the same time, separating them using using commas.
Errors for getting metadata for multiple datasets, layers or widgets
Error code | Error message | Description |
---|---|---|
400 | Missing 'ids' from request body | The required ids field is missing in the request body. |
Creating metadata
Creating a new metadata for a given dataset
curl -X POST 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata' \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <auth_token>" \
-H "Content-Type: application/json" \
-d '{
"application": <application>,
"language": <language>,
"name": "metadata name"
}'
Creating a new metadata for a given layer
curl -X POST 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/metadata' \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <auth_token>" \
-H "Content-Type: application/json" \
-d '{
"application": <application>,
"language": <language>,
"name": "metadata name"
}'
Creating a new metadata for a given widget
curl -X POST 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/metadata' \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <auth_token>" \
-H "Content-Type: application/json" \
-d '{
"application": <application>,
"language": <language>,
"name": "metadata name"
}'
Example response
{
"data": [
{
"id": "5f99b9317fe3c8001be2f272",
"type": "metadata",
"attributes": {
"dataset": "44c7fa02-391a-4ed7-8efc-5d832c567d57",
"application": "gfw",
"resource": {
"id": "44c7fa02-391a-4ed7-8efc-5d832c567d57",
"type": "dataset"
},
"language": "es",
"createdAt": "2020-10-28T18:32:17.464Z",
"updatedAt": "2020-10-28T18:32:17.464Z",
"status": "published"
}
}
]
}
This group of endpoints allows you to associate metadata with an existing dataset, layer or widget. To help make your resources easier to find, understand and reuse, we recommend creating the associated metadata right after you create your new dataset, layer or widget, but you can do it at any time if you want.
As we covered before, the RW API implementation of metadata aims for flexibility, so the only hard requirements when creating a new metadata is that you specify the associate resource id and type, their corresponding dataset id, and the language and application of the metadata (you should ensure that dataset id in the URL matches the dataset id of the resource you're creating metadata for). Everything else is up to you to decide if you want to define or not, but the effectiveness of your metadata will increase if you provide more details about your resources. You can learn more about the available fields in the metadata reference section.
If you want to create new metadata for your resources, you must have the necessary user account permissions. Specifically, you must:
- the user must be logged in and belong to the same application as the metadata you're creating
- the user must have role
ADMIN
orMANAGER
Errors for creating metadata
Error code | Error message | Description |
---|---|---|
400 | <field> : <field> can not be empty |
Your are missing a required field value. |
400 | <field> : empty or invalid <field> |
The provided value for <field> is invalid. |
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to create metadata for an application value that is not associated with your user account. |
Updating metadata
Updating metadata for a given dataset
curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <auth_token>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"language": <language>,
"name": "updated metadata name"
}'
Updating metadata for a given layer
curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/metadata \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <auth_token>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"language": <language>,
"name": "updated metadata name"
}'
Updating metadata for a given widget
curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/metadata \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <auth_token>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"language": <language>,
"name": "updated metadata name"
}'
Example response
{
"data": [
{
"id": "942b3f38-9504-4273-af51-0440170ffc86-dataset-942b3f38-9504-4273-af51-0440170ffc86-rw-en",
"type": "metadata",
"attributes": {
"dataset": "942b3f38-9504-4273-af51-0440170ffc86",
"application": "rw",
"resource": {
"type": "dataset",
"id": "942b3f38-9504-4273-af51-0440170ffc86"
},
"language": "en",
"name": "Cloud Computing Market - USA - 2016",
"source": "http://www.forbes.com/",
"info": {
"summary": "These and many other insights are from the latest series of cloud computing forecasts and market estimates produced by IDC, Gartner, Microsoft and other research consultancies. Amazon’s decision to break out AWS revenues and report them starting in Q1 FY2015 is proving to be a useful benchmark for tracking global cloud growth. In their latest quarterly results released on January 28, Amazon reported that AWS generated $7.88B in revenues and attained a segment operating income of $1.863B. Please see page 8 of the announcement for AWS financials. For Q4, AWS achieved a 28.5% operating margin (% of AWS net sales).",
"author": "Louis Columbus",
"date": "MAR 13, 2016 @ 10:42 PM",
"link": "http://www.forbes.com/sites/louiscolumbus/2016/03/13/roundup-of-cloud-computing-forecasts-and-market-estimates-2016/#5875cf0074b0"
},
"createdAt": "2017-01-20T08:07:53.272Z",
"updatedAt": "2017-01-20T08:40:30.190Z",
"status": "published"
}
}
]
}
To update an existing metadata, you need to issue a PATCH request to the endpoint that matches your resource type and id, specify the new values you want to use. You can update most of the fields listed in the metadata reference section, apart from:
id
userId
createdAt
andupdatedAt
language
andapplication
dataset
resource
One important detail is that you MUST specify, in your request body, both the application
and language
values of the
metadata you're trying to update. These fields will not be used as new values, as you would expect, but are used to
pinpoint exactly which metadata entry will be updated - remember that each resource may have multiple metadata
associated with it, but only one per application-language pair.
Also keep in mind that, when updating object type fields, your new value will overwrite the previous value for that field entirely - it's up to you to implement any sort of data merge logic you'd like to see happen.
To perform this operation, the following conditions must be met:
- the user must be logged in and belong to the same application as the metadata that's being updated
- the user must comply with the RW API role-based access control guidelines.
Errors for updating metadata
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to update metadata. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the metadata owner (through the userId field of the metadata). |
403 | Forbidden | You are trying to update metadata with an application value that is not associated with your user account. |
404 | Metadata of resource |
Metadata matching the provided resource data, language and application does not exist. |
Cloning dataset metadata
Cloning metadata for a given dataset
curl -X POST 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata/clone' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-H "Authorization: Bearer <auth_token>" -d \
'{
"newDataset": "<targer dataset>",
"application": "<application>"
}'
Example response
{
"data": [
{
"id": "942b3f38-9504-4273-af51-0440170ffc86-dataset-942b3f38-9504-4273-af51-0440170ffc86-rw-en",
"type": "metadata",
"attributes": {
"dataset": "942b3f38-9504-4273-af51-0440170ffc86",
"application": "rw",
"resource": {
"type": "dataset",
"id": "942b3f38-9504-4273-af51-0440170ffc86"
},
"language": "en",
"name": "Cloud Computing Market - USA - 2016",
"source": "http://www.forbes.com/",
"info": {
"summary": "These and many other insights are from the latest series of cloud computing forecasts and market estimates produced by IDC, Gartner, Microsoft and other research consultancies. Amazon’s decision to break out AWS revenues and report them starting in Q1 FY2015 is proving to be a useful benchmark for tracking global cloud growth. In their latest quarterly results released on January 28, Amazon reported that AWS generated $7.88B in revenues and attained a segment operating income of $1.863B. Please see page 8 of the announcement for AWS financials. For Q4, AWS achieved a 28.5% operating margin (% of AWS net sales).",
"author": "Louis Columbus",
"date": "MAR 13, 2016 @ 10:42 PM",
"link": "http://www.forbes.com/sites/louiscolumbus/2016/03/13/roundup-of-cloud-computing-forecasts-and-market-estimates-2016/#5875cf0074b0"
},
"createdAt": "2017-01-20T08:07:53.272Z",
"updatedAt": "2017-01-20T08:40:30.190Z",
"status": "published"
}
}
]
}
This endpoint allows you to clone all the existing metadata associated with a dataset, as new metadata associated with a different dataset. Note that this will not clone metadata for widgets or layers associated with the defined dataset; only dataset metadata will be cloned.
When calling this endpoint, you must provide two body parameters:
newDataset
: the id of the target dataset to which the cloned metadata will be associated.application
: an application to which your user account is associated. This is not used in the cloning logic.
A successful cloning will return a list of all metadata created in this process.
To perform this operation, the following conditions must be met:
- the user must be logged in and belong to the same application as the metadata that's being updated
- the user must comply with the RW API role-based access control guidelines.
Errors for cloning metadata
Error code | Error message | Description |
---|---|---|
400 | - newDataset: newDataset can not be empty. - | You need to specify the newDataset body parameter. |
400 | Metadata of resource dataset: |
The target dataset already has metadata associated with it, and cloning the metadata from the source dataset would cause it to have more than one metadata per language and application. |
401 | Unauthorized | You need to be logged in to be able to update metadata. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the metadata owner (through the userId field of the metadata). |
403 | Forbidden | You are trying to clone metadata with an application value that is not associated with your user account. |
404 | Metadata of resource |
Metadata matching the provided resource data, language and application does not exist. |
Deleting metadata
Deleting metadata for a given dataset
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata?application=<application>&language=<language> \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <auth_token>"
Deleting metadata for a given layer
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/metadata?application=<application>&language=<language> \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <auth_token>"
Deleting metadata for a given widget
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/metadata?application=<application>&language=<language> \
-H "x-api-key: <your-api-key>" \
-H "Authorization: Bearer <auth_token>"
Example response
{
"data": [
{
"id": "942b3f38-9504-4273-af51-0440170ffc86-dataset-942b3f38-9504-4273-af51-0440170ffc86-rw-en",
"type": "metadata",
"attributes": {
"dataset": "942b3f38-9504-4273-af51-0440170ffc86",
"application": "rw",
"resource": {
"type": "dataset",
"id": "942b3f38-9504-4273-af51-0440170ffc86"
},
"language": "en",
"name": "Cloud Computing Market - USA - 2016",
"source": "http://www.forbes.com/",
"info": {
"summary": "These and many other insights are from the latest series of cloud computing forecasts and market estimates produced by IDC, Gartner, Microsoft and other research consultancies. Amazon’s decision to break out AWS revenues and report them starting in Q1 FY2015 is proving to be a useful benchmark for tracking global cloud growth. In their latest quarterly results released on January 28, Amazon reported that AWS generated $7.88B in revenues and attained a segment operating income of $1.863B. Please see page 8 of the announcement for AWS financials. For Q4, AWS achieved a 28.5% operating margin (% of AWS net sales).",
"author": "Louis Columbus",
"date": "MAR 13, 2016 @ 10:42 PM",
"link": "http://www.forbes.com/sites/louiscolumbus/2016/03/13/roundup-of-cloud-computing-forecasts-and-market-estimates-2016/#5875cf0074b0"
},
"createdAt": "2017-01-20T08:07:53.272Z",
"updatedAt": "2017-01-20T08:40:30.190Z",
"status": "published"
}
}
]
}
The metadata delete endpoint allows you to delete a single metadata at a time, provided you have the necessary
permissions. Besides the details provided in the URL itself, you must also specify, as query parameters, both
the application
and language
values of the metadata you're trying to delete. These fields will be used to pinpoint
exactly which metadata entry will be deleted - remember that each resource may have multiple metadata associated with
it, but only one per application-language pair.
To perform this operation, the following conditions must be met:
- the user must be logged in and belong to the same application as the metadata that's being deleted
- the user must comply with the RW API role-based access control guidelines.
Errors for deleting metadata
Error code | Error message | Description |
---|---|---|
400 | Bad request | Your request does not include the application or language query parameters. |
401 | Unauthorized | You need to be logged in to be able to delete metadata. |
403 | Forbidden | You need to either have the ADMIN role, or have role MANAGER and be the metadata owner (through the userId field of the metadata). |
403 | Forbidden | You are trying to delete metadata with an application value that is not associated with your user account. |
404 | Metadata of resource |
Metadata matching the provided resource data, language and application does not exist. |
Metadata reference
This section gives you a complete view at the properties that are maintained as part of metadata objects. When
interacting with metadata objects (on get, on create, etc) you will find most of these properties available to you,
although they may be organized in a slightly different structure (ie: on get, everything but the id
is nested inside
an attributes
object).
You can find more details in the source code.
Field name | Type | Required | Default value | Description |
---|---|---|---|---|
id | String | Yes (autogenerated) | Unique Id of the metadata. Auto generated on creation. Cannot be modified by users. | |
dataset | String | Yes | Id of the dataset to which the metadata object corresponds. Set on metadata creation, cannot be modified. | |
application | Array | Yes | Applications associated with this metadata. Read more about this field here. | |
resource.id | String | Yes | Id of the resource associated with the metadata. | |
resource.type | String | Yes | Type of the resource associated with the metadata. | |
userId | String | Yes (autopopulated) | Id of the user who created the metadata. Set automatically on creation. Cannot be modified by users. | |
language | String | Yes | Language in which the metadata details are written. While not enforced, we strongly recommend using 2 character language codes. | |
name | String | No | Name of the metadata. | |
description | String | No | User defined description of the metadata. | |
status | String | No | published | Publication status of the metadata. Defaults to published , can alternatively be set to unpublished . |
source | String | No | Source information about the associated resource | |
citation | String | No | Citation information about the associated resource | |
license | String | No | License named used for the associated resource | |
units | Object | No | Free-form object mapping each of the associated resource's fields to a unit | |
info | Object | No | Free-form object for custom information about the associated resource | |
columns | Object | No | Free-form object mapping each of the associated resource's fields to a free-form object containing more details. | |
applicationProperties | Object | No | Free-form object containing application-specific information about the associated resource | |
createdAt | Date | No (autogenerated) | Automatically maintained date of when the metadata was created. Cannot be modified by users. | |
updatedAt | Date | No (autogenerated) | Automatically maintained date of when the metadata was last updated. Cannot be modified by users. |
Vocabularies and tags
What are vocabularies and tags?
Vocabularies and tags concepts are covered in their dedicated section, and we strongly recommend you read that section before diving into the details of the respective endpoints. In it, we explain in detail what is a tag and a vocabulary, and why you should use them to empower different use cases of the RW API.
Simply put, a tag is a keyword that describes a resource
(we'll talk in depth about what these are in the next
section). A vocabulary is a group of tags and has a name (also called and used as an id
for the vocabulary) that
should define the scope or context of the tags it contains.
It's important to keep in mind that these associations between a resource and a vocabulary have
an application associated with them. Putting this in an example, dataset
AAA
may be associated with
vocabulary BBB
for application rw
, but not for application gfw
. Most endpoints will allow you explicitly define
which application you are referring to (some will even require it), and a rw
default value will be assumed when no
explicit value is provided.
What are resources?
Throughout this section, we'll refer multiple times to resources
. Simply put, a resource
is either a dataset, a
widget, or a layer. Tags and vocabularies work in a similar fashion for each of these 3 types of RW API entity, so often
we'll refer to resources instead, for convenience.
We assume that, at this point, you are already familiar with the concepts of dataset, layer or widget (ideally you are familiar with the 3). If that's not the case, we strongly encourage you to learn about those concepts first, and we also recommend you take some time to explore and experiment using actual dataset, layer, or widget endpoints before proceeding. Vocabularies and tags exist to improve and empower your use cases of those resources, so it should only be used by applications and users that are already comfortable with the basics, and want to take their knowledge of the RW API to the next level.
The behavior of vocabulary and tags endpoints aims to be, as much as possible, independent from the type of the target resource it references. In the detailed endpoint documentation below we'll cover the different endpoints in depth, and highlight the differences in behavior when handling different resource types, but you can safely assume that, for most of it, the behavior described for a type of resource will be the same for all 3 types.
A note on resources
Creating a new vocabulary/tag for a widget
curl -X POST https://api.resourcewatch.org/v1/dataset/AAA/widget/BBB/vocabulary/VVV \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"tags": [<tags>]
}'
In the context of the vocabulary/tag service, widgets and layers are identified not only by their own id but also by the
id you specify as being their associated dataset. Using the side example as reference, this API request would create a
vocabulary VVV
for the resource widget BBB
associated with dataset AAA
. If you later reference the same widget id,
but as belonging to a different dataset, it will be treated as a different resource altogether, and thus will have
different vocabularies and tags. Keep in mind that widgets and layers should only be associated with a single dataset,
so this behavior is described as a pitfall, and you should only rely on vocabularies/tags for widgets/layers properly
associated with their correct dataset.
The special knowledge_graph
vocabulary
Throughout the whole vocabulary/tags service, there is a special vocabulary named knowledge_graph
. When used, this
vocabulary acts as any other vocabulary but has additional logic built-in for the purpose of integrating vocabulary/tags
with the graph available as part of the RW API.
Whenever you create or clone a vocabulary named knowledge_graph
for a resource,
the dataset, layer or widget node is added to the graph if not already present, and
the tags are associated to it. Updating the knowledge_graph
vocabulary also
updates the corresponding tags associated to it on the graph side, and
deleting the vocabulary
also deletes the corresponding tags in the graph.
For more details on the graph, its purpose, and how to use it, please refer its dedicated concept and reference documentation.
Associations between vocabularies, tags and resources
Vocabularies and resources
Despite not being 100% accurate, it's useful to think that a vocabulary is uniquely identified by a tuple of 3 values:
- The resource (id and type) to which it's associated
- Its
name
orid
(these are 2 names for the same underlying value) - Its
application
Putting it in other words: you can think of a vocabulary as being associated with only one resource at a time. So, if you create, update or delete a vocabulary, you are only doing so for that resource. You can safely modify the vocabularies for a resource without fear of affecting vocabularies and tags for other resources.
Further down, we'll cover endpoints that allow you to discover resources by performing searches based on vocabularies and tags. These endpoints are able to aggregate these different vocabularies and tags from multiple resources, and produce a unified response - making it look like vocabularies are shared across resources, and thus producing meaningful results.
If you find the above slightly confusing, we advise you explore these docs and learn more about the different endpoints available - maybe even try to add vocabularies and tags to one of your resources - and then come back and see if your newly gained knowledge helps you get a deeper understanding of how vocabularies and tags work on the RW API.
Vocabularies and tags
Tags are simply strings associated with an individual vocabulary. They have no direct connection to a resource and have no logic or complexity within the context of a vocabulary. Tags that have the same value but belong to different vocabularies are not matched or related in any way.
Endpoint overview
In broad terms, there are two types of endpoints for manipulating vocabulary/tags: endpoints that allow to CRUD vocabulary/tags for a given resource, and endpoints that allow you to query for resources for a given vocabulary/tag.
We'll start by covering how you can manipulate associations between vocabulary/tags and resources, and further down will cover how to list vocabulary/tags, and their associated resources.
Getting vocabulary/tags for a resource
There are two types of endpoints that will allow you to get vocabularies and tags for a resource: one to retrieve all vocabularies and their tags, and another to retrieve all tags for a given vocabulary.
Getting all vocabularies and tags for a resource
Getting vocabularies and tags associated with a dataset
curl -L -X GET 'https://api.resourcewatch.org/dataset/<dataset-id>/vocabulary' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Getting vocabularies and tags associated with a layer
curl -L -X GET 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer_id>/vocabulary' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Getting vocabularies and tags associated with a widget
curl -L -X GET 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget_id>/vocabulary' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Example response
{
"data": [
{
"id": "testVocabulary1",
"type": "vocabulary",
"attributes": {
"tags": [
"tag1",
"tag2"
],
"name": "testVocabulary1",
"application": "rw"
}
},
{
"id": "testVocabulary2",
"type": "vocabulary",
"attributes": {
"tags": [
"tag3",
"tag2"
],
"name": "testVocabulary2",
"application": "rw"
}
}
]
}
These endpoints allow you to get vocabulary/tags for a single dataset, widget, or layer. By default, vocabulary/tags for
the rw
application are returned, but you can use the optional app
or application
query parameters to load data for
a different application.
Getting a single vocabulary and its tags for a resource
Getting a single vocabulary and tags associated with a dataset
curl -L -X GET 'https://api.resourcewatch.org/dataset/<dataset-id>/vocabulary/<vocabulary-id>' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Getting a single vocabulary and tags associated with a layer
curl -L -X GET 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer_id>/vocabulary/<vocabulary-id>' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Getting a single vocabulary and tags associated with a widget
curl -L -X GET 'https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget_id>/vocabulary/<vocabulary-id>' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json'
Example response
{
"data": [
{
"id": "test1",
"type": "vocabulary",
"attributes": {
"tags": [
"tag1",
"tag2"
],
"name": "test1",
"application": "rw"
}
}
]
}
These endpoints allow you to get a single vocabulary and its tags for a single dataset, widget, or layer. By default,
vocabulary/tags for the rw
application are returned, but you can use the optional app
or application
query
parameters to load data for a different application.
Getting vocabularies and tags for multiple resources
Getting vocabularies and tags for multiple datasets
curl -X POST https://api.resourcewatch.org/v1/dataset/vocabulary/find-by-ids \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"ids": [<ids>]
}'
Getting vocabularies and tags for multiple widgets
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/vocabulary/find-by-ids \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"ids": [<ids>]
}'
Getting vocabularies and tags for multiple layers
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/vocabulary/find-by-ids \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"ids": [<ids>]
}'
Example response
{
"data": [
{
"type": "vocabulary",
"attributes": {
"resource": {
"id": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"type": "dataset"
},
"tags": [
"tag1",
"tag5"
],
"name": "vocabulary1",
"application": "cw"
}
},
{
"type": "vocabulary",
"attributes": {
"resource": {
"id": "ca6817fd-130c-47d4-8a95-303083b2cffa",
"type": "dataset"
},
"tags": [
"tag3",
"tag2"
],
"name": "test2",
"application": "gfw"
}
}
]
}
This group of endpoints allows you to retrieve the vocabularies for multiple resources of the same type using a single
request. It expects a body containing an ids
value, which can either be an array of ids, or a string containing
multiple ids separated by commas.
When retrieving widgets or layers using these endpoints, the dataset id passed in the URL is ignored, and will not affect the result of the endpoint.
These endpoints return vocabularies for all applications by default, but you can pass an optional application
value as
a query parameter to filter by a specific application.
Errors for getting vocabularies and tags for multiple resources
Error code | Error message | Description |
---|---|---|
404 | Bad request - Missing 'ids' from request body | Your request body is missing the ids field |
Creating vocabularies/tags for a resource
There are two types of endpoints for associating vocabulary/tags with resources: one allows you to create a single vocabulary (and its tags) for a resource, while the other supports creating multiple vocabularies/tags for a single resource. The primary use case for these endpoints is when you just created a new dataset/layer/widget, and want to add vocabularies/tags to them.
Creating a single vocabulary/tags for a resource
Creating a new vocabulary/tag for a dataset
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"tags": [<tags>]
}'
Creating a new vocabulary/tag for a widget
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"tags": [<tags>]
}'
Creating a new vocabulary/tag for a layer
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"tags": [<tags>]
}'
Example response
{
"data": [
{
"id": "testVocabulary1",
"type": "vocabulary",
"attributes": {
"tags": [
"tag1",
"tag2"
],
"name": "testVocabulary1",
"application": "rw"
}
},
{
"id": "testVocabulary2",
"type": "vocabulary",
"attributes": {
"tags": [
"tag3",
"tag2"
],
"name": "testVocabulary2",
"application": "rw"
}
}
]
}
This set of endpoints will allow you to create a new vocabulary/tags for a resource.
The request body must contain both an array of tags and the application
under which the vocabulary/tags are being
created. If a vocabulary with the same name already exists for the specified application, you will get an error message
- you can use the update endpoints to modify an existing vocabulary.
Assuming the creation was successful, the response will contain a list of all vocabularies and their respective tags associated with the specified resource, for all applications.
If you want to create new vocabulary/tags for your resources, you must have the necessary user account permissions. Specifically:
- the user must be logged in and belong to the same application as the resource
- the user must match one of the following:
- have role
ADMIN
- have role
MANAGER
and be the resource's owner (through theuserId
field of the resource)
- have role
An important note: When creating vocabulary/tags for a resource, the dataset id specified in the URL is validated, and the requests fail if a dataset with the given id does not exist. When creating a vocabulary for a widget or layer, you should ensure you specify the dataset id that matches that of the widget/layer, as that validation is not done automatically - this is a known limitation of the current implementation, and may be modified at any time, and invalid resources (those where the layer's/widget's dataset id does not match the dataset id defined in the resource) may be purged without prior warning.
Errors for creating a single vocabulary/tags for a resource
Error code | Error message | Description |
---|---|---|
400 | This relationship already exists | The resource already has a vocabulary with the same name for the specified application |
400 | - tags: tags can not be empty. - | tags body fields is empty |
400 | - tags: tags check failed. - | Either the tags or applications body fields are missing or have an invalid value |
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to create a vocabulary for a resource whose application value is not associated with your user account. |
404 | 404 - {\"errors\":[{\"status\":404,\"detail\":\"Dataset with id <dataset id> doesn't exist\"}]} |
You are trying to create a vocabulary for a dataset that doesn't exist. |
Creating multiple vocabularies/tags for a resource
Creating new vocabularies/tags for a dataset
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"vocabulary1": {
"tags":["tag1", "tag2"],
"application": "rw"
},
"vocabulary2": {
"tags":["tag3", "tag4"],
"application": "rw"
}
}'
Creating new vocabularies/tags for a widget
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"vocabulary1": {
"tags":["tag1", "tag2"],
"application": "rw"
},
"vocabulary2": {
"tags":["tag3", "tag4"],
"application": "rw"
}
}'
Creating new vocabularies/tags for a layer
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"vocabulary1": {
"tags":["tag1", "tag2"],
"application": "rw"
},
"vocabulary2": {
"tags":["tag3", "tag4"],
"application": "rw"
}
}'
Example response
{
"data": [
{
"id": "vocabulary1",
"type": "vocabulary",
"attributes": {
"tags": [
"tag1",
"tag2"
],
"name": "vocabulary1",
"application": "rw"
}
},
{
"id": "vocabulary2",
"type": "vocabulary",
"attributes": {
"tags": [
"tag3",
"tag4"
],
"name": "vocabulary2",
"application": "rw"
}
}
]
}
This set of endpoints will allow you to create multiple vocabularies/tags for a single resource in a single request.
The request body must contain at least one key, each of them corresponding to the names of the vocabularies you want to create. Each of these keys must have an object-type value, which in turn must contain the following keys:
tags
: an array of tagsapplication
: the application associated with the vocabulary.
You can create different vocabularies for different applications in a single request.
Assuming the creation was successful, the response will contain a list of all vocabularies and their respective tags associated with the specified resource, for all applications.
If you want to create new vocabulary/tags for your resources, you must have the necessary user account permissions. Specifically:
- the user must be logged in and belong to the same application as the resource
- the user must match one of the following:
- have role
ADMIN
- have role
MANAGER
and be the resource's owner (through theuserId
field of the resource)
- have role
An important note: When creating vocabularies/tags for a resource, the dataset id specified in the URL is validated, and the requests fail if a dataset with the given id does not exist. When creating a vocabulary for a widget or layer, you should ensure you specify the dataset id that matches that of the widget/layer, as that validation is not done automatically - this is a known limitation of the current implementation, and may be modified at any time, and invalid resources (those where the layer's/widget's dataset id does not match the dataset id defined in the resource) may be purged without prior warning.
Errors for creating a single vocabulary/tags for a resource
Error code | Error message | Description |
---|---|---|
400 | This relationship already exists | The resource already has one or more vocabularies with the same name(s) for the specified application(s) |
400 | - <value> : <value> check failed. - |
The body object has a <value> key which content is invalid (is not an object or is missing tags and/or application ). |
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to create a vocabulary for a resource whose application value is not associated with your user account. |
404 | 404 - {\"errors\":[{\"status\":404,\"detail\":\"Dataset with id <dataset id> doesn't exist\"}]} |
You are trying to create a vocabulary for a dataset that doesn't exist. |
Updating vocabularies/tags
If you have already associated vocabularies and tags to your resources and would like to modify those tags, the next set of endpoints is for you.
There are three types of endpoints for updating existing vocabulary/tags:
- endpoints that allow you to modify a single vocabulary (and its tags) for a resource
- endpoints that allow you to modify multiple vocabularies/tags for a single resource with a single request
- endpoint that allows you to add new tags to an existing vocabulary. This endpoint only exists for dataset resources, not widgets or layers.
Updating a single vocabulary/tags for a resource
Updating a vocabulary for a dataset
curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"tags": [<tags>]
}'
Updating a vocabulary for a widget
curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"tags": [<tags>]
}'
Updating a vocabulary for a layer
curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"application": <application>,
"tags": [<tags>]
}'
Example response
{
"data": [
{
"id": "vocabularyNameOne",
"type": "vocabulary",
"attributes": {
"tags": [
"tag1",
"tag2",
"tag3"
]
}
},
{
"id": "science",
"type": "vocabulary",
"attributes": {
"tags": [
"maths",
"astronomy"
]
}
},
{
"id": "aaa",
"type": "vocabulary",
"attributes": {
"tags": [
"biology",
"chemistry"
]
}
}
]
}
This set of endpoints will allow you to update the tags of an existing vocabulary/tags for a resource.
The request body must contain the application
of the vocabulary you want to update, and it will fail if you specify a
vocabulary name/application pair that does not exist. Additionally, it must contain a tags
array of strings with a
list of new tags to use. Any existing tags that already existed for that vocabulary (for that resource and application)
will be deleted, and replaced with the values you provide through this request.
Assuming the update was successful, the response will contain a list of all vocabularies and their respective tags associated with the specified resource, for all applications.
If you want to update vocabulary/tags for your resources, you must have the necessary user account permissions. Specifically:
- the user must be logged in and belong to the same application as the resource
- the user must match one of the following:
- have role
ADMIN
- have role
MANAGER
and be the resource's owner (through theuserId
field of the resource)
- have role
An important note: When updating vocabulary/tags for a resource, the dataset id specified in the URL is validated, and the requests fail if a dataset with the given id does not exist. When updating a vocabulary for a widget or layer, you should ensure you specify the dataset id that matches that of the widget/layer, as that validation is not done automatically - this is a known limitation of the current implementation, and may be modified at any time, and invalid resources (those where the layer's/widget's dataset id does not match the dataset id defined in the resource) may be purged without prior warning.
Errors for updating a single vocabulary/tags for a resource
Error code | Error message | Description |
---|---|---|
400 | - <value> : <value> check failed. - |
The body object has a <value> key which content is invalid (is not an object, or is missing tags and/or application ). |
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to update a vocabulary for a resource whose application value is not associated with your user account. |
404 | 404 - {\"errors\":[{\"status\":404,\"detail\":\"Dataset with id <dataset id> doesn't exist\"}]} |
You are trying to create a vocabulary for a dataset that doesn't exist. |
404 | Relationship between undefined and dataset - <dataset id> and dataset: <dataset id> doesn't exist |
You are trying to update a vocabulary that doesn't exist. Check your vocabulary name and application |
Updating multiple vocabularies/tags for a dataset
Updating multiple vocabularies/tags for a dataset
curl -X PUT https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"vocabulary1": {
"tags":["tag1", "tag2"],
"application": "rw"
},
"vocabulary2": {
"tags":["tag3", "tag4"],
"application": "rw"
}
}'
Example response
{
"data": [
{
"id": "vocabulary1",
"type": "vocabulary",
"attributes": {
"tags": [
"tag1",
"tag2"
],
"name": "vocabulary1",
"application": "rw"
}
},
{
"id": "vocabulary2",
"type": "vocabulary",
"attributes": {
"tags": [
"tag3",
"tag4"
],
"name": "vocabulary2",
"application": "rw"
}
}
]
}
Know issue warning There's a known issue where you may experience a 400 - This relationship already exists
error
when using this endpoint. There's currently no ETA for its resolution. As a workaround, we suggest updating vocabularies
individually.
This endpoint will allow you to update multiple vocabularies/tags for a single dataset in a single request.
The request body must contain at least one key, each of them corresponding to the names of the vocabularies you want to update. Each of these keys must have an object-type value, which in turn must contain the following keys:
tags
: an array of tags that will replace all the tags for that vocabulary (associated with that dataset and application)application
: the application associated with the vocabulary you want to update.
You can update different vocabularies for different applications in a single request.
Assuming the update was successful, the response will contain a list of all vocabularies and their respective tags associated with the specified dataset, for all applications.
If you want to update vocabulary/tags for your datasets, you must have the necessary user account permissions. Specifically:
- the user must be logged in and belong to the same application as the dataset
- the user must match one of the following:
- have role
ADMIN
- have role
MANAGER
and be the dataset's owner (through theuserId
field of the dataset)
- have role
Errors for updating multiple vocabularies/tags for a dataset
Error code | Error message | Description |
---|---|---|
400 | - tags: tags can not be empty. - | tags body fields is empty |
400 | - tags: tags check failed. - | Either the tags or applications body fields are missing or have an invalid value. |
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to update a vocabulary for a resource whose application value is not associated with your user account. |
404 | 404 - {\"errors\":[{\"status\":404,\"detail\":\"Dataset with id <dataset id> doesn't exist\"}]} |
You are trying to create a vocabulary for a dataset that doesn't exist. |
404 | Relationship between undefined and dataset - <dataset id> and dataset: <dataset id> doesn't exist |
You are trying to update a vocabulary that doesn't exist. Check your vocabulary name and application |
Concatenating tags to a dataset vocabulary
Concatenating tags to a dataset vocabulary
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary/<vocabulary-id>/concat \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"tags":["tag1", "tag2"],
"application": "rw"
}'
Example response
{
"data": [
{
"id": "vocabulary1",
"type": "vocabulary",
"attributes": {
"tags": [
"tag1",
"tag2"
],
"name": "vocabulary1",
"application": "rw"
}
},
{
"id": "vocabulary2",
"type": "vocabulary",
"attributes": {
"tags": [
"tag3",
"tag4"
],
"name": "vocabulary2",
"application": "rw"
}
}
]
}
This endpoint allows you to add more tags to an existing vocabulary for a dataset. The dataset is identified by the id
provided in the URL, while the specific vocabulary to update is determined by the vocabulary id in the URL and
the application
value in the POST body - if no matching vocabulary is found, a new one is created. The body should
also contain an array of tags
which will be appended to the target vocabulary. The endpoint validates and requires
that a dataset with the provided id exists. Any tags that exist both in the request and in the vocabulary prior to the
concat are merged - the resulting tags list won't have duplicated values.
Should the request be successful, the response will have a complete list of vocabularies/tags for the dataset, for all applications.
Errors for concatenating tags to a dataset vocabulary
Error code | Error message | Description |
---|---|---|
400 | - tags: tags can not be empty. - | tags body fields is empty |
400 | - tags: tags check failed. - | Either the tags or applications body fields are missing or have an invalid value. |
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to concatenate a vocabulary for a dataset whose application value is not associated with your user account. |
404 | 404 - {\"errors\":[{\"status\":404,\"detail\":\"Dataset with id <dataset id> doesn't exist\"}]} |
The dataset specified in the request URL doesn't exist. |
Cloning vocabularies/tags for a dataset
Cloning vocabularies/tags for a dataset
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary/clone/dataset \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"newDataset": "<target-dataset-id>"
}'
Example response
{
"data": [
{
"id": "vocabulary1",
"type": "vocabulary",
"attributes": {
"tags": [
"tag1",
"tag2"
],
"name": "vocabulary1",
"application": "rw"
}
},
{
"id": "vocabulary2",
"type": "vocabulary",
"attributes": {
"tags": [
"tag3",
"tag4"
],
"name": "vocabulary2",
"application": "rw"
}
}
]
}
This endpoint allows you to clone all vocabularies/tags for all applications, for a single dataset.
The URL should include the id of the source dataset, while the POST body should include a newDataset
field containing
the id of the target dataset. The target dataset id is not validated - the cloning will still occur even if the target
id doesn't correspond to an existing dataset.
The dataset you use as the target dataset can have existing vocabularies - the cloning operation is an additive, and will not update nor destroy any existing vocabulary that may have already been associated with the target dataset. However, the cloning operation will fail if it tries to overwrite a vocabulary (ie. if the target dataset already has a vocabulary with the same name and application as one being created as part of the cloning). This failure is not atomic - the target dataset may end up with some of the vocabularies of the source dataset. It's up to you, as the RW API user, to both manage these collisions, and recover from them should they happen.
Assuming the cloning was successful, the response will contain a list of all vocabularies (both newly cloned and preexisting) and their respective tags, for all applications, for the target dataset.
If you want to clone vocabularies/tags for your datasets, you must have the necessary user account permissions. Specifically:
- the user must be logged in and belong to the same application as the source dataset
- the user must match one of the following:
- have role
ADMIN
- have role
MANAGER
and be the resource's owner (through theuserId
field of the resource)
- have role
An important note: When cloning vocabularies/tags for a dataset, the source dataset id specified in the URL is validated, and the requests fails if a dataset with the given id does not exist. When creating a vocabulary for a widget or layer, you should ensure you specify the dataset id that matches that of the widget/layer, as that validation is not done automatically - this is a known limitation of the current implementation, and may be modified at any time, and invalid resources (those where the layer's/widget's dataset id does not match the dataset id defined in the resource) may be purged without prior warning.
Errors for cloning vocabularies/tags for a dataset
Error code | Error message | Description |
---|---|---|
400 | This relationship already exists | The target dataset already has one or more vocabularies with the same name(s) and application(s) as the source dataset. |
400 | - newDataset: newDataset can not be empty. - | The body object must have a newDataset key with the id of the target dataset. |
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to clone vocabulary for a source dataset whose application value is not associated with your user account. |
404 | 404 - {\"errors\":[{\"status\":404,\"detail\":\"Dataset with id <dataset id> doesn't exist\"}]} |
You are trying to clone a vocabularies for a source dataset that doesn't exist. |
Deleting vocabularies/tags for a resource
There are two types of endpoints for deleting vocabularies/tags: one allows you to delete a single vocabulary (and its tags) for a resource, while the other supports deleting all the vocabularies/tags for a single resource. Some use cases for these include deleting vocabularies prior to deleting the actual resource, or typical housekeeping tasks you may want to carry out on your data.
Deleting a single vocabulary/tags for a resource
Deleting a single vocabulary/tag for a dataset
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>"
Deleting a single vocabulary/tag for a widget
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>"
Deleting a single vocabulary/tag for a layer
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>"
Example response
{
"data": [
{
"id": "country",
"type": "vocabulary",
"attributes": {
"tags": [
"Spain",
"Italy",
"Portugal"
]
}
},
{
"id": "color",
"type": "vocabulary",
"attributes": {
"tags": [
"red",
"green",
"blue"
]
}
}
]
}
This set of endpoints will allow you to delete a single vocabulary and its tags, for a resource.
As a query param, you can optionally provide an app
or application
values, to identify the application of the
vocabulary to delete - by default, rw
is assumed.
Assuming the operation was successful, the response will contain a list of all vocabularies and their respective tags associated with the specified resource, for all applications - including the vocabulary that was deleted.
If you want to delete vocabularies/tags for your resources, you must have the necessary user account permissions. Specifically:
- the user must be logged in and belong to the same application as the resource
- the user must match one of the following:
- have role
ADMIN
- have role
MANAGER
and be the resource's owner (through theuserId
field of the resource)
- have role
An important note: When deleting vocabulary/tags for a resource, the dataset id specified in the URL is validated, and the requests fail if a dataset with the given id does not exist. When deleting a vocabulary for a widget or layer, you should ensure you specify the dataset id that matches that of the widget/layer, as that validation is not done automatically - this is a known limitation of the current implementation and may be modified at any time.
Errors for deleting a single vocabulary/tags for a resource
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to delete a vocabulary for a resource whose application value is not associated with your user account. |
404 | 404 - {\"errors\":[{\"status\":404,\"detail\":\"Dataset with id <dataset id> doesn't exist\"}]} |
You are trying to create a vocabulary for a dataset that doesn't exist. |
404 | Relationship between <vocabulary-id> and dataset - |
You are trying to delete a vocabulary that doesn't exist. |
Deleting all vocabulary/tags for a resource
Deleting all vocabularies/tag for a dataset
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary \
-H "x-api-key: <your-api-key>"
Deleting all vocabularies/tag for a widget
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary \
-H "x-api-key: <your-api-key>"
Deleting all vocabularies/tag for a layer
curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary \
-H "x-api-key: <your-api-key>"
Example response
{
"data": [
{
"id": "country",
"type": "vocabulary",
"attributes": {
"tags": [
"Spain",
"Italy",
"Portugal"
]
}
},
{
"id": "color",
"type": "vocabulary",
"attributes": {
"tags": [
"red",
"green",
"blue"
]
}
}
]
}
Know issue warning There's a known issue where you may experience
a 404 - Relationship between undefined and dataset - <dataset id> and dataset: <dataset id> doesn't exist
error when
using these endpoints. If you experience this issue, keep in mind that some vocabularies may have already been deleted,
despite the error message. Those are not recoverable. There's currently no ETA for its resolution. As a workaround, we
suggest deleting vocabularies individually.
This set of endpoints will allow you to delete all vocabularies and their tags for a resource.
Assuming the operation was successful, the response will contain a list of all vocabularies and their respective tags associated with the specified resource, for all applications - all of which were already deleted.
If you want to delete vocabularies/tags for your resources, you must have the necessary user account permissions. Specifically:
- the user must be logged in and belong to the same application as the resource
- the user must match one of the following:
- have role
ADMIN
- have role
MANAGER
and be the resource's owner (through theuserId
field of the resource)
- have role
An important note: When deleting vocabulary/tags for a resource, the dataset id specified in the URL is validated, and the requests fail if a dataset with the given id does not exist. When deleting vocabularies for a widget or layer, you should ensure you specify the dataset id that matches that of the widget/layer, as that validation is not done automatically - this is a known limitation of the current implementation and may be modified at any time.
Errors for deleting all vocabularies/tags for a resource
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You are not authenticated. |
403 | Forbidden | You are trying to delete vocabularies for a resource whose application value is not associated with your user account. |
404 | 404 - {\"errors\":[{\"status\":404,\"detail\":\"Dataset with id <dataset id> doesn't exist\"}]} |
You are trying to delete vocabularies for a dataset that doesn't exist. |
Getting vocabularies and tags across resources
There are several endpoints you can use to retrieve vocabularies and their details, independently from the resources to which they are associated
Getting all vocabularies
Getting all vocabularies, their resources and tags
curl -X GET https://api.resourcewatch.org/v1/vocabulary \
-H "x-api-key: <your-api-key>"
Example response
{
"data": [
{
"id": "test1",
"type": "vocabulary",
"attributes": {
"resources": [
{
"tags": [
"tag1",
"tag2"
],
"id": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"type": "dataset"
},
{
"tags": [
"tag1",
"tag2"
],
"id": "0002ed77-f07d-4231-b4eb-cfda77eeafe5",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"type": "layer"
},
{
"tags": [
"tag1",
"tag2"
],
"id": "0002ed77-f07d-4231-b4eb-cfda77eeafe5",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e91",
"type": "layer"
}
],
"name": "test1",
"application": "rw"
}
},
{
"id": "forestChange",
"type": "vocabulary",
"attributes": {
"resources": [],
"name": "forestChange",
"application": "gfw"
}
}
]
}
This endpoint will give you a list of vocabularies. Inside each, you'll find a list of resources, identifying the resource id, type, associated dataset (if the resource is a dataset, the dataset id will be equal to the resource id)and the tags that said vocabulary associates to that resource
You can optionally pass a limit
integer value as a query parameter if you wish to limit the number of vocabularies
returned by calls to this endpoint. There is not full blown pagination support for this endpoint.
You can also optionally pass a env
string value as a query parameter if you wish to filter the underlying lists of
resources by their environment.
You can filter by multiple env
values (OR
logic) using a comma separated list of values.
Getting a single vocabulary
Getting a single vocabulary, all its resources and tags
curl -X GET https://api.resourcewatch.org/v1/vocabulary/<vocabulary-id> \
-H "x-api-key: <your-api-key>"
Example response
{
"data": [
{
"id": "test1",
"type": "vocabulary",
"attributes": {
"resources": [
{
"tags": [
"tag1",
"tag2"
],
"id": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"type": "dataset"
},
{
"tags": [
"tag1",
"tag2"
],
"id": "0002ed77-f07d-4231-b4eb-cfda77eeafe5",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"type": "layer"
},
{
"tags": [
"tag1",
"tag2"
],
"id": "0002ed77-f07d-4231-b4eb-cfda77eeafe5",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e91",
"type": "layer"
}
],
"name": "test1",
"application": "rw"
}
}
]
}
This endpoint will give you the details for a single vocabulary, identified by name. In it, you'll find a list of resources, identified by the resource id, type, associated dataset (if the resource is a dataset, the dataset id will be equal to the resource id) and the tags that said vocabulary associates to that resource.
Keep in mind that there's an implicit application filter applied to the data returned - only vocabularies and
associations for the corresponding application are returned. By default, this filter uses the rw
value, but you can
modify it with the application
or app
query parameters.
You can also optionally pass a env
string value as a query parameter if you wish to filter the underlying lists of
resources by their environment.
You can filter by multiple env
values (OR
logic) using a comma separated list of values.
Getting tags for single vocabulary
Getting the tags for a single vocabulary
curl -X GET https://api.resourcewatch.org/v1/vocabulary/<vocabulary-id>/tags \
-H "x-api-key: <your-api-key>"
Example response
{
"data": [
"tag11",
"tag21",
"tag1",
"tag2"
]
}
This endpoint will give you a flat list of all the tags associated with the specified vocabulary.
Keep in mind that there's an implicit application filter applied to the data returned - only tags for the corresponding
application are returned. By default, this filter uses the rw
value, but you can modify it with the application
or app
query parameters.
Getting resources by vocabulary and tag
Getting datasets by vocabulary and tag
curl -X GET https://api.resourcewatch.org/v1/dataset/vocabulary/find?<vocabulary-id>=<tag> \
-H "x-api-key: <your-api-key>"
Getting widgets by vocabulary and tag
curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/vocabulary/find?<vocabulary-id>=<tag> \
-H "x-api-key: <your-api-key>"
Getting layers by vocabulary and tag
curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/vocabulary/find?<vocabulary-id>=<tag> \
-H "x-api-key: <your-api-key>"
Example response
{
"data": [
{
"type": "vocabulary",
"attributes": {
"resources": [
{
"id": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e90",
"type": "dataset"
},
{
"id": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e92",
"dataset": "7fa6ec77-5ab0-43f4-9a4c-a3d19bed1e92",
"type": "dataset"
}
]
}
}
]
}
This is perhaps the most useful endpoint when it comes to data discovery - it allows you to specify a vocabulary name and a tag or set of tags, and see resources that match that search criteria.
All three endpoints require at least one query parameter, in the format <vocabulary-id>=<tag>
. This will return all
resources of that type, associated with a vocabulary with the name vocabulary-id
, and having a tag with value tag
for that vocabulary.
You can expand these filters by specifying multiple tags for a single vocabulary, using
the <vocabulary-id>=<tag1>,<tag2>
syntax. This type of filter will return resources that have either tag1
or tag2
for vocabulary vocabulary-id
You can also filter by multiple vocabularies using multiple query parameters with the formats described above. The result will contain any resource that matches either vocabulary/tags filters.
You can also optionally pass a env
string value as a query parameter if you wish to filter the underlying lists of
resources by their environment.
You can filter by multiple env
values (OR
logic) using a comma separated list of values.
The filters described above do not take into account the application
for which the vocabularies were defined. If you
wish to only see results matching the vocabulary of a specific application, you can pass either an app
or application
query parameter with the value of the application you wish to filter by.
Errors for getting resources by vocabulary and tag
Error code | Error message | Description |
---|---|---|
400 | Vocabulary and Tags are required in the queryParams | You must specify at least one vocabulary/tag to filter by. |
Geostore
What is Geostore
If you are new to the RW API, or want to learn more about the concept of a geostore, we strongly encourage you to read the geostore concept documentation first. It gives you a brief and clear description of what a geostore is, and what it can do for you.
Once you've read that section, you can come back here to learn more details about using the RW API Geostore feature, which aims to provide a comprehensive way to communicate geographic vector-data structures described using GeoJSON between platforms and microservices.
Geostore objects, describing things like the boundaries of countries, protected areas or land use types, have been uploaded by WRI, its partner organizations, or by API users like you. They are particularly useful for combining with the range of datasets available in the RW API, for example to create national summaries or for making a specific analysis within your own user-defined region.
To find out more about accessing the geostore objects already available on the RW API, check out the documentation
on getting geostore objects. A quick, visual way to view an existing geostore
is by using the /geostore/:id/view
endpoint.
You can also create you own geostore objects on the RW API, if you'd like to share your data with the world, or if you are looking to use the RW API and its features to gain insights into your data.
What are Geostore objects
Geostore objects contain GeoJSON FeatureCollection
objects (geojson
), with
a single Feature
whose Geometry
has been checked for geometric validity, and have been assigned an
identifier (id
, hash
) upon creation.
This identifier is a 128-bit hash generated by passing the pre-processed GeoJSON stringthrough the MD5 message-digest algorithm. This means that each identifier is a unique fingerprint of the GeoJSON string.
If you add an exact copy of your GeoJSON string, it will generate the same hash. But if any GeoJSON property is changed in any way, the generated hash will be different. Hence, the Geostore identifier provides the RW API a way to ensure that platforms and microservices are using exactly the same geographic structures. This also means that Geostore objects are static and cannot be modified.
To prevent overwriting of existing geostore objects, they contain a field indicated if the object is locked to
editing (lock
); which can be set when creating geostore objects.
Also, during object creation the minimum bounding box enclosing all geometries in the GeoJSON (bbox
), and, if the
geometries are type (Multi) Polygon, total surface area in hectares of the geometries (areaHa
) are added to the
geostore. Note these values are not calculated if supplied when creating a geostore.
Geostore objects can also
be created by getting a GeoJSON from provider API; in which case
the geostore will also include an object which gives information used to connect to the provider data
source (provider
). At present the only provider definition supported is a Carto table,
using "type": "carto"
.
Finally, all geostore objects have a property for storing application specific attributes (info
), which has no
formalized schema. Here, fields used for indexing, and metadata, related to use on different platforms are added.
Overview of a geostore object
Field | Type | Description |
---|---|---|
id |
string | A unique identifier for the geostore object in the form of a 128 bit MD5 hash generated from the GeoJSON object. |
hash |
string | A unique identifier for the geostore object in the form of a 128 bit MD5 hash generated from the GeoJSON object. |
geojson |
object | A valid FeatureCollection , Feature , or Geometry GeoJSON object. |
provider |
object | Optional provider definition used to fetch GeoJSON data from APIs. |
lock |
string | Optional indication if the object is locked for editing |
areaHa |
number | Optional total surface area in hectares of all Polygon and MultiPolygon geometries in the GeoJSON object. |
bbox |
array | Array describing the minimum bounding box enclosing all of the geometries in the GeoJSON object, expressed as an array of the form min Longitude , min Latitude , max Longitude , max Latitude. |
info |
object | Object that defines application specific properties, for example used for indexing or related to editing of the geostore object. |
Overview of available endpoints
The Geostore API consists of a number of endpoints to help users interact with geostore objects. Many of them are essentially helpers to make it easy to access geometries from useful data sources, such as:
- Administrative areas (countries, regions, ect.) from the Database of Global Administrative Areas (GADM).
- Protected areas (world heritage sites, national parks, ect.) from the The World Database on Protected Areas.
- Land activity/use types (logging, mining, ect.) from the WRI managed forest, mining, and oil palm concessions, and WWF/RESOLVE tiger conservation datasets.
As these data sets are periodically updated, these "helper" endpoints are updated to use the latest data. So unless you really need an older version of a data set, such as GADM, you should always use the latest endpoint version. See the table below to get an overview of what can be done; click on the description to get more details.
Comparison of endpoint versions
Version | Description |
---|---|
v1 |
GADM version 2.8. |
v2 |
GADM version 3.6. |
Overview of endpoints
Method | Path | Description |
---|---|---|
POST | /v1/geostore |
Create a geostore object |
GET | /v2/geostore/:id |
Get a geostore object by Geostore id |
POST | /v2/geostore/find-by-ids |
Get geostore objects by Geostore ids |
GET | /v2/geostore/:id/view |
Get a geostore object by Geostore id and view at GeoJSON.io |
GET | /v2/geostore/admin/list |
Get all Geostore ids, names and country codes |
GET | /v2/geostore/admin/:iso |
Get a geostore object by country code |
GET | /v2/geostore/admin/:iso/:id1 |
Get a geostore object by country code and GADM admin 1 id |
GET | /v2/geostore/admin/:iso/:id1/:id2 |
Get a geostore object by country code, GADM admin 1 and admin 2 ids |
GET | /v2/geostore/wdpa/:id |
Get a geostore object by WDPA id |
GET | /v2/geostore/use/:name/:id |
Get a geostore object by Land Use Type name and id |
POST | /v1/geostore/area |
Calculate the area of a provided Geostore object |
Create a geostore object
Geostore objects can be created in the RW API Geostore using a valid GeoJSON object or by selecting a row from a Carto table.
Errors for creating a geostore object
Error code | Error message | Description |
---|---|---|
400 | <field> : <field> can not be empty |
Your are missing a required field value. |
400 | <field> : empty or invalid <field> |
The provided value for <field> is invalid. This is usually happens if an invalid value type is provided, but certain fields use more advanced validation rules, that may produce this error message if validation fails (ie: geojson , which must be type: FeatureCollection , Feature , or Geometry ). |
400 | provider: must be valid |
Your provider type value is invalid. The <list of valid providers> will contain the list of providers that are supported. |
Create using a GeoJSON
Geostore objects can be created via the POST geostore
endpoint, which accepts as body a GeoJSON object (<geojson>
).
This must be a FeatureCollection
, Feature
or Geometry
. If the object is correctly added to the Geostore a 200
response is returned, as well as the new geostore object.
Example request pattern
curl -X POST https://api.resourcewatch.org/v1/geostore/ \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{"geojson": <geojson>}'
Example URL request
curl --location --request POST 'https://api.resourcewatch.org/v1/geostore' \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
--data-raw '{
"geojson":{
"type":"FeatureCollection",
"features":[
{
"type":"Feature",
"properties":{
},
"geometry":{
"type":"Polygon",
"coordinates":[
[
[
-4.4549560546875,
40.84706035607122
],
[
-4.4549560546875,
41.30257109430557
],
[
-3.5211181640624996,
41.30257109430557
],
[
-3.5211181640624996,
40.84706035607122
],
[
-4.4549560546875,
40.84706035607122
]
]
]
}
}
]
}
}'
Example response
{
"data": {
"type": "geoStore",
"id": "4b25676360d8bbd5106a022103e0cd28",
"attributes": {
"geojson": {
"crs": {},
"type": "FeatureCollection",
"features": [
{
"geometry": {
"coordinates": [
[
[
-4.454956055,
40.847060356
],
[
-4.454956055,
41.302571094
],
[
-3.521118164,
41.302571094
],
[
-3.521118164,
40.847060356
],
[
-4.454956055,
40.847060356
]
]
],
"type": "Polygon"
},
"type": "Feature"
}
]
},
"hash": "4b25676360d8bbd5106a022103e0cd28",
"provider": {},
"areaHa": 397372.34118232,
"bbox": [
-4.454956055,
40.847060356,
-3.521118164,
41.302571094
],
"lock": false,
"info": {
"use": {}
}
}
}
}
Create using a provider definition
Geostore objects can be created via the POST geostore
endpoint, which accepts as body a provider definition
object (<provider>
), the API then fetches a GeoJSON from the provider, and adds it to the Geostore. If the object is
correctly added to the Geostore a 200
response is returned, as well as the new geostore object. At present the only
provider definition supported is a Carto table, using "type": "carto"
.
If the specified table
, user
, or filter
is not recognized a 400
response is returned with the error message "
Geojson not found".
Overview of provider object
Field | Type | Description |
---|---|---|
type |
string | Keyword of the provider |
table |
string | Name of the provider table |
user |
string | Provider username |
filter |
string | Provider specific filter |
Example request pattern
curl -X POST https://api.resourcewatch.org/v1/geostore \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{"provider": <provider>}'
Example URL request
curl -X POST https://api.resourcewatch.org/v1/geostore \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"provider":{
"type": "carto",
"table": "gfw_mining",
"user": "wri-01",
"filter": "cartodb_id=573"
}
}'
Example response
{
"data": {
"type": "geoStore",
"id": "b3b2875affa75f145b4f3e5289fd47d7",
"attributes": {
"geojson": {
"crs": {},
"type": "FeatureCollection",
"features": [
{
"geometry": {
"coordinates": [
[
14.26438308756265,
14.062500000000002
],
[
5.266007882805498,
2.8125
],
[
44.84029065139799,
16.523437500000004
],
[
-7.362466865535738,
-3.1640625000000004
]
],
"type": "MultiPoint"
},
"type": "Feature",
"properties": null
}
]
},
"hash": "b3b2875affa75f145b4f3e5289fd47d7",
"provider": {
"type": "carto",
"table": "gfw_mining",
"user": "wri-01",
"filter": "cartodb_id=573"
},
"areaHa": 0,
"bbox": [
-102.65625,
-29.688052749856787,
45.87890625,
57.79794388498275
],
"lock": false,
"info": {
"use": {}
}
}
}
}
Getting geostore objects
The fundamental way to read geometries from the RW APIs Geostore is by using Geostore ids. Using these identifiers you
can ensure that you are always retrieving exactly the same Feature
. If
you add your own geostore objects you will be
using these endpoints.
Alternatively you may prefer to get selected geometries from the datasets already added to the RW API Geostore, such as
the latest administrative areas, protected areas, or land use types.
Note, these are periodically updated, and potentially both geometries and ids may change between versions. By design
this means that, for example, the Geostore ids of countries change between versions. These geometries can also be
simplified when reading them from the Geostore, using the parameter ?simplify=<value>
, where <value>
is given to the
simplification algorithm - 0.005
usually works well.
Get a geostore object by Geostore id
Geostore objects can be retrieved via the GET geostore/:id
endpoint, which returns a single object selected from the
Geostore using a single Geostore id (<id>
).
Example request pattern
curl -X GET https://api.resourcewatch.org/v2/geostore/<id> \
-H "x-api-key: <your-api-key>"
Example URL request
curl -X GET https://api.resourcewatch.org/v2/geostore/ca38fa80a4ffa9ac6217a7e0bf71e6df \
-H "x-api-key: <your-api-key>"
Example response
{
"data": {
"type": "geoStore",
"id": "ca38fa80a4ffa9ac6217a7e0bf71e6df",
"attributes": {
"geojson": {
"crs": {},
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Polygon",
"coordinates": [
[
[
-5.273512601852417,
42.81137220349083
],
[
-5.273512601852417,
42.811803118457306
],
[
-5.272732079029083,
42.811803118457306
],
[
-5.272732079029083,
42.81137220349083
],
[
-5.273512601852417,
42.81137220349083
]
]
]
}
}
]
},
"hash": "ca38fa80a4ffa9ac6217a7e0bf71e6df",
"provider": {},
"areaHa": 0.3057556230214663,
"bbox": [
-5.273512601852417,
42.81137220349083,
-5.272732079029083,
42.811803118457306
],
"lock": false,
"info": {
"use": {}
}
}
}
}
Errors for getting geostore objects by id
Error code | Error message | Description |
---|---|---|
404 | Geostore not found. | A geostore with the id provided was not found. |
Get geostore by Geostore id and view at GeoJSON.io
Geostore objects can be retrieved and viewed via the GET geostore/:id/view
endpoint, which returns a URL allowing
viewing of a single geostore object selected by Geostore id (<id>
) at
GeoSON.io.
Example request pattern
curl -X GET https://api.resourcewatch.org/v2/geostore/<id>/view \
-H "x-api-key: <your-api-key>"
Example URL request
curl -X GET https://api.resourcewatch.org/v2/geostore/ca38fa80a4ffa9ac6217a7e0bf71e6df/view \
-H "x-api-key: <your-api-key>"
Example response
{
"view_link": "http://geojson.io/#data=data:application/json,%7B%22crs%22%3A%7B%7D%2C%22type%22%3A%22FeatureCollection%22%2C%22features%22%3A%5B%7B%22type%22%3A%22Feature%22%2C%22geometry%22%3A%7B%22type%22%3A%22Polygon%22%2C%22coordinates%22%3A%5B%5B%5B-5.273512601852417%2C42.81137220349083%5D%2C%5B-5.273512601852417%2C42.811803118457306%5D%2C%5B-5.272732079029083%2C42.811803118457306%5D%2C%5B-5.272732079029083%2C42.81137220349083%5D%2C%5B-5.273512601852417%2C42.81137220349083%5D%5D%5D%7D%2C%22properties%22%3Anull%7D%5D%7D"
}
Errors for viewing geostore objects by id
Error code | Error message | Description |
---|---|---|
400 | Geometry too large, please try again with a smaller geometry. | The Geostore provided is too large (more than 150k chars when stringified) and cannot be viewed. |
404 | Geostore not found. | A geostore with the id provided was not found. |
Get geostore objects by Geostore ids
Many geostore objects can be retrieved via the POST geostore/find-by-ids
endpoint, which returns an array of a
geostore objects selected by an array of Geostore ids ([<id>, <id>]
). In
case of success, the returned response will contain an array with all of the geostore objects found and summary info is
available in the root property info
.
Example request pattern
curl -X POST https://api.resourcewatch.org/v2/geostore/find-by-ids \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{"geostores": [<id>, <id>]}'
Example URL request
curl -X POST https://api.resourcewatch.org/v2/geostore/find-by-ids \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{"geostores": ["35a6d982388ee5c4e141c2bceac3fb72", "8f77fe62cf15d5098ba0ee11c5126aa6"]}'
Example response (coordinates are truncated)
{
"data": [
{
"geostoreId": "35a6d982388ee5c4e141c2bceac3fb72",
"geostore": {
"data": {
"type": "geoStore",
"id": "35a6d982388ee5c4e141c2bceac3fb72",
"attributes": {
"geojson": {
"crs": {},
"type": "FeatureCollection",
"features": [
{
"geometry": {
"coordinates": [
...
],
"type": "MultiPolygon"
},
"type": "Feature"
}
]
},
"hash": "35a6d982388ee5c4e141c2bceac3fb72",
"provider": {},
"areaHa": 50662609.25209112,
"bbox": [
-18.1604175567627,
27.6384716033936,
4.32819509506226,
43.7915267944337
],
"lock": false,
"info": {
"use": {},
"iso": "ESP",
"name": "Spain"
}
}
}
}
},
{
"geostoreId": "8f77fe62cf15d5098ba0ee11c5126aa6",
"geostore": {
"data": {
"type": "geoStore",
"id": "8f77fe62cf15d5098ba0ee11c5126aa6",
"attributes": {
"geojson": {
"crs": {},
"type": "FeatureCollection",
"features": [
{
"geometry": {
"coordinates": [
...
],
"type": "MultiPolygon"
},
"type": "Feature"
}
]
},
"hash": "8f77fe62cf15d5098ba0ee11c5126aa6",
"provider": {},
"areaHa": 54935531.53854849,
"bbox": [
-5.14375114440907,
41.3337516784668,
9.5604162216186,
51.08939743042
],
"lock": false,
"info": {
"use": {},
"iso": "FRA",
"name": "France"
}
}
}
}
}
],
"info": {
"found": 2,
"foundIds": [
"35a6d982388ee5c4e141c2bceac3fb72",
"8f77fe62cf15d5098ba0ee11c5126aa6"
],
"returned": 2
}
}
Errors for getting multiple geostore objects by id
Error code | Error message | Description |
---|---|---|
404 | Geostore not found. | A geostore with the id provided was not found. |
Get all Geostore ids, names and country codes
All of the Geostore ids, names, and country ISO 3166-1 alpha-3 code values available from the GADM data source in the
Geostore can be retrieved via the GET geostore/admin/list
endpoint, which returns an array of objects with the
properties geostoreId
, name
, and iso
.
Example URL request
curl -X GET https://api.resourcewatch.org/v2/geostore/admin/list \
-H "x-api-key: <your-api-key>"
Example response
{
"data": [
{
"geostoreId": "35a6d982388ee5c4e141c2bceac3fb72",
"iso": "ESP",
"name": "Spain"
},
{
"geostoreId": "8f77fe62cf15d5098ba0ee11c5126aa6",
"iso": "FRA",
"name": "France"
},
{
"geostoreId": "1d568c183033da6c17cc28c4aecf1bcf",
"iso": "cod",
"name": "Democratic Republic of the Congo"
}
]
}
Note - This endpoint does not return a unique array of iso codes and names.
Getting predefined geostores for commonly used geometries
The endpoints described below allow API users to retrieve geostores representative of the boundaries of countries, GADM admin regions, WDPA and land use areas. These endpoints can be used as utility methods to retrieve commonly used geometries.
Get geostore by country code
Example request pattern
curl -X GET https://api.resourcewatch.org/v2/geostore/admin/<iso> \
-H "x-api-key: <your-api-key>"
Example URL request
curl -X GET https://api.resourcewatch.org/v2/geostore/admin/ESP \
-H "x-api-key: <your-api-key>"
Example response (note coordinates are truncated)
{
"data": {
"type": "geoStore",
"id": "56f9a919e061d5edd10c042a8fcd31b6",
"attributes": {
"geojson": {
"crs": {},
"type": "FeatureCollection",
"features": [
{
"geometry": {
"coordinates": [
...
],
"type": "MultiPolygon"
},
"type": "Feature",
"properties": null
}
]
},
"hash": "56f9a919e061d5edd10c042a8fcd31b6",
"provider": {},
"areaHa": 50662609.2516529,
"bbox": [
-18.160417557,
27.638471603,
4.328195095,
43.791526794
],
"lock": false,
"info": {
"use": {},
"iso": "ESP",
"id1": null,
"id2": null,
"gadm": "2.8",
"name": "Spain"
}
}
}
}
Use the GET geostore/admin/:iso
endpoint to retrieve a geostore object representative of the boundaries of the country
with ISO 3166-1 alpha-3 code (<iso>
). The returned geometries can
be simplified using the parameter ?simplify=<value>
. Where <value>
is given to the simplification algorithm- 0.005
usually works well.
Note - The source of the geometries is GADM version 3.6.
Errors for getting geostore objects by country code
Error code | Error message | Description |
---|---|---|
404 | Geostore not found. | A geostore for the country ISO code provided was not found. |
Get geostore by country code and GADM admin 1 id
Example request pattern
curl -X GET https://api.resourcewatch.org/v2/geostore/admin/<iso>/<id1> \
-H "x-api-key: <your-api-key>"
Example URL request
curl -X GET https://api.resourcewatch.org/v2/geostore/admin/ESP/9 \
-H "x-api-key: <your-api-key>"
Example response (note coordinates are truncated)
{
"data": {
"type": "geoStore",
"id": "7d1534d7c24b2f907c4ae37d11fc51fe",
"attributes": {
"geojson": {
"crs": {},
"type": "FeatureCollection",
"features": [
{
"geometry": {
"coordinates": [
...
],
"type": "MultiPolygon"
},
"type": "Feature",
"properties": null
}
]
},
"hash": "7d1534d7c24b2f907c4ae37d11fc51fe",
"provider": {},
"areaHa": 1036273.8136673134,
"bbox": [
-2.500030994,
41.909896851,
-0.726752043,
43.314189911
],
"lock": false,
"info": {
"use": {},
"iso": "ESP",
"id1": 9,
"id2": null,
"gadm": "2.8"
}
}
}
}
Use the GET geostore/admin/:iso/:id1
endpoint to retrieve a geostore object representative of the boundaries of
a ISO 3166-1 alpha-3 code (<iso>
)
and GADM admin level 1 id (<id1>
). The returned geometries can be simplified using
the parameter ?simplify=<value>
. Where <value>
is given to the simplification algorithm- 0.005 usually works well.
Note - The source of the geometries is GADM version 3.6.
Errors for getting geostore objects by country code and GADM admin 1 id
Error code | Error message | Description |
---|---|---|
404 | Geostore not found. | A geostore for the combination of country ISO code and GADM admin 1 id provided was not found. |
Get geostore by country code, GADM admin 1 and admin 2 ids
Example request pattern
curl -X GET https://api.resourcewatch.org/v2/geostore/admin/<iso>/<id1>/<id2> \
-H "x-api-key: <your-api-key>"
Example URL request
curl -X GET https://api.resourcewatch.org/v2/geostore/admin/ESP/1/2 \
-H "x-api-key: <your-api-key>"
Example response
{
"data": {
"type": "geoStore",
"id": "214e74a9e8702f78354ed5cb0297c10d",
"attributes": {
"geojson": {
"crs": {},
"features": [
{
"geometry": {
"coordinates": [
...
],
"type": "MultiPolygon"
},
"properties": null,
"type": "Feature"
}
],
"type": "FeatureCollection"
},
"hash": "214e74a9e8702f78354ed5cb0297c10d",
"provider": {},
"areaHa": 744195.8099038196,
"bbox": [
-6.47347212,
35.9995842,
-5.08662891,
37.05246735
],
"lock": false,
"info": {
"use": {},
"simplifyThresh": 0.00005,
"gadm": "3.6",
"name": "Cádiz",
"id2": 2,
"id1": 1,
"iso": "ESP"
}
}
}
}
Use the GET geostore/admin/:iso/:id1/:id2
endpoint to retrieve a geostore object representative of the boundaries of
a ISO 3166-1 alpha-3 code (<iso>
), GADM admin level 1
id (<id1>
), and GADM admin level 2 id (<id2>
). The returned geometries can be
simplified using the parameter ?simplify=<value>
. Where <value>
is given to the simplification algorithm- 0.005
usually works well.
Note - The source of the geometries is GADM version 3.6.
Errors for getting geostore objects by country code, GADM admin 1 id and admin 2 id
Error code | Error message | Description |
---|---|---|
404 | Geostore not found. | A geostore for the combination of country ISO code, GADM admin 1 id and admin 2 id provided was not found. |
Get geostore by World Database on Protected Areas id
Example request pattern
curl -X GET https://api.resourcewatch.org/v2/geostore/wdpa/<id> \
-H "x-api-key: <your-api-key>"
Example URL request
curl -X GET https://api.resourcewatch.org/v2/geostore/wdpa/142809 \
-H "x-api-key: <your-api-key>"
Example response (note coordinates are truncated)
{
"data": {
"type": "geoStore",
"id": "88db597b6bcd096fb80d1542cdc442be",
"attributes": {
"geojson": {
"crs": {},
"type": "FeatureCollection",
"features": [
{
"geometry": {
"coordinates": [
...
],
"type": "MultiPolygon"
},
"type": "Feature",
"properties": null
}
]
},
"hash": "88db597b6bcd096fb80d1542cdc442be",
"provider": {},
"areaHa": 5081.838068566336,
"bbox": [
-6.031685272,
36.160220287,
-5.879245686,
36.249656987
],
"lock": false,
"info": {
"use": {},
"wdpaid": 142809
}
}
}
}
Use the GET geostore/admin/wdpa/:id
endpoint to retrieve a geostore object representative of the boundaries of
a World Database on Protected Areas (WDPA) with id (<id>
) provided. To find valid
WDPA id values check the link above.
Note marine protected areas are NOT included
Errors for getting geostore objects by WDPA id
Error code | Error message | Description |
---|---|---|
404 | Geostore not found. | A geostore for the WDPA id provided was not found. |
Get geostore by Land Use Type keyword and id
Example request pattern
curl -X GET https://api.resourcewatch.org/v2/geostore/use/<name>/<id> \
-H "x-api-key: <your-api-key>"
Example URL request
curl -X GET https://api.resourcewatch.org/v2/geostore/use/logging/1 \
-H "x-api-key: <your-api-key>"
Example response (note coordinates are truncated)
{
"data": {
"type": "geoStore",
"id": "bd5feac1b0dd4e73f3a1553889807622",
"attributes": {
"geojson": {
"crs": {},
"type": "FeatureCollection",
"features": [
{
"geometry": {
"coordinates": [
...
],
"type": "MultiPolygon"
},
"type": "Feature",
"properties": null
}
]
},
"hash": "bd5feac1b0dd4e73f3a1553889807622",
"provider": {},
"areaHa": 45978.43408272762,
"bbox": [
102.691404026,
-0.248440312,
103.036606,
-0.071735991
],
"lock": false,
"info": {
"use": {
"use": "gfw_logging",
"id": 1
},
"simplify": false
}
}
}
}
Use the GET geostore/admin/use/:name/:id
endpoint to retrieve a geostore object representative of the boundaries of a
Land Use Type keyword (<name>
) and Land Use Type object id (<id>
).
Geostore objects for five land use types are available:
- Tiger conservation landscapes (
tiger_conservation_landscapes
) - Oil Palm production (
oilpalm
) - Mining activities (
mining
) - Wood fiber production (
fiber
) - Forest logging activities (
logging
).
The returned geometries can be simplified using the parameter ?simplify=<value>
. Where <value>
is given to the
simplification algorithm- 0.005 usually works well.
Note - each of the land use types actually represents an individual dataset, each with different geographical extents and temporal coverage, see the dataset urls for details
Errors for getting geostore objects by land use type
Error code | Error message | Description |
---|---|---|
404 | Geostore not found. | A geostore for the specified <name> and <id> was not found. |
Calculate the area of a geostore object
If you have a GeoJSON geometry and you intend to know the area that your geometry occupies or what is the bounding box
for your geometry, you can use the POST v2/geostore/area
endpoint to calculate the area of your geometry.
Example request pattern
curl -X POST https://api.resourcewatch.org/v2/geostore/area \
-H "x-api-key: <your-api-key>" \
-d '{"geojson": <geojson>}'
Example URL request
curl -X POST https://api.resourcewatch.org/v2/geostore/area \
-H "x-api-key: <your-api-key>" \
-d '{
"geojson":{
"type": "Polygon",
"coordinates": [
[
[-0.1758,51.2894],
[8.4375,51.1793],
[6.8555,47.5172],
[-0.1758,51.2894]
]
]
}}'
Example response:
{
"data": {
"type": "geomArea",
"attributes": {
"bbox": [
-0.1758,
47.5172,
8.4375,
51.2894
],
"areaHa": 12797498.414088473
}
}
}
Errors for calculating the area of a geostore object
Error code | Error message | Description |
---|---|---|
400 | geojson, esrijson or provider required. |
You need to provide the GeoJSON for the geometry you intend to calculate the area. |
Subscriptions
What is a subscription?
Note: We strongly recommend that you read the dataset concept and dataset endpoints sections before proceeding.
A subscription allows you to get notified of updates on a datasets' data - either for every update, or for updates restricted to geographical areas of your interest. For example, you can use subscriptions to subscribe to deforestation alerts (GLAD alerts dataset) in the Amazon forest, or track fire alerts (VIIRS fire alerts dataset) in your area of residence.
In the following sections, we will cover how you can interact and manage subscriptions in the RW API. We will see how you can customize subscriptions so that we only get notified for changes in a dataset's data for specific geographic regions. You will learn how to use them to get notified via email or calls to a URL you provide. We will also dive into subscription lifecycle, and understand how we can confirm subscriptions, resend confirmation emails and how to unsubscribe and stop receiving notifications.
Subscription lifecycle
In this section, you will learn about the lifecycle of a subscription. This will help you understand how you can best use subscriptions to meet your goals. The first step for using subscriptions is understanding which data you want to subscribe - for this, we recommend searching the existing datasets in the WRI API (or maybe even creating a new one). Once you are certain of the dataset you wish to subscribe, the next step is ensuring that this dataset is subscribable.
Subscribable datasets
Example of a subscribable dataset
{
"name": "Example dataset",
"application": ["app"],
"provider": "carto",
...
"subscribable": {
"test": {
"dataQuery": "SELECT * FROM dataset-name WHERE 'reported_date' >= '{{begin}}' AND 'reported_date' <= '{{end}}' AND 'number_dead' > 0 ORDER BY reported_date DESC LIMIT 10",
"subscriptionQuery": "SELECT COUNT(*) FROM dataset-name WHERE 'reported_date' >= '{begin}' AND 'reported_date' <= '{end}' AND 'number' > 0"
}
}
}
While you can create a subscription for any dataset, some conditions must be met by the dataset for its corresponding subscriptions to be functional and actually work as described here.
In order to support a functional subscription, a dataset must have some queries defined in its subscribable
property. In this property, of type object, one (or many) sub-objects should be declared. Please note that you can define multiple keys in the subscribable
object, and each key will be evaluated separately and trigger its own updates. Each object inside the subscribable
property must define two queries:
dataQuery
, which will be evaluated as the subscription's content - i.e. this is what has been updated since the last check on the updates of this dataset.subscriptionQuery
, which will be evaluated to check if a subscription has changed since the last update. This query should return a single row with the count of updated items since the last update check. If the value returned by this query is greater than 0, then all the subscriptions that reference this dataset will receive a notification.
The example on the side defines the subscribable
object for an example dataset, and this object contains a the key test
, including both a dataQuery
and a subscriptionQuery
. For more details on how you can modify the subscribable
property of a dataset, check out the documentation on updating a dataset. The keys in the subscribable object (e.g. test
) are just for organizational purposes, and they won't be used in any way from the subscription's perspective.
Both queries can contain two special keywords: {begin}
and {end}
. These will be replaced with ISO-formatted dates on runtime, with the datetime in which the subscription was last evaluated, and the datetime at the time of evaluation, respectively.
Please note that, for readability purposes, the special characters in example on the side are not properly escaped. Don't forget all special characters must be properly escaped for the queries to be correctly executed.
Creating and confirming the subscription
You have your dataset ready to be subscribed. The next steps would be to actually create the subscription - check the docs for creating subscriptions for detailed information on how to do that.
After creating the subscription, an email is sent with a confirmation link. You need to click this link in order to confirm the notification and start receiving notifications. You can check if the subscription is confirmed or not by looking at the confirmed
field of the subscription object. Check more information about confirming subscriptions in the confirming a subscription section.
If, for some reason, you have lost the confirmation email, you can check the resending confirmation emails section for more information on how to resend the confirmation email.
At any point, you might want to stop receiving email or webhook notifications - if that is the case, you can check the unsubscribing section for details on how to stop receiving notifications for your subscriptions.
The same subscription can subscribe to multiple datasets - for that, you just need to provide all the dataset ids you intend to subscribe in either the datasets
or datasetsQuery
fields of the subscription on creation. However, a subscription can only notify a single email at a time - if you intend to receive subscription notifications on multiple emails, you'll need to create multiple subscriptions.
How are subscription notifications sent?
Example of POST body data for a webhook notification:
{
"value": 5,
"downloadUrls": {
"csv": "https://production-api.globalforestwatch.org/glad-alerts/download/?period=2020-02-22,2020-03-04&gladConfirmOnly=False&aggregate_values=False&aggregate_by=False&geostore=423e5dfb0448e692f97b590c61f45f22&format=csv",
"json": "https://production-api.globalforestwatch.org/glad-alerts/download/?period=2020-02-22,2020-03-04&gladConfirmOnly=False&aggregate_values=False&aggregate_by=False&geostore=423e5dfb0448e692f97b590c61f45f22&format=json"
},
"alerts": [
{
"alert_type": "GLAD",
"date": "10/10/2019 00:10 UTC"
},
{
"alert_type": "GLAD",
"date": "11/10/2019 00:10 UTC"
},
{
"alert_type": "GLAD",
"date": "12/10/2019 00:10 UTC"
},
{
"alert_type": "GLAD",
"date": "13/10/2019 00:10 UTC"
},
{
"alert_type": "GLAD",
"date": "14/10/2019 00:10 UTC"
},
{
"alert_type": "GLAD",
"date": "15/10/2019 00:10 UTC"
}
],
"layerSlug": "glad-alerts",
"alert_name": "Subscription for Amazônia, Brazil",
"selected_area": "Amazônia, Brazil",
"unsubscribe_url": "https://production-api.globalforestwatch.org/subscriptions/5ea996383efbd0119327b372/unsubscribe?redirect=true&lang=en",
"subscriptions_url": "https://www.globalforestwatch.org/my-gfw?lang=en",
"dashboard_link": "https://www.globalforestwatch.org/dashboards/aoi/5ea996383efbd0119327b372?lang=en",
"alert_link": "https://www.globalforestwatch.org/map/aoi/5ea996383efbd0119327b372?lang=en&map%5BcanBound%5D=true&map%5Bdatasets%5D%5B0%5D%5Bdataset%5D=bfd1d211-8106-4393-86c3-9e1ab2ee1b9b&map%5Bdatasets%5D%5B0%5D%5Blayers%5D%5B0%5D=8e4a527d-1bcd-4a12-82b0-5a108ffec452&map%5Bdatasets%5D%5B0%5D%5BtimelineParams%5D%5BstartDate%5D=2020-04-15&map%5Bdatasets%5D%5B0%5D%5BtimelineParams%5D%5BendDate%5D=2020-04-22&map%5Bdatasets%5D%5B0%5D%5BtimelineParams%5D%5BtrimEndDate%5D=2020-04-22&map%5Bdatasets%5D%5B1%5D%5Bdataset%5D=0b0208b6-b424-4b57-984f-caddfa25ba22&map%5Bdatasets%5D%5B1%5D%5Blayers%5D%5B0%5D=b45350e3-5a76-44cd-b0a9-5038a0d8bfae&map%5Bdatasets%5D%5B1%5D%5Blayers%5D%5B1%5D=cc35432d-38d7-4a03-872e-3a71a2f555fc&mainMap%5BshowAnalysis%5D=true",
"alert_date_begin": "2020-04-15",
"alert_date_end": "2020-04-22"
}
Subscriptions support two types of notifications: emails or webhook requests is performed. Both notifications are checked and sent every day, assuming that the dataset data has changed since the last notification sent.
Webhook notifications are sent as POST requests to the URL saved in the subscription. You can check on the side an example of the data that is sent in the body of the POST call. Please note that the webhook POST body data can change, based on the dataset chosen to receive notifications.
You can see in the image below an example of an email notification for GLAD deforestation alerts:
Summary of the subscription lifecycle
- First, you should know which dataset to use and when its data gets updated.
- You ensure that the dataset is subscribable - if not, you should write the subscription queries and update the dataset.
- You create a subscription.
- You get a confirmation email and click on the link to confirm the subscription.
- Done! You will now get an email every day with the updates to the dataset data (note that if there are no updates, no email is sent).
- Later, you can unsubscribe or delete the subscription.
Getting subscriptions owned by the request user
Getting the subscriptions for the request user:
curl -X GET "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"type": "subscription",
"id": "587cc014f3b3f6280058e478",
"attributes": {
"name": "Test subscription",
"createdAt": "2020-01-16T12:45:08.434Z",
"userId": "57a063da096c4eda523e99ae",
"resource": {
"type": "EMAIL",
"content": "example@wri.org"
},
"datasets": ["viirs-active-fires"],
"datasetsQuery": [],
"params": {
"geostore": "50601ff9257df221e808af427cb47701"
},
"confirmed": false,
"language": "en",
"env": "production"
}
}
]
}
This endpoint will allow you to get all the subscriptions owned by the user who performed the request (identified by the access token). To use this endpoint, you must be logged in (i.e. a token must be provided). In the sections below, we’ll explore how you can customize this endpoint call to match your needs.
For a detailed description of each field, check out the Subscription reference section.
Filters
The /v1/subscriptions
endpoint supports the following optional query parameters as filters:
Field | Description | Type | Default value |
---|---|---|---|
application | Application to which the subscription is associated. Read more about this field here. | String | 'gfw' |
env | The environment to which the subscription is associated. Read more about this field in the Environments concept section. | String | 'production' |
Deprecation notice: the default value for the application
filter (currently, gfw
) will be removed and the application
filter will then have no default value. We recommend reviewing your application to ensure you set and load the correct application
explicitly.
Errors for getting subscriptions
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | No valid token was provided in the request headers. |
Getting a subscription by id
Example call for getting a subscription by its id:
curl -X GET "https://api.resourcewatch.org/v1/subscriptions/<subscription_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Response:
{
"data": {
"type": "subscription",
"id": "587cc014f3b3f6280058e478",
"attributes": {
"name": "Test subscription",
"createdAt": "2020-01-16T12:45:08.434Z",
"userId": "57a063da096c4eda523e99ae",
"resource": {
"type": "EMAIL",
"content": "example@wri.org"
},
"datasets": ["viirs-active-fires"],
"datasetsQuery": [],
"params": {
"geostore": "50601ff9257df221e808af427cb47701"
},
"confirmed": false,
"language": "en",
"env": "production"
}
}
}
If you know the id of a subscription, then you can access it directly by performing a GET request to the /v1/subscriptions/:id
endpoint. Keep in mind that this will only match subscriptions that are owned by the user who performed the request.
Errors for getting subscriptions by id
Error code | Error message | Description |
---|---|---|
400 | ID is not valid | The id provided is not a valid subscription id. |
401 | Unauthorized | No valid token was provided in the request headers. |
404 | Subscription not found | Either no subscription exists with the provided id, or the subscription with the id provided is not owned by the user who performed the request. |
Creating a subscription
Example POST request to create a subscription providing the bare minimum body fields:
curl -X POST "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"datasets": "20cc5eca-8c63-4c41-8e8e-134dcf1e6d76",
"resource": {
"type": "EMAIL",
"content": "example@wri.org"
},
"params": {},
"application": "gfw",
"language": "en"
}'
Example response:
{
"data": {
"type": "subscription",
"id": "5eea1e6cfd754e001b28cb2b",
"attributes": {
"createdAt": "2020-06-17T13:45:16.222Z",
"userId": "5ed75dd2a82a420010ed066b",
"resource": {
"type": "EMAIL",
"content": "example@wri.org"
},
"datasets": ["20cc5eca-8c63-4c41-8e8e-134dcf1e6d76"],
"params": {},
"confirmed": false,
"language": "en",
"datasetsQuery": [],
"env": "production"
}
}
}
This section will guide you through the process of creating a basic subscription in the RW API. Creating a subscription can be done by any logged user using a POST request and passing the relevant data as body fields. The supported body fields are as defined on the subscription reference section, but the minimum field list you must specify for all subscriptions are:
datasets
ordatasetsQuery
resource
(which must include bothresource.type
andresource.content
)params
application
language
If the creation of the subscription is successful, the HTTP response code will be 200 OK, and the response body will contain the created subscription object. Please note that subscriptions must be confirmed before they become active - refer to the subscription lifecycle for more details on this.
Errors for creating subscriptions
Error code | Error message | Description |
---|---|---|
400 | <field> required |
You didn't provide one of the required fields. |
401 | Unauthorized | No valid token was provided in the request headers. |
Defining the datasets
You will need to provide the dataset ids to which your subscription will watch for updates. In order to do so, you'll need to provide one of two fields when creating a subscription:
datasets
- this field is a simple array of dataset ids. Each dataset will be individually evaluated for updates, and it will trigger an email if thesubscriptionsQuery
returns greater than 0.datasetsQuery
is an alternative way of defining the datasets to subscribe: using this field, you have the advantage of being able to define a different threshold for sending the email (i.e. the email is sent if thesubscriptionQuery
returns a count greater than the threshold defined in thedatasetsQuery
object). For more details on the structure of the objects insidedatasetsQuery
, please check the subscription model reference.
Customizing the geographic area for the subscription
When it comes to geo-referenced data, subscriptions are intrinsically tied to a geographic area of interest. This association enables users to create subscriptions to be notified of changes in the data of a dataset, but only if there are changes in the data of the dataset relative to the concrete geographic area of the world they are interested in. The specification of the geographic information for the subscription should be done in the params
field of the subscription.
Subscribing to an area of interest
Creating a subscription providing the id of an area of interest in the params field:
curl -X POST "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"datasets": ["<dataset-id>"],
"params": {
"area": "35a6d982388ee5c4e141c2bceac3fb72"
},
"application": "gfw",
"language": "en",
"env": "production",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
}
}'
A subscription can refer to a specific area of interest that has been created using the RW API Areas service. If this is the case, you should first create your area of interest, grab its id and provide it in the params.area
field of the request body when creating the subscription.
Field | Description | Type |
---|---|---|
params |
Geographic area of the subscription | Object |
params.area |
Id of area of interest from the RW API Areas service | String |
Subscribing to a country, country region or subregion
Creating a subscription to a whole country:
curl -X POST "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"datasets": ["<dataset-id>"],
"params": {
"iso": {
"country": "BRA"
}
},
"application": "gfw",
"language": "en",
"env": "production",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
}
}'
Creating a subscription to a country subregion:
curl -X POST "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"datasets": ["<dataset-id>"],
"params": {
"iso": {
"country": "BRA",
"region": "1",
"subregion": "2"
}
},
"application": "gfw",
"language": "en",
"env": "production",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
}
}'
A subscription can refer to a country, one of its regions, or a subregion within a region. Countries are identified by their ISO 3166-1 alpha-3 code - check here for a list of all the available country codes. Regions and subregions are identified by their respective GADM id, which can be obtained from GADM's dataset here. When creating a subscription for a region, the country ISO must be specified. For subscribing to a subregion, both region and country ISO must be provided.
Field | Description | Type |
---|---|---|
params.iso.country |
ISO 3-letter code of the country to subscribe | String |
params.iso.region |
Region id to subscribe | String |
params.iso.subregion |
Subregion id to subscribe (optional) | String |
Subscribing to a protected area from World Database on Protected Areas
Creating a subscription providing a WDPA id in the params field:
curl -X POST "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"datasets": ["<dataset-id>"],
"params": {
"wdpaid": "32054"
},
"application": "gfw",
"language": "en",
"env": "production",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
}
}'
A subscription can refer to a specific protected area by the id of that area in the World Database on Protected Areas. If this is the case, you should provide the WDPA id in the params.wdpaid
field when creating the subscription. IDs of protected areas worldwide can be obtained from the Protected Planet website.
Field | Description | Type |
---|---|---|
params.wdpaid |
Id of the protected area in the WDPA | String |
Subscribing to a RW API geostore
Creating a subscription providing the id of a geostore obtained from the RW API in the params field:
curl -X POST "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"datasets": ["<dataset-id>"],
"params": {
"geostore": "35a6d982388ee5c4e141c2bceac3fb72"
},
"application": "gfw",
"language": "en",
"env": "production",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
}
}'
A subscription can refer to a specific geostore that has been created using the RW API Geostore service. If this is the case, you should create your geostore and use its id in the params.geostore
field of the request body when creating the subscription.
Field | Description | Type |
---|---|---|
params.geostore |
Id of the RW API geostore to subscribe to. | String |
Subscribing to a GFW Data API geostore
Creating a subscription providing the id of a geostore obtained from the GFW Data API in the params field:
curl -X POST "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"datasets": ["<dataset-id>"],
"params": {
"geostoreDataApi": "35a6d982388ee5c4e141c2bceac3fb72"
},
"application": "gfw",
"language": "en",
"env": "production",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
}
}'
A subscription can refer to a specific geostore that has been created using the GFW Data API. If this is the case, you should check the docs for the GFW Data API and create your geostore, then use its id in the params.geostoreDataApi
field of the request body when creating the subscription.
Field | Description | Type |
---|---|---|
params.geostoreDataApi |
Id of the GFW Data API geostore to subscribe to. | String |
Subscribing to land use areas
Creating a subscription providing the id of a land use area in the params field:
curl -X POST "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"datasets": ["<dataset-id>"],
"params": {
"use": "mining",
"useid": "234"
},
"application": "gfw",
"language": "en",
"env": "production",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
}
}'
A subscription can refer to a land use area provided by different datasets. At this point, the following land use datasets are supported: mining
for mining areas, logging
for Congo Basin logging roads, oilpalm
for palm oil plantations or fiber
for wood fiber plantations. If this is the case, you should provide the name of the land use dataset you wish to use in the params.use
field, and the id of the area in the params.useid
field of the request body when creating the subscription.
The ids to be used for land use areas can be obtained from the following CartoDB datasets:
- Mining area IDs can be obtained by querying this dataset.
- Palm oil plantation IDs can be obtained from this CartoDB table.
- Wood fiber plantation IDs can be obtained from this CartoDB table.
- Congo Basin logging road IDs can be obtained from this CartoDB table.
Field | Description | Type |
---|---|---|
params.use |
The type of land use you want to subscribe to. Can be one of mining , logging , oilpalm or fiber . |
String |
params.useid |
The id of the land use area you want to subscribe to. | String |
Updating a subscription
Example PATCH request for updating a subscription by id:
curl -X PATCH "https://api.resourcewatch.org/v1/subscriptions/<subscription_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
-H "Content-Type: application/json" -d \
'{
"datasets": ["20cc5eca-8c63-4c41-8e8e-134dcf1e6d76"],
"params": {
"geostore": "35a6d982388ee5c4e141c2bceac3fb72"
},
"application": "rw",
"language": "fr",
"env": "staging",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
}
}'
Example response:
{
"data": {
"type": "subscription",
"id": "5ee79291a67d9a001b11043a",
"attributes": {
"createdAt": "2020-06-15T15:24:01.806Z",
"userId": "5ed75dd2a82a420010ed066b",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
},
"datasets": ["20cc5eca-8c63-4c41-8e8e-134dcf1e6d76"],
"params": {
"geostore": "35a6d982388ee5c4e141c2bceac3fb72"
},
"confirmed": true,
"language": "fr",
"datasetsQuery": [],
"env": "staging"
}
}
}
You can update subscriptions associated with you user account by using the PATCH /v1/subscriptions/:id
endpoint. Updating a subscription follows the same validations as when creating a new one - i.e. all required field values must be provided, even if they remain the same. Values for fields other than the following are optional. The minimum fields list you must specify to update a subscription is:
datasets
ordatasetsQuery
resource
(which much includeresource.type
andresource.content
)params
application
language
If the update of the subscription is successful, the HTTP response code will be 200 OK, and the response body will contain the updated subscription object.
Note: Updating a subscription does not require confirming it. A confirmed subscription will stay confirmed after an update.
Errors for updating subscriptions
Error code | Error message | Description |
---|---|---|
400 | <field> required |
You didn't provide one of the required fields. |
400 | Id is not valid | The id provided is not valid. |
401 | Unauthorized | No valid token was provided in the request headers. |
404 | Subscription not found | Either a subscription with the id provided does not exist or it is not owned by the user who performed the request. |
Deleting subscriptions
Example DELETE request for deleting a subscription by its id:
curl -X DELETE "https://api.resourcewatch.org/v1/subscriptions/<subscription_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": {
"type": "subscription",
"id": "5ee79291a67d9a001b11043a",
"attributes": {
"createdAt": "2020-06-15T15:24:01.806Z",
"userId": "5ed75dd2a82a420010ed066b",
"resource": {
"type": "EMAIL",
"content": "email@address.com"
},
"datasets": ["20cc5eca-8c63-4c41-8e8e-134dcf1e6d76"],
"params": {
"geostore": "35a6d982388ee5c4e141c2bceac3fb72"
},
"confirmed": true,
"language": "fr",
"datasetsQuery": [],
"env": "staging"
}
}
}
To delete a subscription associated with your user account, you should use the DELETE /v1/subscriptions/:id
endpoint. If the deletion of the subscription is successful, the HTTP response code will be 200 OK, and the response body will contain the deleted subscription object.
Errors for deleting subscriptions
Error code | Error message | Description |
---|---|---|
400 | Id is not valid | The id provided is not valid. |
401 | Unauthorized | No valid token was provided in the request headers. |
404 | Subscription not found | Either a subscription with the id provided does not exist or it is not owned by the user who performed the request. |
Deleting subscriptions by user id
Example DELETE request for deleting subscriptions by user id:
curl -X DELETE "https://api.resourcewatch.org/v1/subscriptions/by-user/<user_id>" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"type": "subscription",
"id": "587cc014f3b3f6280058e478",
"attributes": {
"name": "Test subscription",
"createdAt": "2020-01-16T12:45:08.434Z",
"userId": "57a063da096c4eda523e99ae",
"resource": {
"type": "EMAIL",
"content": "example@wri.org"
},
"datasets": ["viirs-active-fires"],
"datasetsQuery": [],
"params": {
"geostore": "50601ff9257df221e808af427cb47701"
},
"confirmed": false,
"language": "en",
"env": "production"
}
}
]
}
To delete every subscription associated with a specific user account, the DELETE /v1/subscriptions/by-user/:userId
endpoint can be used. If the deletion process is successful, the HTTP response code will be 200 OK, and the response body will contain all the deleted subscriptions. This endpoint requires microservice or ADMIN access, or being logged as the user that wants their subscriptions deleted.
Errors for deleting subscriptions by user id
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | No valid token was provided in the request headers. |
403 | Forbidden | Either the user logged is not the same as the user id that is going to be deleted or is not an ADMIN or microservice. |
Confirming a subscription`
Example GET request to confirm a subscription:
curl -X GET "https://api.resourcewatch.org/v1/subscriptions/<subscription_id>/confirm" \
-H "x-api-key: <your-api-key>"
Upon creation of the subscription, a confirmation email is sent to the email of the user who created the subscription. This email will contain a link, which you will need to click in order to confirm the subscription. You can also confirm the subscription by performing a GET request to the /v1/subscriptions/:id/confirm
endpoint, as exemplified on the side.
Manually calling this endpoint will redirect you to the GFW application.
Resending the subscription confirmation email
Example GET request to resend the confirmation email for a subscription:
curl -X GET "https://api.resourcewatch.org/v1/subscriptions/<subscription_id>/send_confirmation" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
For convenience, the RW API offers an additional endpoint to resend the confirmation email. In order to do this, you should perform a GET request to the /v1/subscriptions/:id/send_confirmation
. As with most of the other subscription endpoints, please keep in mind that you must be authenticated in order to use this endpoint.
This endpoint does not change the subscription - i.e. if the subscription was already confirmed, it stays that way. The confirmation email will always be sent, regardless if the subscription is confirmed or not.
Manually calling this endpoint will redirect you to the GFW application.
Unsubscribing
Example GET request to unsubscribe:
curl -X GET "https://api.resourcewatch.org/v1/subscriptions/<subscription_id>/unsubscribe" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Note: When you unsubscribe, the underlying subscription resource is deleted..
You can use the endpoint /v1/subscriptions/:id/unsubscribe
(exemplified on the side) for unsubscribing from a subscription. As with most of the other subscription endpoints, please keep in mind that you must be authenticated in order to use this endpoint.
Subscription statistics
The following section details the endpoints that can be used to access statistics on the usage of subscriptions.
The usage of the following endpoints is restricted to ADMIN users.
General subscription statistics
Example GET request to obtain general subscription statistics:
curl -X GET "https://api.resourcewatch.org/v1/subscriptions/statistics?start=:start&end=:end" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"topSubscriptions": {
"geostore": 1000,
"country": 30,
"region": 20,
"wdpa": 10,
"use": 1
},
"info": {
"numSubscriptions": 1000,
"totalSubscriptions": 6000,
"usersWithSubscriptions": 1000,
"totalEmailsSentInThisQ": 0,
"totalEmailsSended": 0
},
"usersWithSubscription": 119,
"newUsers": 210,
"groupStatistics": {
"glad-alerts": {
"country": 15,
"region": 28,
"use": 1,
"wdpa": 9,
"geostore": 1305,
"countries": {
"CHL": 1,
"IDN": 3,
...
},
"regions": {
"1": 1,
"2": 2,
...
},
"wdpas": {
"130": 1,
"34043": 5,
...
},
"countryTop": {
"name": "IDN",
"value": 3
},
"regionTop": {
"nameRegion": 12,
"nameCountry": "IDN",
"value": 2
},
"wdpaTop": {
"id": 34043,
"value": 5
}
},
"prodes-loss": {...},
"umd-loss-gain": {...},
"terrai-alerts": {...},
"viirs-active-fires": {...},
"imazon-alerts": {...},
"forma250GFW": {...},
"forma-alerts": {...},
"story": {...},
"63f34231-7369-4622-81f1-28a144d17835": {...}
}
}
The /v1/subscriptions/statistics
endpoint can be used to access all the data regarding the subscription notifications that have been sent.
Filters
This endpoint supports the following query parameters as filters:
Field | Description | Type | Default | Example |
---|---|---|---|---|
start | The start of the date range to fetch the statistics. This parameter is required. | String | None | 01-01-2020 |
end | The end of the date range to fetch the statistics. This parameter is required. | String | None | 02-20-2020 |
application | The application for which the statistics will be fetched. Read more about this field here. | String | 'gfw' | 'rw' |
Grouped subscription statistics
Example GET request to obtain grouped subscription statistics:
curl -X GET "https://api.resourcewatch.org/v1/subscriptions/statistics-group?start=:start&end=:end" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"glad-alerts": {
"country": 15,
"region": 28,
"use": 1,
"wdpa": 9,
"geostore": 1305,
"countries": {
"CHL": 1,
"IDN": 3,
...
},
"regions": {
"1": 1,
"2": 2,
...
},
"wdpas": {
"130": 1,
"34043": 5,
...
},
"countryTop": {
"name": "IDN",
"value": 3
},
"regionTop": {
"nameRegion": 12,
"nameCountry": "IDN",
"value": 2
},
"wdpaTop": {
"id": 34043,
"value": 5
}
},
"prodes-loss": {...},
"umd-loss-gain": {...},
"terrai-alerts": {...},
"viirs-active-fires": {...},
"imazon-alerts": {...},
"forma250GFW": {...},
"forma-alerts": {...},
"story": {...},
"63f34231-7369-4622-81f1-28a144d17835": {...}
}
The /v1/subscriptions/statistics-group
endpoint can be used to access data regarding the subscription notifications that have been sent, grouped by the the dataset of the subscription. The output of this endpoint is a subset of the output of the /v1/subscriptions/statistics
endpoint.
Filters
This endpoint supports the following query parameters as filters:
Field | Description | Type | Default | Example |
---|---|---|---|---|
start | The start of the date range to fetch the statistics. This parameter is required. | String | None | 01-01-2020 |
end | The end of the date range to fetch the statistics. This parameter is required. | String | None | 02-20-2020 |
application | The application for which the statistics will be fetched. Read more about this field here. | String | 'gfw' | 'rw' |
Subscription reference
This section gives you a complete view at the properties that are maintained as part of a subscription. When interacting with a subscription (on get, on create, etc) you will find most of these properties available to you, although they may be organized in a slightly different structure (ie: on get, everything but the id
is nested inside an attributes
object).
You can find more details in the source code.
Filter | Type | Required | Default value | Description |
---|---|---|---|---|
id | String | Yes | (auto-generated) | Unique Id of the subscription. Auto generated on creation. Cannot be modified by users. |
name | String | No | The name of the subscription. | |
confirmed | Boolean | No | false | If the subscription is confirmed or not. Cannot be modified by users, only through the usage of the confirm and unsubscribe endpoints. (TODO: missing refs!) |
resource | Object | Yes | An object containing the data for who (or what) should be notified on dataset data changes. | |
resource.type | Enum | Yes | The type of resource to be notified. Can take the values of EMAIL (for an email notification) or URL for a webhook notification. |
|
resource.content | String | Yes | The object to be notified: should be a valid email case resource.type is EMAIL , and a valid URL case resource.type is URL . |
|
datasets | Array | No | [] |
An array of dataset ids that this subscription is tracking. |
datasetsQuery | Array | No | [] |
An alternative way of stating the datasets that this subscription is tracking. This field is an array of objects, check the rows below to see which properties each object should have. |
datasetsQuery[0].id | String | No | An identifier for the dataset being subscribed. | |
datasetsQuery[0].type | String | No | A type for the dataset being subscribed. | |
datasetsQuery[0].threshold | Number | No | 0 | The threshold to be considered when checking for updates in the dataset's data. By default, it takes the value the value 0, but you can customize it to only get notified if there are at least (for instance) 5 updates to the dataset's data. |
datasetsQuery[0].lastSentDate | Date | No | (auto-generated) | Value automatically updated to have set the last date when updates were detected in this dataset. |
datasetsQuery[0].lastSentDate | Date | No | (auto-generated) | This value is automatically updated with the historical data of all the updates detected in the dataset's data. |
params | Object | No | {} |
Determines the area of interest that this subscription should track. Can contain information to narrow the updates being tracked (especially in the case of geo-referenced data). |
userId | String | Yes | (auto-populated) | Id of the user who owns the subscription. Set automatically on creation. Cannot be modified by users. |
language | String | No | 'en' |
The language for this subscription. Useful for customizing email notifications according to the language of the subscription. Possible values include 'en' , 'es' , 'fr' , 'pt' or 'zh' . |
application | String | Yes | 'gfw' |
Applications associated with this subscription. Read more about this field here. |
env | String | Yes | 'production' |
Environment to which the subscription belongs. Read more about this field in the Environments concept section. |
createdAt | Date | No | (auto-populated) | Automatically maintained date of when the subscription was created. Cannot be modified by users. |
updatedAt | Date | No | (auto-populated) | Automatically maintained date of when the subscription was last updated. Cannot be modified by users. |
Favorites
The users can save their own favorites resources of the API.
Field | Description | Type |
---|---|---|
id | Name | Text |
resourceId | Id of the resource | Text |
resourceType | Type of resource | Text (dataset, layer, widget) |
userId | Id of the owner user | Text |
createdAt | Creation date | Date |
Create Favorite
To create a favorite, you need to define all next fields in the request body. The required fields that compose a favorite are:
Field | Description | Type |
---|---|---|
resourceId | Id of the resource | Text |
resourceType | Type of resource | Text (dataset, layer, widget) |
To create a favorite, you have to do a POST with the following body:
curl -X POST https://api.resourcewatch.org/v1/favourite \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"resourceType":"<resourceType>",
"resourceId": "<resourceId>"
}'
Get favorites
This endpoint returns the favorites of the logged user.
To get all favorite of the logged user, you have to do a GET request:
curl -X GET https://api.resourcewatch.org/v1/favourite \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
You can also retrieve all data about the resources by including the query parameter "include=true" in the request.
curl -X GET https://api.resourcewatch.org/v1/favourite?include=true \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Get favorite by id
This endpoint returns the favorite with id of the param. If the favorite belongs to other user or not exist, the endpoint returns 400.
To get the favorite by id, you have to do a GET request:
curl -X GET https://api.resourcewatch.org/v1/favourite/:id \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Delete favorite
This endpoint deletes the favorite with id of the param. If the favorite belongs to other user or not exist, the endpoint returns 400.
To delete the favorite by id, you have to do a DELETE request:
curl -X DELETE https://api.resourcewatch.org/v1/favourite/:id \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Delete a favourite by user id
To delete the favourite by user id, you have to do a DELETE request:
curl -X DELETE https://api.resourcewatch.org/v1/favourite/by-user/:userId \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
In case of success, the deleted favourites are returned in the response body:
{
"data": [
{
"id": "5e6f6eb9bb494e001ab7e413",
"type": "favourite",
"attributes": {
"userId": "57ac9f9e2930906323e573a2",
"resourceType": "dataset",
"resourceId": "1e56170c1fca55001ad51779",
"createdAt": "2020-03-16T12:19:05.125Z",
"application": "rw"
}
}
]
}
This endpoint deletes the favourites owned by the user with id userId
. Any ADMIN user can use this endpoint to delete data for any user, while users with USER or MANAGER roles can only delete their own data.
Errors for deleting a favourites by user id
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to delete favourites. |
403 | Forbidden | You need to either have the ADMIN role, or call this endpoint with your own user id |
Graph
The following section details the endpoints you can use to interact with graph information about the RW API. If you are new to the RW API or want to learn more about what the RW API graph can do for you, we strongly encourage you to read the graph concept documentation first.
Before proceeding, let's look at some concepts that will be used across the graph endpoint documentation.
What is a resource
Throughout this section, we'll refer multiple times to resources
. Simply put, a resource
is either a dataset, a
widget, a layer, or a metadata entry. Graph nodes represent in a similar fashion these 4 types of RW API entity, so
often we'll refer to resources instead, for convenience.
We assume that, at this point, you are already familiar with the concepts of dataset, layer, widget or metadata (ideally you are familiar with the 4). If that's not the case, we strongly encourage you to learn about those concepts first, and we also recommend you take some time to explore and experiment using actual dataset, layer, widget, or metadata endpoints before proceeding. The RW API Graph service builds on top of these concepts and empowers your use cases of those resources, so it should only be used by applications and users that are already comfortable with the basics, and want to take their knowledge of the RW API to the next level.
In the context of the RW API Graph service, resources are represented as graph nodes. They can be associated (using graph edges) with concepts to create relationships of relevance between the two entities.
What is a concept
Similarly, we'll refer multiple times to concepts
. A concept
is a keyword used to describe a resource (
e.g. health
, society
, solar_power
, etc.). It shares some similarities
with tags, in the sense it can be associated with resources of different types (
datasets, layers, or widgets).
As with resources, in the context of the RW API Graph service, concepts are represented as graph nodes. They can be associated (using graph edges) with resources to create relationships of relevance between the two entities.
Bird's-eye view of the graph service
As an API user, you will surely be glad to hear that most of the management of graph entities is performed automatically. As you will discover by reading the sections on creating or deleting graph resources, graph nodes for resources are automatically created and deleted when you create or delete your resources, respectively. This means that, as an API user, you are abstracted from these processes and the only thing you need to worry about is actually managing relationships between graph resources and concepts.
To do so, you will need to interact with vocabulary endpoints, using a specific
vocabulary called knowledge_graph
. You can tag your resources using said vocabulary, and the tags you add will be
added as graph concepts and associated with your resources. You can read more about this process in the section
on relationships between graph nodes and concepts. Some
concepts have been pre-loaded into the graph service, and you can use them to associate your resources with widely-used
concepts. However, you are also encouraged to create your own concepts - which, once again, is performed automatically
when managing your associations using the vocabulary endpoints.
You may come across some hierarchical concepts in the following sections, such as "ancestors", "parent concepts" or " descendants". These were initially added with the intention of supporting hierarchy between graph concepts, but such features were not completed. As such, it is recommended that, for now, you ignore and do not rely on any type of hierarchy between graph concepts. This may, however, change in the future.
Lastly, a note: none of the endpoints below are paginated. Most of the endpoints interact with a single resource ( dataset, layer, widget, or metadata), which contributes to a healthy size for most of the Graph service endpoint responses, as long as you keep your associations between graph resources and concepts to a reasonable amount. However, some of the endpoints aim at retrieving full lists of, for instance, graph concepts - please ensure that you take into consideration the impact of using such endpoints in the performance of your applications.
List concepts
Request to list concepts:
curl -X GET https://api.resourcewatch.org/v1/graph/query/list-concepts \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "society",
"label": "Society",
"synonyms": [
"People"
],
"labels": [
"CONCEPT",
"TOPIC"
],
"numberOfDatasetsTagged": 1,
"datasets": [
"4458eb12-8572-45d1-bf07-d5a3ee097021"
]
}
]
}
This endpoint does not return a paginated list - you will receive a full list of all the concepts available in the graph. Additionally, the returned response can only be filtered by application, not searched - which means that it's very unlikely that you will receive a reduced payload by using this endpoint. As such, you should avoid using this specific endpoint since it might harm the performance of your application, should the graph increase significantly in size. You can find alternative endpoints in the sections below that allow you to navigate the graph by similarity of concepts, which is the recommended approach to navigating the graph.
This endpoint returns the list of concepts available in the graph. If successful, the response will have status 200 OK,
containing a list of elements in the data
index, each containing the information about one concept. Check out
the Graph concept reference for details on each of the fields of the returned
response.
Filters
Filtering concepts by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/list-concepts?application=gfw \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated to this concept - read more about this field here. | String | "rw" |
List concepts for a dataset
Request to list concepts for a dataset:
curl -X GET https://api.resourcewatch.org/v1/graph/query/list-concepts/:dataset \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "4458eb12-8572-45d1-bf07-d5a3ee097021",
"type": "graph",
"attributes": {
"iso": "",
"synonyms": [
"Habitat"
],
"id": "habitat",
"label": "Habitats",
"default_parent": "ecosystem"
}
},
{
"id": "4458eb12-8572-45d1-bf07-d5a3ee097021",
"type": "graph",
"attributes": {
"iso": "",
"synonyms": "",
"id": "species",
"label": "Species",
"default_parent": "biodiversity"
}
}
]
}
This endpoint returns the list of relationships between the dataset with id provided in the URL path and concepts. If
successful, the response will have status 200 OK, containing a list of elements in the data
index, each containing the
information about one graph relationship. Check out
the Graph relationship reference for details on each of the fields of the
returned response.
If the dataset id provided is not valid or not found, the response returned will contain an empty list in the data
index.
Filters
Filtering concepts for a dataset by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/list-concepts/:dataset?application=gfw \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated to this concept - read more about this field here. | String | "rw" |
List concepts for multiple datasets
Request to list concepts for multiple datasets:
curl -X POST https://api.resourcewatch.org/v1/graph/find-by-ids \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d \
'{
"ids": [
"37d04efc-0ab2-4499-a891-54dca1013c74",
"0448c79d-0ee0-42ff-9331-aeee70cef301"
]
}'
Example response:
{
"data": [
{
"type": "concept",
"attributes": {
"dataset": "37d04efc-0ab2-4499-a891-54dca1013c74",
"iso": "",
"synonyms": "",
"id": "sanitation",
"label": "Sanitation",
"default_parent": "health"
}
},
{
"type": "concept",
"attributes": {
"dataset": "37d04efc-0ab2-4499-a891-54dca1013c74",
"iso": "",
"synonyms": [
"city",
"urban"
],
"id": "urban",
"label": "Cities",
"default_parent": "settlements"
}
}
]
}
This endpoint returns the list of relationships between the datasets with ids provided in the body of the POST request.
If successful, the response will have status 200 OK, containing a list of elements in the data
index, each containing
the information about one graph relationship. Check out
the Graph relationship reference for details on each of the fields of the
returned response.
Filters
Filtering concepts for multiple datasets by application:
curl -X GET https://api.resourcewatch.org/v1/graph/find-by-ids?application=gfw \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated to this concept - read more about this field here. | String | "rw" |
Errors for listing concepts for multiple datasets
Error code | Error message | Description |
---|---|---|
400 | Bad Request | The ids provided in the body of the request are not correctly formatted. |
Infer concepts from other concepts
GET request to infer concepts related to the concepts passed as query parameters:
curl -X GET https://api.resourcewatch.org/v1/graph/query/concepts-inferred?concepts=society,urban \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
POST request to infer concepts related with the concepts passed in the request body:
curl -X POST https://api.resourcewatch.org/v1/graph/query/concepts-inferred \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d \
'{ "concepts": ["society", "urban"] }'
Example response:
{
"data": [
{
"id": "society",
"label": "Society",
"synonyms": [
"People"
],
"labels": [
"CONCEPT",
"TOPIC"
]
},
{
"id": "urban",
"label": "Cities",
"synonyms": [
"city",
"urban"
],
"labels": [
"CONCEPT",
"TOPIC"
]
}
]
}
This endpoint lets API users discover concepts that have relationships in common with the list of concepts provided. You
can use the GET version of the endpoint, providing the list of concepts as a comma-separated string query string
parameter. Alternatively, you can use the POST version and provide the list of concepts in the concepts
index of the
POST request body.
If successful, the response will have status 200 OK, containing a list of elements in the data
index, each containing
the information about one concept. Check out the Graph concept reference for
details on each of the fields of the returned response.
Filters
Filtering inferred concepts by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/concepts-inferred?application=gfw \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated to this concept - read more about this field here. | String | "rw" |
Errors for listing concepts for multiple datasets
Error code | Error message | Description |
---|---|---|
400 | Concepts are required. | A list of concepts was not provided. |
Query similar datasets
GET request to find out similar datasets to a dataset with id provided:
curl -X GET https://api.resourcewatch.org/v1/graph/query/similar-dataset/:dataset \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Alternative syntax, providing the dataset id as query string parameter:
curl -X GET https://api.resourcewatch.org/v1/graph/query/similar-dataset?dataset=:dataset \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Example response:
{
"data": [
{
"dataset": "1b97e47e-ca18-4e50-9aae-a2853acca3f0",
"concepts": [
"health",
"urban"
]
},
{
"dataset": "51159bdb-4904-4101-a88e-ca7bd4f67cb0",
"concepts": [
"infrastructure"
]
}
]
}
This endpoint lets API users discover datasets that share concepts with the dataset with id provided in the URL path. If
successful, the response will have status 200 OK, containing a list of elements in the data
index, each containing the
id of the dataset that is related and a list of concepts that are shared.
The results returned are sorted by their degree of similarity, meaning the datasets with the higher number of shared concepts are higher on the list.
Filters
Filtering similar datasets by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/similar-dataset/:dataset?application=gfw \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated with this concept - read more about this field here. | String | "rw" |
env | Only list datasets that have the specified environment. | String (can be a comma separated list of env values) | none |
Errors for querying similar datasets
Error code | Error message | Description |
---|---|---|
400 | Dataset query param required | You must provide a valid dataset id. |
Query similar datasets including descendants
GET request to find out similar datasets including descendants to a dataset with id provided:
curl -X GET https://api.resourcewatch.org/v1/graph/query/similar-dataset-including-descendant/:dataset \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Alternative syntax, providing the dataset id as query string parameter:
curl -X GET https://api.resourcewatch.org/v1/graph/query/similar-dataset-including-descendant?dataset=:dataset \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Example response:
{
"data": [
{
"dataset": "37d04efc-0ab2-4499-a891-54dca1013c74",
"concepts": [
"urban",
"health",
"sanitation"
],
"numberOfOcurrences": 1
},
{
"dataset": "223b936e-06b8-4970-abd9-4f123904d95d",
"concepts": [
"hunger",
"famine",
"health"
],
"numberOfOcurrences": 1
}
]
}
This endpoint lets API users discover datasets that share concepts with the dataset with id provided in the URL path. The difference from the endpoint above is that this endpoint also looks at the ancestor concepts from the dataset with id provided - datasets returned might have ancestor concepts in common, but not necessarily the same exact concepts in common.
If successful, the response will have status 200 OK, containing a list of elements in the data
index, each containing
the id of the dataset that is related and a list of concepts that are shared. Each list item also contains
a numberOfOcurrences
field, containing the count of common concepts. The results returned are sorted by their degree
of similarity, meaning the datasets with the higher number of shared concepts (numberOfOcurrences
) are higher on the
list.
Filters
Filtering similar datasets including descendants by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/similar-dataset-including-descendant/:dataset?application=gfw \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated to this concept - read more about this field here. | String | "rw" |
env | Only list datasets that have the specified environment. | String (can be a comma separated list of env values) | none |
Errors for querying similar datasets
Error code | Error message | Description |
---|---|---|
400 | Dataset query param required | You must provide a valid dataset id. |
Search datasets by concepts
GET request to search datasets by concepts:
curl -X GET https://api.resourcewatch.org/v1/graph/query/search-datasets?concepts[0][0]=:concept \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
POST request to search datasets by concepts provided in the request body:
curl -X POST https://api.resourcewatch.org/v1/graph/query/search-datasets \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{ "concepts": [[":concept"]] }'
Providing multiple sets of concepts as GET request:
curl -X GET https://api.resourcewatch.org/v1/graph/query/search-datasets?concepts[0][0]=spain,concepts[0][1]=europe,concepts[1][0]=water,concepts[2][0]=raster,concepts[2][1]=geospatial \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Providing multiple sets of concepts as POST request:
curl -X GET https://api.resourcewatch.org/v1/graph/query/search-datasets \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" \
-d '{
"concepts": [
["spain", "europe"],
["water"],
["raster", "geospatial"]
]
}'
Example response:
{
"data": [
"11f43558-d703-4b9d-aff0-f2354a11b359",
"12510410-1eb3-4af0-844f-8a05be50b1c1",
"1b8f1592-2a92-4dd5-bd85-6d231c7d3229",
"1b97e47e-ca18-4e50-9aae-a2853acca3f0",
"371e700e-bc9a-4526-af92-335d888de309",
"4b000ded-5f4d-4dbd-83c9-03f2dfcd36db",
"5be16fea-5b1a-4daf-a9e9-9dc1f6ea6d4e",
"60be01b0-99fb-459c-8a08-b934270f8c4b",
"63a7a997-695d-4629-b6e9-9b169f5c69bf",
"795a7ceb-ebc1-4479-95ad-76ea4d045ad3"
]
}
This endpoint lets API users discover datasets related to the lists of concepts provided. Note that, either in the GET
or POST forms for this endpoint, concepts must be provided as a list of sets. AND logical operators (&&
) are
applied among the list of sets, while OR (||
) is used for set elements. You can provide up to three sets of concepts
to search for - the example on the side exemplifies a request to this endpoint given the following sets of concepts:
- Set 1:
['spain', 'europe']
- Set 2:
['water']
- Set 3:
['raster', 'geospatial']
In this specific case, the datasets returned would be related with "spain"
OR "europe"
, "water"
, and "raster"
or "geospatial"
. Or, expressed as a logical
condition: ("spain" || "europe") && "water" && ("raster" || "geospatial")
.
If successful, the response will have status 200 OK, containing a list of dataset ids that are related to the concepts
provided in the data
index. Also, note that ancestor concepts are also taken into account in the search.
Filters
Filtering searched datasets by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/search-datasets/:dataset?application=gfw \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated with this concept - read more about this field here. | String | "rw" |
depth | Limits the depth of the graph search. | Number | 15 |
env | Only list datasets that have the specified environment. | String (can be a comma separated list of env values) | none |
Errors for searching datasets by concepts
Error code | Error message | Description |
---|---|---|
400 | Concepts query params are required | You must provide the list of sets of concepts. |
Search datasets by concepts and their synonyms
GET request to search datasets by concepts and their synonyms:
curl -X GET https://api.resourcewatch.org/v1/graph/query/search-by-label-synonyms?search=:search \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Example providing multiple concepts in one request:
curl -X GET https://api.resourcewatch.org/v1/graph/query/search-by-label-synonyms?search=health society \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Example response:
{
"data": [
"11f43558-d703-4b9d-aff0-f2354a11b359",
"12510410-1eb3-4af0-844f-8a05be50b1c1",
"1b8f1592-2a92-4dd5-bd85-6d231c7d3229",
"1b97e47e-ca18-4e50-9aae-a2853acca3f0",
"371e700e-bc9a-4526-af92-335d888de309",
"4b000ded-5f4d-4dbd-83c9-03f2dfcd36db",
"5be16fea-5b1a-4daf-a9e9-9dc1f6ea6d4e",
"60be01b0-99fb-459c-8a08-b934270f8c4b",
"63a7a997-695d-4629-b6e9-9b169f5c69bf",
"795a7ceb-ebc1-4479-95ad-76ea4d045ad3"
]
}
This endpoint finds datasets in the graph that are related to the concepts provided or any of its synonyms. If
successful, the response will have status 200 OK, containing a list of dataset ids in the data
index. You can provide
multiple concepts by splitting them with blank spaces.
Filters
Filtering searched datasets by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/search-by-label-synonyms?application=gfw \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated to this concept - read more about this field here. | String | "rw" |
env | Only list datasets that have the specified environment. | String (can be a comma separated list of env values) | none |
Errors for searching datasets by concepts and their synonyms
Error code | Error message | Description |
---|---|---|
400 | Search query param required | You must provide the search query parameter. |
Most liked datasets
GET request to find out which are the most liked datasets:
curl -X GET https://api.resourcewatch.org/v1/graph/query/most-liked-datasets \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Example response:
{
"data": [
{
"id": "c36c3108-2581-4b68-852a-c929fc758001",
"count": {
"low": 6,
"high": 0
}
},
{
"id": "20cc5eca-8c63-4c41-8e8e-134dcf1e6d76",
"count": {
"low": 5,
"high": 0
}
}
]
}
This endpoint returns a list of dataset sorted by the number of times these datasets were marked as favorite by users. The returned list is sorted descending, from the datasets with higher favorite count to the ones with a lower count.
If successful, this endpoint will return 200 OK, containing the list of sorted datasets in the data
index of the
response body. Each element of the list contains the dataset id in the id
property and the number of times the dataset
was marked as favorite by a user in the count.low
property.
Filters
Filtering most liked datasets by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/most-liked-datasets?application=gfw \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated to this concept - read more about this field here. | String | "rw" |
env | Only list datasets that have the specified environment. | String (can be a comma separated list of env values) | none |
Most viewed datasets
GET request to find out which are the most viewed datasets:
curl -X GET https://api.resourcewatch.org/v1/graph/query/most-viewed \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Example response:
{
"data": [
{
"dataset": "0087944f-871c-44bc-b4d9-cd5acfc27023",
"views": 76
},
{
"dataset": "00abb46f-34e2-4bf7-be30-1fb0b1de022f",
"views": 39
}
]
}
This endpoint returns a list of dataset sorted by the number of times these datasets were viewed by users. The returned list is sorted descending, from the datasets with higher view count to the ones with a lower count.
If successful, this endpoint will return 200 OK, containing the list of sorted datasets in the data
index of the
response body. Each element of the list contains the dataset id in the dataset
property and the number of times the
dataset was viewed in the views
property.
Note that the concept of view might differ from one application to another. In order to increase the view count of a dataset, an application has to explicitly increment the count for that dataset by calling the increment view endpoint.
Filters
Filtering most viewed datasets by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/most-viewed?application=gfw \
-H "x-api-key: <your-api-key>"
Limiting the number of returned results:
curl -X GET https://api.resourcewatch.org/v1/graph/query/most-viewed?limit=3 \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated with this concept - read more about this field here. | String | "rw" |
limit | Limits the number of results returned in the response. | Number | No limit applied - all results are returned. |
env | Only list datasets that have the specified environment. | String (can be a comma separated list of env values) | none |
Most viewed datasets by user
GET request to find out which are the most viewed datasets for the token user:
curl -X GET https://api.resourcewatch.org/v1/graph/query/most-viewed \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Example response:
{
"data": [
{
"dataset": "0087944f-871c-44bc-b4d9-cd5acfc27023",
"views": 76
},
{
"dataset": "00abb46f-34e2-4bf7-be30-1fb0b1de022f",
"views": 39
}
]
}
This endpoint returns a list of dataset sorted by the number of times these datasets were viewed by the user of the token provided in the request headers. The returned list is sorted descending, from the datasets with higher view count to the ones with a lower count.
If successful, this endpoint will return 200 OK, containing the list of sorted datasets in the data
index of the
response body. Each element of the list contains the dataset id in the dataset
property and the number of times the
dataset was viewed in the views
property.
As in the case of the most-viewed
endpoint, please keep in mind that the concept of view might differ from one
application to another. In order to increase the view count of a dataset, an application has to explicitly increment the
count for that dataset by calling the increment view endpoint.
Filters
Filtering most viewed datasets by the token user by application:
curl -X GET https://api.resourcewatch.org/v1/graph/query/most-viewed-by-user?application=gfw \
-H "x-api-key: <your-api-key>"
Limiting the number of returned results:
curl -X GET https://api.resourcewatch.org/v1/graph/query/most-viewed-by-user?limit=3 \
-H "x-api-key: <your-api-key>"
This endpoint supports the following filters as query string parameters:
Filter | Description | Type | Default value |
---|---|---|---|
application | Applications associated with this concept - read more about this field here. | String | "rw" |
limit | Limits the number of results returned in the response. | Number | No limit applied - all results are returned. |
env | Only list datasets that have the specified environment. | String (can be a comma separated list of env values) | none |
Errors for getting most viewed datasets by user
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You must provide your API user's token in the response headers. |
Increment dataset view count
POST request to find out which are the most viewed datasets for the token user:
curl -X POST https://api.resourcewatch.org/v1/graph/dataset/:id/visited \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Use this endpoint if you want to increment the view count of the dataset with id provided in the URL path. If successful, this endpoint will return 200 OK containing an empty object in the response body.
You can optionally provide the authentication token for your API user in the request headers. If no token is provided, a dataset view is registered without being associated with any user. If a token is provided, the dataset view count for your API user will be incremented.
Creating resources
The creation of resources on the graph is performed automatically after the creation of each resource, so you don't
need to explicitly do it yourself. Because of this, creating resources on the graph is restricted to other RW API
services, and requires authentication from a RW API service. Normal API users won't be able to call these endpoints
successfully - if you try to do it with a "normal" API user token, you will receive a response with HTTP status
code 403 Forbidden
.
For details on how these specific endpoints work, you should check out the developer docs for each of the resources supported. The following resources are currently supported as graph nodes:
Deleting resources
The deletion of resources on the graph is performed automatically after the deletion of each resource, so you don't
need to explicitly do it yourself. Because of this, deleting resources on the graph is restricted to other RW API
services, and requires authentication from a RW API service. Normal API users won't be able to call these endpoints
successfully - if you try to do it with a "normal" API user token, you will receive a response with HTTP status
code 403 Forbidden
.
For details on how these specific endpoints work, you should check out the developer docs for each of the resources supported. The following resources are currently supported as graph nodes:
Relationships between graph nodes and concepts
Getting the list of concepts for a dataset:
curl -X GET https://api.resourcewatch.org/v1/graph/query/list-concepts/:id \
-H "x-api-key: <your-api-key>"
Example response, containing the "urban" concept:
{
"data": [
{
"id": "37d04efc-0ab2-4499-a891-54dca1013c74",
"type": "graph",
"attributes": {
"iso": "",
"synonyms": [
"city",
"urban"
],
"id": "urban",
"label": "Cities",
"default_parent": "settlements"
}
}
]
}
Getting vocabulary for the same dataset:
curl -X GET https://api.resourcewatch.org/v1/dataset/:id/vocabulary \
-H "x-api-key: <your-api-key>"
Example response, containing the "knowledge_graph" vocabulary with the "urban" tag associated:
{
"data": [
{
"id": "knowledge_graph",
"type": "vocabulary",
"attributes": {
"tags": [
"urban"
],
"name": "knowledge_graph",
"application": "rw"
}
}
]
}
Creating (if it doesn't exist yet) the association between the vocabulary "knowledge_graph" and a dataset:
curl -X POST https://api.resourcewatch.org/v1/dataset/:id/vocabulary/knowledge_graph \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-token>' \
-d '{
"application": "rw",
"tags": ["urban", "society"]
}'
Editing the association between the vocabulary "knowledge_graph" and a dataset:
curl -X PATCH https://api.resourcewatch.org/v1/dataset/:id/vocabulary/knowledge_graph \
-H "x-api-key: <your-api-key>" \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer <your-token>' \
-d '{
"application": "rw",
"tags": ["urban"]
}'
Deleting the association between the vocabulary "knowledge_graph" and a dataset:
curl -X DELETE https://api.resourcewatch.org/v1/dataset/:id/vocabulary/knowledge_graph \
-H "x-api-key: <your-api-key>"
The management of connections between resources and concepts is handled by vocabulary endpoints, using the
vocabulary "knowledge_graph"
. Using this vocabulary, you can add tags to your dataset. These tags will be added as
concepts, and one (or more, accordingly) graph edges will be created, establishing a connection between your resource
and the provided tags.
This section provides some examples of how you can use vocabulary endpoints to manage your resources' concepts. Keep in mind that you can always refer to the vocabulary endpoint documentation for more details on how to use these endpoints.
On the examples on the side, you'll be able to understand that you can map the tags associated with a given resource
with the tags associated with the "knowledge_graph"
vocabulary for the same resource. You can use vocabulary's
endpoints to create (if it doesn't exist yet), edit, or delete the tags associated with that resource. Those changes
will be reflected in the concepts that are associated with that same resource.
Lastly, keep in mind that, despite the examples on the side refer to datasets, you can use vocabulary's endpoints to
update the tags associated with the "knowledge_graph"
vocabulary for all supported resource types: datasets, layers,
widgets, and metadata.
Favorite relationships between graph nodes and users
As in the case of managing relationships between graph nodes and concepts, the management of favorite relationships between resources and users is handled by vocabulary endpoints. Please refer to the favorite endpoint documentation for more details on how to use these endpoints.
Graph concept reference
Example concept entity structure:
{
"id": "society",
"label": "Society",
"synonyms": [
"People"
],
"labels": [
"CONCEPT",
"TOPIC"
],
"numberOfDatasetsTagged": 1,
"datasets": [
"4458eb12-8572-45d1-bf07-d5a3ee097021"
]
}
This section describes the attributes that are present on a graph concept entity:
Field name | Type | Description |
---|---|---|
id |
String | The concept unique identifier. |
label |
String | A readable version of the concept identifier. |
synonyms |
String | Array | The list of synonyms for this concept (or an empty string, if no synonyms exist). |
labels |
Array | The list of identifiers for the type of this graph node. |
numberOfDatasetsTagged |
Number | The number of datasets that are currently tagged with this concept. |
datasets |
Array | The list of dataset ids that are currently tagged with this concept. |
Graph relationship reference
Example relationship entity structure:
{
"id": "4458eb12-8572-45d1-bf07-d5a3ee097021",
"type": "graph",
"attributes": {
"iso": "",
"synonyms": [
"Habitat"
],
"id": "habitat",
"label": "Habitats",
"default_parent": "ecosystem"
}
}
This section describes the attributes that are present on a graph relationship entity:
Field name | Type | Description |
---|---|---|
id |
String | The id of the relationship (usually the dataset id, if finding concepts related to a dataset). |
type |
String | Always set to "graph". |
attributes.iso |
String | Deprecated attribute - you should not rely on this attribute. |
attributes.synonyms |
Array | A list of synonyms for this concept. |
attributes.id |
String | The concept unique identifier. |
attributes.label |
String | A readable version of the concept identifier. |
attributes.default_parent |
String | The id of the parent concept, if existing. |
Areas
Note: the documentation for these endpoints is not maintained and might not be up to date.
The following sections describe endpoints API users can use to interact with version 1 of Areas of Interest.
Get user areas
Getting a list of areas for the current user
curl -X GET https://api.resourcewatch.org/v1/area
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Response:
{
"data": [
{
"type": "area",
"id": "59ca3213d08a7d001054522b",
"attributes": {
"name": "Test area France",
"application": "rw",
"geostore": "8f77fe62cf15d5098ba0ee11c5126aa6",
"userId": "58e22f662071c01c02f76a0f",
"env": "production",
"createdAt": "2017-09-26T10:55:15.990Z",
"updatedAt": "2017-09-26T10:55:15.990Z",
"image": "",
"datasets": [
],
"use": {
},
"iso": {
}
}
},
{
"type": "area",
"id": "59ca32ea3209db0014e9a7b7",
"attributes": {
"name": "Test custom area",
"application": "rw",
"geostore": "b12640deba9d3c5012c5359dd5572e2d",
"userId": "58e22f662071c01c02f76a0f",
"env": "production",
"createdAt": "2017-09-26T10:58:50.226Z",
"updatedAt": "2017-09-26T10:58:50.226Z",
"image": "",
"datasets": [
],
"use": {
},
"iso": {
}
}
}
]
}
Returns the list of areas created by the user provided.
Filters
Getting a list of areas for the current user and a given application
curl -X GET https://api.resourcewatch.org/v1/area?application=rw
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Parameter | Description | Type | Values |
---|---|---|---|
application | Application. Read more about this field here. | Text | Any Text, values separated by commas |
env | Environment. Read more about this field here. | Text |
Pagination
Example request to load page 2 using 25 results per page
curl -X GET https://api.resourcewatch.org/v1/area?page[number]=2&page[size]=25 \
-H "x-api-key: <your-api-key>"
The Areas service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your areas list.
In the specific case of the Areas service, the default value for the page[size]
query parameter is 1000 for backwards compatibility reasons, instead of 10. However (as recommended in the pagination guidelines), you should not rely on the default page size and always provide a value tailored to your needs.
Sorting
Sorting areas
curl -X GET https://api.resourcewatch.org/v1/area?sort=name \
-H "x-api-key: <your-api-key>"
Sorting areas by multiple criteria
curl -X GET https://api.resourcewatch.org/v1/area?sort=name,createdAt \
-H "x-api-key: <your-api-key>"
Sort by name descending, createdAt ascending
curl -X GET https://api.resourcewatch.org/v1/area?sort=-name,+createdAt \
-H "x-api-key: <your-api-key>"
The Areas service currently supports sorting using the sort
query parameter. Sorting areas adheres to the conventions defined in the Sorting guidelines for the RW API, so we strongly recommend reading that section before proceeding.
Create area
Creates a new area
Parameters
Parameter | Description | Type | Values | Required |
---|---|---|---|---|
application | Application. Read more about this field here. | Text | Any Text, values separated by commas | Yes |
name | Name of the new area | Text | Any Text | Yes |
geostore | Geostore ID | Text | Any Text | Yes |
env | Environment. Read more about this field here. | Text | Any Text | No |
curl -X POST https://api.resourcewatch.org/v1/area \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": <name>,
"application": <application>,
"geostore": <geostore id>
}'
Example
Create an area with name 'Portugal area' and Geostore ID '713899292fc118a915741728ef84a2a7' for the Resource Watch application
curl -X POST https://api.resourcewatch.org/v1/area?application=rw \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": "Portugal area",
"application": "rw",
"geostore": "713899292fc118a915741728ef84a2a7"
}'
{
"data": {
"type": "area",
"id": "5a0da028e6d876001080c259",
"attributes": {
"name": "Portugal area",
"application": "rw",
"geostore": "713899292fc118a915741728ef84a2a7",
"userId": "58e22f662071c01c02f76a0f",
"env": "production",
"createdAt": "2017-11-16T14:26:48.396Z",
"updatedAt": "2017-11-16T14:26:48.396Z",
"image": "",
"datasets": [
],
"use": {
},
"iso": {
}
}
}
}
Delete area
Deletes an area
curl -X DELETE https://api.resourcewatch.org/v1/area/<area-id> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example
curl -X DELETE https://api.resourcewatch.org/v1/area/59ca3213d08a7d001054522b \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Delete areas by user id
curl -X DELETE https://api.resourcewatch.org/v1/area/by-user/<user-id> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"type": "area",
"id": "59ca3213d08a7d001054522b",
"attributes": {
"name": "Test area France",
"application": "rw",
"geostore": "8f77fe62cf15d5098ba0ee11c5126aa6",
"userId": "58e22f662071c01c02f76a0f",
"env": "production",
"createdAt": "2017-09-26T10:55:15.990Z",
"updatedAt": "2017-09-26T10:55:15.990Z",
"image": "",
"datasets": [
],
"use": {
},
"iso": {
}
}
},
{
"type": "area",
"id": "59ca32ea3209db0014e9a7b7",
"attributes": {
"name": "Test custom area",
"application": "rw",
"geostore": "b12640deba9d3c5012c5359dd5572e2d",
"userId": "58e22f662071c01c02f76a0f",
"env": "production",
"createdAt": "2017-09-26T10:58:50.226Z",
"updatedAt": "2017-09-26T10:58:50.226Z",
"image": "",
"datasets": [
],
"use": {
},
"iso": {
}
}
}
]
}
This endpoint deletes all areas for the provided userId
. Any microservice or user with ADMIN role can use this endpoint. Regular users can use this endpoint to delete the areas they own.
Errors for deleting areas by user id
Error code | Error message (example) | Description |
---|---|---|
401 | Unauthorized |
No token was provided. |
403 | Not authorized |
You are trying to delete the areas of an user that is not the same logged user, not an ADMIN user or a microservice. |
Get area
Gets all the information from an area
curl -X GET https://api.resourcewatch.org/v1/area/<area-id> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example
curl -X GET https://api.resourcewatch.org/v1/area/59ca32ea3209db0014e9a7b7 \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
{
"data": {
"type": "area",
"id": "59ca32ea3209db0014e9a7b7",
"attributes": {
"name": "Test custom area",
"application": "rw",
"geostore": "b12640deba9d3c5012c5359dd5572e2d",
"userId": "58e22f662071c01c02f76a0f",
"env": "production",
"createdAt": "2017-09-26T10:58:50.226Z",
"updatedAt": "2017-09-26T10:58:50.226Z",
"image": "",
"datasets": [],
"use": {},
"iso": {}
}
}
}
Areas v2
Before reading any further, please ensure you have read the Areas of Interest concept documentation first. It gives you a brief and clear description of what an Area of Interest is and what it can do for you.
Once you've read that section, you can come back here to learn more details about using the RW API's Areas service. Areas of Interest are used by the Global Forest Watch website to subscribe to notifications on deforestation and fire alerts inside a particular areas you might be interest in. The sections below describe in detail how you can use the endpoints provided by RW API's Areas service to define your own geographic areas of interest.
What is the difference between v1 and v2?
v2 areas are an upgrade in the functionality of the Areas service, and provide you with an easier-to-use interface for creating Areas of Interest. Features such as the notification of alerts inside your Area of Interest are only available in v2 endpoints.
Up until v2 areas endpoints were available, you could create Areas of Interest, but you could not define deforestation or fire alerts for your areas. In order to do that, you would need to manually create a subscription that referenced your Area of Interest. Not only that, but you also needed to manage this interaction between Areas of Interest and Subscriptions by yourself.
v2 areas endpoints were built with the intention of automating this interaction between areas and subscriptions, thus merging together v1 areas of interest and subscriptions. In practice, this means that, if your users already had v1 areas or subscriptions previously created, they will show up as v2 areas when requesting data from the v2 endpoints. This also means that, if your application was already using either subscriptions or v1 areas, you can safely transition into v2 areas while keeping the legacy v1 areas and subscriptions that your users have created.
Throughout the sections below, you'll be able to find Implementation details sections that dive deeper into how this synchronization between Areas and Subscriptions is performed on each particular case.
Interaction between Areas and Subscriptions
As it was stated in the paragraphs above, you can use v2 endpoint to create Areas of Interest and subscribe to deforestation of fire alerts. These subscriptions (and the associated emails or webhook notifications) are handled by the Subscriptions service. This means in practice that each Area might have a Subscription associated. If this is the case, the Area's subscriptionId
property will contain the id of the associated Subscription from the Subscriptions service.
This interaction between Areas and Subscriptions is transparent for the API users, meaning that you don't need to worry about creating, updating or deleting the subscriptions associated to your areas - this happens automatically, taken into account the Area properties.
Getting all user areas
Example request to get all areas for the logged user:
curl -X GET https://api.resourcewatch.org/v2/area \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"type": "area",
"id": "5e4d74c3ef240412c2d56a71",
"attributes": {
"application": "gfw",
"userId": "5e2f0eaf9de40a6c87dd9b7d",
"createdAt": "2020-02-19T12:17:01.176Z",
"datasets": [],
"use": {},
"env": "production",
"iso": {},
"admin": {},
"tags": [],
"status": "saved",
"public": false,
"fireAlerts": false,
"deforestationAlerts": false,
"webhookUrl": "",
"monthlySummary": false,
"subscriptionId": "5e4d273dce77c53768bc24f9",
"email": "your.email@resourcewatch.org",
"language": "en"
}
}
]
}
The /v2/areas
endpoint returns all the areas of interest associated with the user who made the request. For a detailed description of each field, check out the Area reference section.
Pagination
Example request to load page 2 using 25 results per page
curl -X GET https://api.resourcewatch.org/v2/area?page[number]=2&page[size]=25 \
-H "x-api-key: <your-api-key>"
The Areas v2 service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your areas list.
In the specific case of the Areas v2 service, the default value for the page[size]
query parameter is 100, instead of 10. However, this default value will be reduced to 10 in future releases, so (as recommended in the pagination guidelines), you should not rely on the default page size and always provide a value tailored to your needs.
Filters
Filtering areas
curl -X GET https://api.resourcewatch.org/v2/area?application=rw&public=true \
-H "x-api-key: <your-api-key>"
The /v2/areas
endpoint provides the following parameters to tailor the returned listing:
Field | Description | Type | Example |
---|---|---|---|
application | Filter results by the application associated with the areas. | String | 'gfw' |
status | Filter results by the status of the area. | String | 'saved' |
public | Filter results by the privacy status of the area. | Boolean | true |
env | Environment to which the area belongs. Multiple values can be combined using , as a separator. Does not support regexes. Read more about this field in the Environments concept section. |
String | any valid text. Defaults to production . |
all | Return all the areas instead of just the areas associated with user of the request. This filter will only be taken into account for ADMIN users. | Boolean | true |
Sorting
Sorting areas
curl -X GET "https://api.resourcewatch.org/v2/area?sort=name" \
-H "x-api-key: <your-api-key>"
Sorting layers by multiple criteria
curl -X GET "https://api.resourcewatch.org/v2/area?sort=name,status" \
-H "x-api-key: <your-api-key>"
Explicit order of sorting
curl -X GET "https://api.resourcewatch.org/v2/area?sort=-name,+status" \
-H "x-api-key: <your-api-key>"
The Areas v2 service currently supports sorting using the sort
query parameter. Sorting v2 areas adheres to the conventions defined in the Sorting guidelines for the RW API, so we strongly recommend reading that section before proceeding. Additionally, you can check out the Area reference section for a detailed description of the fields you can use when sorting.
Errors for getting user areas
Error code | Error message (example) | Description |
---|---|---|
401 | Unauthorized |
No authorization token was provided. |
Implementation details
Finds all areas for the user who requested the list of areas. For each area, if it has an associated subscription (i.e. the subscriptionId
field of the area is not empty), it merges the subscription data over the area data, returning it as a single object. After that, the remaining user subscriptions are converted to area objects and returned.
Getting all areas
Example request to get ALL areas (only available for ADMIN users):
curl -X GET https://api.resourcewatch.org/v2/area?all=true \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"type": "area",
"id": "5e4d74c3ef240412c2d56a71",
"attributes": {
"application": "gfw",
"userId": "5e2f0eaf9de40a6c87dd9b7d",
"createdAt": "2020-02-19T12:17:01.176Z",
"updatedAt": "2020-02-19T12:17:01.176Z",
"datasets": [],
"use": {},
"env": "production",
"iso": {},
"admin": {},
"tags": [],
"status": "saved",
"public": false,
"fireAlerts": false,
"deforestationAlerts": false,
"webhookUrl": "",
"monthlySummary": false,
"subscriptionId": "5e4d273dce77c53768bc24f9",
"email": "your.email@resourcewatch.org",
"language": "en"
}
}
],
"links": {
"self": "https://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10",
"last": "https://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10",
"prev": "https://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10"
},
"meta": {
"total-pages": 1,
"total-items": 1,
"size": 10
}
}
The same /v2/areas
endpoint, used to retrieve all of the logged user's areas, can be used to retrieve ALL areas (for all users). To trigger this behavior, all you need to do is provide the all=true
flag as a query parameter - keep in mind this option will only be taken into account for ADMIN users (i.e. if the logged user is not an ADMIN, the all=true
flag is ignored and the logged user's areas are returned).
For a detailed description of each field, check out the Area reference section.
Pagination
Example request to load page 2 using 25 results per page
curl -X GET https://api.resourcewatch.org/v2/area?page[number]=2&page[size]=25&all=true \
-H "x-api-key: <your-api-key>"
The Areas v2 service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your areas list.
Filters
Filtering areas
curl -X GET https://api.resourcewatch.org/v2/area?application=rw&public=true&all=true \
-H "x-api-key: <your-api-key>"
The filters for this endpoint are the same as the /v2/areas
endpoint described above:
Field | Description | Type | Example |
---|---|---|---|
application | Filter results by the application associated with the areas. Read more about this field here. | String | 'gfw' |
status | Filter results by the status of the area. | String | 'saved' |
public | Filter results by the privacy status of the area. | Boolean | true |
env | Environment to which the area belongs. Multiple values can be combined using , as a separator. Does not support regexes. Read more about this field in the Environments concept section. |
String | any valid text. Defaults to production . |
all | Return all the areas instead of just the areas associated with user of the request. This filter will only be taken into account for ADMIN users. | Boolean | true |
Errors for getting all areas
Error code | Error message (example) | Description |
---|---|---|
401 | Unauthorized |
No authorization token was provided. |
Implementation details
If the all=true
query filter is provided, the /find-all
endpoint of the Subscriptions service is used to find all existing subscriptions (for all users).
Then, for each area in the Areas service database, if it has an associated subscription (i.e. the subscriptionId
field of the area is not empty), it merges the subscription data over the area data, returning it as a single object. After that, the remaining subscriptions are converted to area objects and returned.
Getting an area by its id
curl -X GET https://api.resourcewatch.org/v2/area/:id \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": {
"type": "area",
"id": "5e4d787bef240412c2d56a74",
"attributes": {
"application": "gfw",
"userId": "5e2f0eaf9de40a6c87dd9b7d",
"createdAt": "2020-02-19T12:17:01.176Z",
"updatedAt": "2020-02-19T12:17:01.176Z",
"datasets": [],
"use": {},
"env": "production",
"iso": {},
"admin": {},
"tags": [],
"status": "saved",
"public": false,
"fireAlerts": false,
"deforestationAlerts": false,
"webhookUrl": "",
"monthlySummary": false,
"subscriptionId": "5e4d273dce77c53768bc24f9",
"email": "tiago.garcia@vizzuality.com",
"language": "en"
}
}
}
If you know the id or the slug of a area, then you can access it directly - keep in mind the id search is case-sensitive. If the area has the public
attribute set to false
, you will only be able to fetch its information if you are the owner of the area. If the area has the public
attribute set to true
and the user who requests it is not the owner, some information will be hidden for privacy reasons.
Errors for getting an area by its id
Error code | Error message (example) | Description |
---|---|---|
401 | Unauthorized |
No authorization token was provided. |
401 | Area private |
You are trying to get the information of a private area without being the owner of the area. |
Implementation details
Try to find an area with the id provided:
- If the area exists:
- If the area has an associated subscription, the subscription is fetched, its data is merged over the area and the result is returned.
- If the area has no subscription associated, the area data is returned.
- If the area does not exist:
- Try to find a subscription with the id provided. If it exists, it is returned as an area object, if not, a
404 Not Found
error is returned.
- Try to find a subscription with the id provided. If it exists, it is returned as an area object, if not, a
Creating an area
Example request to create an area
curl -X POST https://api.resourcewatch.org/v2/area \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": "Example area",
"application": "gfw",
"image": "",
"tags": [],
"public": false,
"fireAlerts": true,
"deforestationAlerts": true,
"webhookUrl": "https://example.com",
"monthlySummary": true,
"email": "youremail@resourcewatch.org",
"language": "en"
}'
Example request to create an area with an associated image
curl --location --request POST 'https://api.resourcewatch.org/v2/area' \ \
-H "x-api-key: <your-api-key>"
-H 'Authorization: Bearer <your-token>' \
--form 'name="Example area"' \
--form 'geostore="a15899292fc118a345741728ef84a21a"' \
--form 'deforestationAlerts="true"' \
--form 'deforestationAlertsType="glad-s2"' \
--form 'image=@"/home/user/image.jpg"'
Example response:
{
"data": {
"type": "area",
"id": "5e4d7c47ef240412c2d56a78",
"attributes": {
"name": "Example area",
"application": "gfw",
"wdpaid": null,
"userId": "5e2f0eaf9de40a6c87dd9b7d",
"createdAt": "2020-02-19T18:19:51.485Z",
"updatedAt": "2020-02-19T18:19:51.485Z",
"image": "https://s3.amazonaws.com/image.jpg",
"env": "production",
"datasets": [],
"tags": [],
"status": "pending",
"public": false,
"fireAlerts": true,
"deforestationAlerts": true,
"webhookUrl": "https://example.com",
"monthlySummary": true,
"subscriptionId": "5e4d7c47dd8fa31290d548ae",
"email": "youremail@resourcewatch.org",
"language": "en"
}
}
}
Use this endpoint to create new areas. For a detailed description of each field that can be provided in the body of the request, check out the Area reference section.
Keep in mind that you should provide one of the following when creating an area:
geostore
with the id of a geostore object obtained from RW API's Geostore service, if you are creating an area that references a geostore;geostoreDataApi
with the id of a geostore object obtained from the GFW Data API, as an alternative way to create an area that references a geostore;wdpaid
with the id of a protected area if you are creating an area that references a protected area;iso
object with a valid country/region/subregion if you are creating an area that references an admin country/region/subregion;use
object with valid id and name of a land use concessioned area, if you are creating an area that references a land use area.
According to multiple factors (including the geostore
that is associated with the area, if the area subscribes to fireAlerts
, deforestationAlerts
, etc.), there might be a period of time in which the data for the area is being generated. While that is the case, the area will have status
set to 'pending'
. Once the area data is ready, the status
of the area will be updated to 'saved'
.
Errors for creating an area
Error code | Error message (example) | Description |
---|---|---|
400 | <field> can not be empty. |
You are missing a required field while creating the area. |
400 | <field> is not valid. |
You provided an invalid field while creating the area. |
400 | geostore and geostoreDataApi are mutually exclusive, cannot provide both at the same time |
You are trying to provide geostore and geostoreDataApi at the same time, and only one of the fields can be provided. |
401 | Unauthorized |
No token was provided. |
Email notifications
After creating an area, if the email
field of the area contains a valid email address, an email is sent to the user. The email content varies according to the status of the area:
- If the area has status
saved
, an email is sent to let the user know the area of interest is ready to be viewed. - If the area has status
pending
, an email is sent to let the user know the area of interest is being generated and will be available later.
If you want to understand more about how these emails are sent or how you can update its content, please check the developer docs section on Areas v2 Email Notifications.
Implementation details
POST of a new area always starts by creating the area. Then, taking into account the area attributes, it might also create a subscription which will then be associated with the area. The area's subscriptionId
attribute will then be updated with the id of the created subscription if that's the case. The created area is then returned.
The subscription is created only if the area has selected set to true
at least one of the following attributes:
deforestationAlerts
fireAlerts
monthlySummary
Updating an area
Example request to update an area
curl -X PATCH https://api.resourcewatch.org/v2/area/:id \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"name": "Example area",
"application": "gfw",
"tags": [],
"public": false,
"fireAlerts": true,
"deforestationAlerts": true,
"webhookUrl": "https://example.com",
"monthlySummary": true,
"email": "youremail@resourcewatch.org",
"language": "en"
}'
Example request to update an area with an associated image
curl --location --request PATCH 'https://api.resourcewatch.org/v2/area/:id' \ \
-H "x-api-key: <your-api-key>"
-H 'Authorization: Bearer <your-token>' \
--form 'name="Example area"' \
--form 'geostore="a15899292fc118a345741728ef84a21a"' \
--form 'deforestationAlerts="true"' \
--form 'deforestationAlertsType="glad-s2"' \
--form 'image=@"/home/user/image.jpg"'
Example response:
{
"data": {
"type": "area",
"id": "5e4d7c47ef240412c2d56a78",
"attributes": {
"name": "Example area",
"application": "gfw",
"wdpaid": null,
"userId": "5e2f0eaf9de40a6c87dd9b7d",
"createdAt": "2020-02-19T18:19:51.485Z",
"updatedAt": "2020-05-29T22:17:12.176Z",
"image": "https://s3.amazonaws.com/image.jpg",
"env": "production",
"datasets": [],
"tags": [],
"status": "pending",
"public": false,
"fireAlerts": true,
"deforestationAlerts": true,
"webhookUrl": "https://example.com",
"monthlySummary": true,
"subscriptionId": "5e4d7c47dd8fa31290d548ae",
"email": "youremail@resourcewatch.org",
"language": "en"
}
}
}
Use this endpoint to update an existing area. For a detailed description of each field that can be provided in the body of the request, check out the Area reference section. Keep in mind that you must provide one of the following when updating an area:
geostore
with the id of a geostore object obtained from RW API's Geostore service, if you are updating an area that references a geostore;geostoreDataApi
with the id of a geostore object obtained from the GFW Data API, as an alternative way to update an area that references a geostore;wdpaid
with the id of a protected area if you are updating an area that references a protected area;iso
object with a valid country/region/subregion if you are updating an area that references an admin country/region/subregion;use
object with valid id and name of a land use concessioned area, if you are updating an area that references a land use area.
Please check the Area model reference for details on what values each field is expected to provide.
Errors for updating an area
Error code | Error message (example) | Description |
---|---|---|
400 | <field> can not be empty. |
You are missing a required field while updating the area. |
400 | <field> is invalid. |
You provided an invalid field while updating the area. |
400 | Id required |
No id was provided in the URL. |
400 | geostore and geostoreDataApi are mutually exclusive, cannot provide both at the same time |
You are trying to provide geostore and geostoreDataApi at the same time, and only one of the fields can be provided. |
401 | Unauthorized |
No token was provided. |
403 | Not authorized |
You are trying to update an area that is not owned by you and you are not an ADMIN user. |
404 | Area not found |
The area with id provided does not exist. |
Email notifications
After updating an area, if the email
field of the area contains a valid email address and the area's status is saved
, an email is sent to let the user know the area of interest is ready to be viewed.
If you want to understand more about how these emails are sent or how you can update its content, please check the developer docs section on Areas v2 Email Notifications.
Implementation details
PATCHing an area is a bit more complex, and it comes down to 3 major cases:
- The area already exists and has subscriptions preference (
deforestationAlerts
,fireAlerts
ormonthlySummary
set to true) in the request data:- If the area doesn't have a subscription associated, a new one is created and associated.
- If the area already had a subscription, then the subscription is PATCHed according to the data provided in the request body.
- The area already exists and doesn’t has subscription preferences (
deforestationAlerts
,fireAlerts
ormonthlySummary
set to true) in the request data:- If the area had a subscription associated, then the subscription associated is deleted.
- Otherwise, just save the area.
- The area doesn’t exist because on the fetch it returned a mapped subscription (meaning we are PATCHing an area using the id of a subscription):
- First, create a new area, and then:
- If the request data has subscriptions preference (
deforestationAlerts
,fireAlerts
ormonthlySummary
set to true), also PATCH the subscription. - If the request data doesn't have subscriptions preference (
deforestationAlerts
,fireAlerts
ormonthlySummary
set to true), delete the associated subscription.
- If the request data has subscriptions preference (
- First, create a new area, and then:
Deleting an area
curl -X DELETE https://api.resourcewatch.org/v2/area/:id \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Returns 204 No Content in case of success.
Use this endpoint to delete an existing area. This endpoint requires authentication and, in order to DELETE an area, you need to be either the owner of the area or an ADMIN user.
DELETing an area deletes the area with id provided and any associated subscription with the area being deleted (identified by the id stored in the subscriptionId
field). This is done transparently from the perspective of an API user, so no action is needed to trigger this behavior.
Errors for deleting an area
Error code | Error message (example) | Description |
---|---|---|
400 | Id required |
No id was provided in the URL. |
401 | Unauthorized |
No token was provided. |
403 | Not authorized |
You are trying to delete an area that is not owned by you and you are not an ADMIN user. |
404 | Area not found |
The area with id provided does not exist. |
Deleting areas by user id
curl -X DELETE https://api.resourcewatch.org/v2/area/by-user/:user-id \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"type": "area",
"id": "5e4d74c3ef240412c2d56a71",
"attributes": {
"application": "gfw",
"userId": "5e2f0eaf9de40a6c87dd9b7d",
"createdAt": "2020-02-19T12:17:01.176Z",
"datasets": [],
"use": {},
"env": "production",
"iso": {},
"admin": {},
"tags": [],
"status": "saved",
"public": false,
"fireAlerts": false,
"deforestationAlerts": false,
"webhookUrl": "",
"monthlySummary": false,
"subscriptionId": "5e4d273dce77c53768bc24f9",
"email": "your.email@resourcewatch.org",
"language": "en"
}
}
]
}
This endpoint deletes all areas for the provided userId
. Any microservice or user with ADMIN role can use this endpoint. Regular users can use this endpoint to delete the areas they own.
Errors for deleting areas by user id
Error code | Error message (example) | Description |
---|---|---|
401 | Unauthorized |
No token was provided. |
403 | Not authorized |
You are trying to delete the areas of an user that is not the same logged user, not an ADMIN user or a microservice. |
Update areas by geostore
Example request to update all areas that reference geostores with ids "123" and "234":
curl -X POST https://api.resourcewatch.org/v2/area/update \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"geostores": ["123", "234"],
"update_params": {
"status": "saved",
"name": "Updated Area"
}
}'
Example response:
{
"data": [
{
"type": "area",
"id": "5e4d74c3ef240412c2d56a71",
"attributes": {
"application": "gfw",
"userId": "5e2f0eaf9de40a6c87dd9b7d",
"createdAt": "2020-02-19T12:17:01.176Z",
"updatedAt": "2020-05-29T22:17:12.176Z",
"datasets": [],
"use": {},
"env": "production",
"iso": {},
"admin": {},
"tags": [],
"status": "saved",
"public": false,
"fireAlerts": false,
"deforestationAlerts": false,
"webhookUrl": "",
"monthlySummary": false,
"subscriptionId": "5e4d273dce77c53768bc24f9",
"email": "tiago.garcia@vizzuality.com",
"language": "en"
}
}
]
}
Use this endpoint to batch update multiple areas that are associated with one of the geostore ids provided in the request body. In order to use this endpoint, you need to be authenticated as an ADMIN user.
You can use the update_params
field of the request body to specify multiple fields to update on the areas that belong to the geostore ids provided in the body. Keep in mind that the same validations as when updating an area are applied. If a validation fails, the request will fail with 400 Bad Request
and no area will be updated.
In case of success a 200 OK response is returned, and all the areas that match the update criteria (belonging to one of the geostores provided in the request body) will be returned.
Email notifications
After updating areas by geostore, for each area that was updated which has a valid email address associated and its status updated to saved
, an email will be sent to the user to let them know that the area is ready to be viewed.
If you want to understand more about how these emails are sent or how you can update its content, please check the developer docs section on Areas v2 Email Notifications.
Sync areas
curl -X POST https://api.resourcewatch.org/v2/area/sync \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": {
"syncedAreas": 8,
"createdAreas": 0
}
}
Example snippet that synchronizes the areas before fetching the information of ALL areas:
// First call the sync endpoint
await request.post('v2/area/sync');
// Then call the get endpoint while there are more pages to find
var results = [];
var hasNextPage = true;
var pageNumber = 1;
while (hasNextPage) {
var res = await request.get('v2/area?all=true&page[number]=' + pageNumber);
results = results.concat(res.data);
pageNumber++;
hasNextPage = res.links.self === res.links.last;
}
Use this endpoint to synchronize each area information with the associated subscription. The usage of this endpoint is recommended if you are performing update processes that rely on updated subscription information for the areas.
This endpoint supports the following query parameters to control the execution of the sync:
Field | Description | Type | Example |
---|---|---|---|
startDate | The date from which the sync will be executed. All subscriptions that have been updated since this date will be synced with the existing areas. | String | 2020-03-18T09:45:56.476Z |
endDate | The date until which the sync will be executed. All subscriptions that have been updated until this date will be synced with the existing areas. | String | 2020-03-25T09:45:56.476Z |
Note: By default, the sync is done for the last week changes (i.e. the default value for the startDate
parameter is one week ago and the default value for the endDate
parameter is now).
Area reference
This section gives you a complete view at the properties that are maintained as part of an area. When interacting with an area (on get, on create, etc) you will find most of these properties available to you, although they may be organized in a slightly different structure (ie: on get, everything but the id
is nested inside an attributes
object).
You can find more details in the source code.
Field name | Type | Required | Default value | Description |
---|---|---|---|---|
id | String | Yes (autogenerated) | Unique Id of the area. Auto generated on creation. Cannot be modified by users. | |
name | String | No | Name of the area. | |
application | String | Yes | 'gfw' | The application this area belongs to. |
env | String | Yes | production | Environment to which the area belongs. Read more about this field in the Environments concept section. |
geostore | String | No | If this area references a geostore obtained from RW API's Geostore service, the id of that geostore will be saved in this field. | |
geostoreDataApi | String | No | If this area references a geostore obtained from the GFW Data API, the id of that geostore will be saved in this field. | |
wdpaId | String | No | If this area references a WDPA, the id of the WDPA will be saved in this field. | |
userId | String | Yes (autopopulated) | Id of the user who owns the area. Set automatically on creation. Cannot be modified by users. | |
use | Object | No | If this area references a land use concession, this field will contain an object that identifies the concrete area referred. | |
use.id | String | No | The id of the land use concession to track. | |
use.name | String | No | The name of the land use concession to track. The supported values for this field include mining for mining areas, logging for Congo Basin logging roads, oilpalm for palm oil plantations and fiber for wood fiber plantations. |
|
iso | Object | No | If this area references an admin country or region, this field will contain an object that identifies the concrete area referred. | |
iso.country | String | No | The ISO 3166-1 alpha-3 code of the country being referred by this area. | |
iso.region | String | No | The GADM id of the region inside the country to reference (optional, you can reference the whole country, or just on specific region of the country). | |
iso.subregion | String | No | The GADM id of the subregion inside the region to reference (optional, you can reference the whole region, or just on specific subregion of the region). | |
admin | Object | No | Alternative syntax, see the iso field above. |
|
admin.adm0 | String | No | Alternative syntax, see the iso.country field above. |
|
admin.adm1 | String | No | Alternative syntax, see the iso.region field above. |
|
admin.adm2 | String | No | Alternative syntax, see the iso.subregion field above. |
|
image | String | No | URL for an image representative of the area of interest. When creating/updating areas, you can optionally attach a file to your request, which will be uploaded to a public image repository, and the URL for it will be returned in subsequent GET requests for said areas. Do not upload private/sensitive images. | |
templateId | String | No | ? | |
tags | Array | Yes | [] | Array of string tags that can be used to categorize areas. |
status | String | Yes | 'pending' | The status of the area - can be one of pending , saved or failed . Cannot be modified by users. Initially, it is set as pending . Once all the data for the area is crunched and ready to be read, the status is updated to saved and an email is sent to the user. If errors occur, the status is set to failed . |
public | Boolean | Yes | false | If the area is public or private. Public area information can be accessed by other users. |
fireAlerts | Boolean | Yes | false | If the area subscribes to notifications on fire alerts - set this field to true if you wish to be notified about fire alerts in your area of interest. |
deforestationAlerts | Boolean | Yes | false | If the area subscribes to notifications on deforestation alerts - set this field to true if you wish to be notified about deforestation alerts in your area of interest. |
monthlySummary | Boolean | Yes | false | If the area subscribes to monthly summary notifications - set this field to true if you wish to be notified monthly about deforestation and fire alerts in your area of interest. |
String | No | The email that will be used as receiver of the notification emails. | ||
webhookUrl | String | No | Instead of receiving an email as notification, you can choose to receive a hit in the webhook URL you set in this field. | |
language | String | No | 'en' | The language in which you wish to receive the email notifications. en , fr , zh , id , pt_BR or es_MX are the supported values for this field. If any other value is provided, en is automatically set. |
subscriptionId | String | No | If an area is returned as the reflection of an existing subscription in the Subscriptions service, this field will contain the id of the corresponding subscription. | |
createdAt | Date | No (autogenerated) | now | Automatically maintained date of when the area was created. Cannot be modified by users. |
updatedAt | Date | No (autogenerated) | now | Automatically maintained date of when the area was last updated. Cannot be modified by users. |
Webshot
The webshot set of endpoints allows you to capture a given page as a document file, that can then be used, for example, as a preview thumbnail.
This service has two endpoints:
This endpoint expects a URL as a query parameter and generates a pdf containing a rendered version of that page:
curl -X GET \
'https://api.resourcewatch.org/v1/webshot/pdf?url=https://google.com&filename=my-google-screenshoz.pdf' \
-H "x-api-key: <your-api-key>" \
-H 'Authorization: Bearer <your-token>' \
-H 'Content-Type: application/json' \
The endpoint accepts the following optional parameters:
height
- Configure the height of the generated screenshot.width
- Configure the width of the generated screenshot.format
- Configure the format of the generated screenshot, admitting two values:png
andpdf
.pdf
is the default value.
It is important to take into account that this endpoint works by rendering the https://resourcewatch.org/embed/widget/<widget id>
URL with those dimensions applied to the viewport. So the resulting screenshot will have the proportional size of the corresponding DOM element within that viewport, and not the exact height
and width
specified.
Widget thumbnail
This endpoint generates a thumbnail image for the provided widget and stores it on AWS S3.
curl -X POST \
https://api.resourcewatch.org/v1/webshot/widget/7b540186-9a9f-4e13-a6e8-f38e64fab2e1/thumbnail \
-H "x-api-key: <your-api-key>" \
-H 'Authorization: Bearer <your-token>' \
-H 'Content-Type: application/json' \
{
"data": {
"widgetThumbnail": "https://s3.amazonaws.com/resourcewatch/thumbnails/<filename>.png"
}
}
This endpoint accepts two optional query parameters, height
and width
, that configure the size of the generated screenshot. Keep in mind that this endpoint works by rendering the https://resourcewatch.org/embed/widget/<widget id>
URL with those dimensions applied to the viewport, and then captures the content of the .widget-content
DOM element into an image file. As such, the resulting screenshot will have the proportional size of the corresponding DOM element within that viewport, and not the exact height
and width
specified.
Layer thumbnail
This endpoint generates a thumbnail image for the provided layer and stores it on AWS S3.
curl -X POST \
https://api.resourcewatch.org/v1/webshot/layer/7b540186-9a9f-4e13-a6e8-f38e64fab2e1/thumbnail \
-H "x-api-key: <your-api-key>" \
-H 'Authorization: Bearer <your-token>' \
-H 'Content-Type: application/json' \
{
"data": {
"layerThumbnail": "https://s3.amazonaws.com/resourcewatch/thumbnails/<filename>.png"
}
}
This endpoint accepts two optional query parameters, height
and width
, that configure the size of the generated screenshot. Keep in mind that this endpoint works by rendering the https://resourcewatch.org/embed/layer/<layer id>
URL with those dimensions applied to the viewport, and then captures the content of the .layer-content
DOM element into an image file. As such, the resulting screenshot will have the proportional size of the corresponding DOM element within that viewport, and not the exact height
and width
specified.
Topic
What is a Topic?
A topic contains the information to display a web page belonging to a user.
Getting all topics
This endpoint will allow to get all topics belonging to a user:
curl -X GET https://api.resourcewatch.org/v1/topic -H 'Authorization: Bearer exampleToken' \
-H "x-api-key: <your-api-key>"
Response:
{
"data": [
{
"id": "10",
"type": "topics",
"attributes": {
"name": "Cities topic",
"slug": "cities-topic",
"summary": "",
"description": "",
"content": "<p></p>\n<iframe width=\"500\" height=\"410\" src=\"/embed/widget/5ebeddda-8f3d-4e63-8a52-08e15c3e148c\" frameBorder=\"0\"></iframe>\n<p></p>\n<iframe width=\"500\" height=\"410\" src=\"/embed/widget/73c574b9-f9ab-4f77-87be-651ff8dac5fe\" frameBorder=\"0\"></iframe>\n<p>test1</p>\n",
"published": true,
"env": "production",
"photo": {
"cover": "https://s3.amazonaws.com/image.jpg",
"thumb": "https://s3.amazonaws.com/image.jpg",
"original": "https://s3.amazonaws.com/image.jpg"
},
"user-id": "eb63867922e16e34ef3ce862",
"private": true,
"application": ["rw"]
}
},
...
]
}
Filters
Available filters parameters:
Field | Description | Type |
---|---|---|
published | Filter topics by publishing status (true, false) | Boolean |
private | Filter topics by private status (true, false) | Boolean |
user | Filter topics by author user id | Text |
application | The application to which the topic belongs. Read more about this field here. | Text (single value) |
env | Environment to which the topic belongs. Multiple values can be combined using , as a separator. Does not support regexes. Read more about this field in the Environments concept section. |
String |
curl -X GET https://api.resourcewatch.org/v1/topic?user=57bc2608f098ce98007985e4&private=false \
-H "x-api-key: <your-api-key>"
# Deprecated syntax
curl -X GET https://api.resourcewatch.org/v1/topic?filter[user]=57bc2608f098ce98007985e4&filter[private]=false \
-H "x-api-key: <your-api-key>"
Sorting
There's currently no support for custom sorting of topics. The topics are listed on a pseudo-random order.
Include related entities
When loading topics, you can optionally pass an includes
query argument to load additional data.
User
Loads the name and email address of the author of the topic. If you request this issue as an authenticated user with ADMIN role, you will additionally get the author's role.
If the data is not available (for example, the user has since been deleted), no user
property will be added to the layer object.
Please keep in mind that, due to the limitations of the underlying endpoint used to find users by ids, the performance of the request while including user information might be degraded.
curl -X GET https://api.resourcewatch.org/v1/topic?includes=user \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "86",
"type": "topics",
"attributes": {
"name": "Test topic three",
"slug": "test-topic-three-cd4305e9-e3c8-456b-85a0-32eccb6100e6",
"summary": "test topic three summary",
"description": "test topic three description",
"content": "test topic three description",
"published": true,
"env": "production",
"user-id": "57ac9f9e29309063404573a2",
"application": ["rw"],
"user": {
"name": "John Doe",
"role": "ADMIN",
"email": "john.doe@vizzuality.com"
}
}
}
]
}
Creating a topic
When creating a topic, the application
field should be present and cannot contain any values that are not associated with the creating user's account. If an application
value is not provided, ["rw"]
is used by default, and the process will fail if the user account does not belong to it. Any role can create a topic.
Supported fields:
Name | Description | Accepted values |
---|---|---|
name | Short name for the topic | any valid text |
slug | Unique identifier for the topic | any valid text |
summary | Summary of the content of the topic | any valid text |
description | Description of the topic | any valid text |
content | Content of the topic, typically encoded as a JSON string | any valid text |
published | If the topic is in a publishable state | boolean |
photo | Object containing a set of image urls associated with the topic | object |
user_id | Id of the user who created the topic | string with valid user id (not validated) |
private | boolean | |
application | Application(s) to which the topic belongs. Defaults to ["rw"] . Read more about this field here. |
array of strings |
env | Environment to which the topic belongs. Read more about this field in the Environments concept section. | string |
curl -X POST https://api.resourcewatch.org/v1/topics \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"data": {
"type": "topics",
"attributes": {
"name": "Cities",
"summary": "Traditional models of city development can lock us into congestion, sprawl, and inefficient resource use. However, compact, ...",
"description": "",
"content": "[{...}]",
"published": false,
"env": "production",
"photo": {
"cover": "...",
"thumb": "...",
"original": "..."
},
"user-id": "eb63867922e16e34ef3ce862",
"private": true,
"application": ["rw"]
}
}
}'
{
"data": {
"id": "243",
"type": "topics",
"attributes": {
"name": "Cities",
"slug": "cities-94bbc472-8970-4d9e-a3f2-d5422b1011e0",
"summary": "Traditional models of city development can lock us into congestion, sprawl, and inefficient resource use. However, compact, ...",
"description": "",
"content": "[{...}]",
"published": false,
"env": "production",
"photo": {
"cover": "...",
"thumb": "...",
"original": "..."
},
"user-id": "eb63867922e16e34ef3ce862",
"private": true,
"user": null,
"application": ["rw"]
}
}
}
Editing a topic
In order to perform this operation, the following conditions must be met:
- the user must be logged in and belong to the same application as the topic
- the user must comply with the RW API role-based access control guidelines.
When updating the application
field of a topic, a user cannot add values not associated with their user account.
curl -X PATCH https://api.resourcewatch.org/v1/topics/<id of the topic> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"data": {
"attributes": {
"description": "Topic related with cities."
}
}
}'
{
"data": {
"id": "243",
"type": "topics",
"attributes": {
"name": "Cities",
"slug": "cities-94bbc472-8970-4d9e-a3f2-d5422b1011e0",
"summary": "Traditional models of city development can lock us into congestion, sprawl, and inefficient resource use. However, compact, ...",
"description": "Topic related with cities.",
"content": "[{...}]",
"published": false,
"env": "production",
"photo": {
"cover": "...",
"thumb": "...",
"original": "..."
},
"user-id": "eb63867922e16e34ef3ce862",
"private": true,
"user": null,
"application": ["rw"]
}
}
}
Clone a topic
Clones an existing topic using its ID. If the original topic contains functioning widgets, they will be duplicated and the new ids will be used by the new topic.
curl -X POST https://api.resourcewatch.org/v1/topics/10/clone -H 'Authorization: Bearer exampleToken' \
-H "x-api-key: <your-api-key>"
{
"data": {
"id": "224",
"type": "topics",
"attributes": {
"name": "Cities",
"slug": "cities-a9cb2c87-f6b6-48cf-9b52-9e0de4fd8d6f",
"summary": "Traditional models of city development can lock us into congestion, sprawl, and inefficient resource use. However, compact, ...",
"description": "",
"content": "[{\"id\":1511952250652,\"type\":\"widget\",\"content\":{\"widgetId\":\"b9186ce9-78ae-418b-a6d3-d521283ce485\",\"categories\":[]}},...}]",
"published": false,
"env": "production",
"photo": {
"cover": "/system/topics/photos/data?1523301918",
"thumb": "/system/topics/photos/data?1523301918",
"original": "/system/topics/photos/data?1523301918"
},
"user-id": "eb63867922e16e34ef3ce862",
"private": true,
"application": ["rw"]
}
}
}
Dashboard
Note: the documentation for these endpoints is not maintained and might not be up to date.
What is a dashboard
A dashboard contains the information to display a web page belonging to a user.
Getting all dashboards
curl -X GET https://api.resourcewatch.org/v1/dashboard \
-H 'Authorization: Bearer <your-token>' \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "10",
"type": "dashboards",
"attributes": {
"name": "Cities Dashboard",
"slug": "cities-dashboard",
"summary": "",
"description": "",
"content": "<p></p>\n<iframe width=\"500\" height=\"410\" src=\"/embed/widget/5ebeddda-8f3d-4e63-8a52-08e15c3e148c\" frameBorder=\"0\"></iframe>\n<p></p>\n<iframe width=\"500\" height=\"410\" src=\"/embed/widget/73c574b9-f9ab-4f77-87be-651ff8dac5fe\" frameBorder=\"0\"></iframe>\n<p>test1</p>\n",
"published": true,
"photo": {
"cover": "https://s3.amazonaws.com/image.jpg",
"thumb": "https://s3.amazonaws.com/image.jpg",
"original": "https://s3.amazonaws.com/image.jpg"
},
"user-id": "eb63867922e16e34ef3ce862",
"private": true,
"env": "production",
"application": ["rw"],
"is-highlighted": false,
"is-featured": false,
"author-title": "",
"author-image": {
"cover": "/author_images/cover/missing.png",
"thumb": "/author_images/thumb/missing.png",
"original": "/author_images/original/missing.png"
}
}
}
],
"links": {
"self": "https://api.resourcewatch.org/v1/dashboard?page%5Bnumber%5D=1&page%5Bsize%5D=10",
"first": "https://api.resourcewatch.org/v1/dashboard?page%5Bnumber%5D=1&page%5Bsize%5D=10",
"prev": null,
"next": "https://api.resourcewatch.org/v1/dashboard?page%5Bnumber%5D=2&page%5Bsize%5D=10",
"last": "https://api.resourcewatch.org/v1/dashboard?page%5Bnumber%5D=14&page%5Bsize%5D=10"
},
"meta": {
"total-pages": 14,
"total-items": 140,
"size": 10
}
}
This endpoint will allow to get all dashboards belonging to a user.
Filters
Example request using query string filters:
curl -X GET https://api.resourcewatch.org/v1/dashboard?name=text&private=false \
-H "x-api-key: <your-api-key>"
Deprecated filter syntax:
curl -X GET https://api.resourcewatch.org/v1/dashboard?filter[name]=text&filter[private]=false \
-H "x-api-key: <your-api-key>"
Available filters parameters:
Field | Description | Type |
---|---|---|
name | Filter dashboards by name (partial matches and case-insensitive supported). | Text |
published | Filter dashboards by publishing status (true, false). | Boolean |
private | Filter dashboards by private status (true, false). | Boolean |
user | Filter dashboards by author user id. | Text |
user.role | The role of the user who created the dashboard. If the requesting user does not have the ADMIN role, this filter is ignored. | ADMIN , MANAGER or USER |
application | The application to which the dashboard belongs. Read more about this field here. | Text (single value) |
env | Environment to which the dashboard belongs. Multiple values can be combined using , as a separator. Does not support regexes. Read more about this field in the Environments concept section. |
Text |
is-highlighted | Filter dashboards by highlighted ones (true,false). | Boolean |
is-featured | Filter dashboards by featured ones (true,false). | Boolean |
author-title | Filter dashboards by the title of the author of the dashboard. | Text |
Warning: Please keep in mind that, due to the limitations of the underlying endpoint used to find user ids by role, the performance of the request while using user.role
filter might be degraded.
Deprecation notice: The format filter[filterName]=value which was previously supported for some filters, is now deprecated, in favor of filterName=value.
Pagination
Example request to load page 2 using 25 results per page
curl -X GET https://api.resourcewatch.org/v1/dashboard?page[number]=2&page[size]=25 \
-H "x-api-key: <your-api-key>"
The Dashboards service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your dashboards list.
Sorting
Sorting dashboards
curl -X GET https://api.resourcewatch.org/v1/dashboard?sort=name \
-H "x-api-key: <your-api-key>"
Sorting dashboards by multiple criteria
curl -X GET https://api.resourcewatch.org/v1/dashboard?sort=name,slug \
-H "x-api-key: <your-api-key>"
Explicit order of sorting
curl -X GET https://api.resourcewatch.org/v1/dashboard?sort=-name,+slug \
-H "x-api-key: <your-api-key>"
Sorting dashboards by the role of the user who owns the dashboard
curl -X GET https://api.resourcewatch.org/v1/dashboard?sort=user.role \
-H "x-api-key: <your-api-key>"
The Dashboards service currently supports sorting using the sort
query parameter. Sorting dashboards adheres to the conventions defined in the Sorting guidelines for the RW API, so we strongly recommend reading that section before proceeding. In addition to all dashboard model fields, you can sort the returned results by the name (using user.name
) or role (using user.role
) of the user owner of the dashboard. Keep in mind that sorting by user data is restricted to ADMIN users.
Please also keep in mind that, due to the limitations of the underlying endpoint used to find user ids by name or role, the performance of the request while using this sort might be degraded.
Include related entities
When loading dashboards, you can optionally pass an includes
query argument to load additional data.
User
Example request including the information for the user who owns the dashboard:
curl -X GET https://api.resourcewatch.org/v1/dashboard?includes=user \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "86",
"type": "dashboards",
"attributes": {
"name": "Test dashboard three",
"slug": "test-dashboard-three-cd4305e9-e3c8-456b-85a0-32eccb6100e6",
"summary": "test dashboard three summary",
"description": "test dashboard three description",
"content": "test dashboard three description",
"published": true,
"photo": {
"cover": "https://s3.amazonaws.com/image.jpg",
"thumb": "https://s3.amazonaws.com/image.jpg",
"original": "https://s3.amazonaws.com/image.jpg"
},
"user-id": "57ac9f9e29309063404573a2",
"private": true,
"env": "production",
"application": ["rw"],
"is-highlighted": false,
"is-featured": false,
"author-title": "",
"author-image": {
"cover": "/author_images/cover/missing.png",
"thumb": "/author_images/thumb/missing.png",
"original": "/author_images/original/missing.png"
},
"user": {
"name": "John Doe",
"role": "ADMIN",
"email": "john.doe@vizzuality.com"
}
}
}
]
}
Loads the name and email address of the owner of the dashboard. If you request this issue as an authenticated user with ADMIN role, you will additionally get the owner's role.
If the data is not available (for example, the user has since been deleted), no user
property will be added to the layer object.
Please keep in mind that, due to the limitations of the underlying endpoint used to find users by ids, the performance of the request while including user information might be degraded.
Getting a dashboard by its ID
How to get a dashboard by its ID:
curl -X GET https://api.resourcewatch.org/dashboard/24 \
-H "x-api-key: <your-api-key>"
Response:
{
"data": {
"id": "24",
"type": "dashboards",
"attributes": {
"name": "Cities",
"slug": "cities",
"summary": "Traditional models of city development can lock us into congestion, sprawl, and inefficient resource use. However, compact, connected, and efficient growth can help ensure more competitive cities, and provide a better quality of life for citizens. The decisions that national leaders, local officials, developers, and planners make today will determine how billions of urban cities will live over the next century. Already, half the global population resides in cities. That figure is set to increase to 70 percent by 2050.",
"description": "",
"content": "[]",
"published": false,
"photo": {
"cover": "https://s3.amazonaws.com/wri-api-backups/resourcewatch/staging/dashboards/photos/000/000/024/cover/data?1523301918",
"thumb": "https://s3.amazonaws.com/wri-api-backups/resourcewatch/staging/dashboards/photos/000/000/024/thumb/data?1523301918",
"original": "https://s3.amazonaws.com/wri-api-backups/resourcewatch/staging/dashboards/photos/000/000/024/original/data?1523301918"
},
"user-id": "58f63c81bd32c60206ed6b12",
"private": true,
"env": "production",
"user": null,
"is-highlighted": false,
"is-featured": false,
"author-title": "",
"author-image": {
"cover": "/author_images/cover/missing.png",
"thumb": "/author_images/thumb/missing.png",
"original": "/author_images/original/missing.png"
}
}
}
}
Creating a dashboard
Example request for creating a dashboard:
curl -X POST https://api.resourcewatch.org/v1/dashboard \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"data": {
"type": "dashboards",
"attributes": {
"name": "Cities",
"summary": "Traditional models of city development can lock us into ...",
"description": "",
"content": "[{...}]",
"published": false,
"photo": {
"cover": "...",
"thumb": "...",
"original": "..."
},
"private": true,
"env": "production",
"application": ["rw"],
"is-highlighted": false,
"is-featured": false,
"author-title": "",
"author-image": @file
}
}
}'
Example response:
{
"data": {
"id": "243",
"type": "dashboards",
"attributes": {
"name": "Cities",
"slug": "cities-94bbc472-8970-4d9e-a3f2-d5422b1011e0",
"summary": "Traditional models of city development can lock us into ...",
"description": "",
"content": "[{...}]",
"published": false,
"photo": {
"cover": "...",
"thumb": "...",
"original": "..."
},
"user-id": "eb63867922e16e34ef3ce862",
"private": true,
"env": "production",
"user": null,
"application": ["rw"],
"is-highlighted": false,
"is-featured": false,
"author-title": "",
"author-image": {
"cover": "...",
"thumb": "...",
"original": "..."
}
}
}
}
When creating a dashboard, the application
field should be present and cannot contain any values that are not associated with the creating user's account. If an application
value is not provided, ["rw"]
is used by default, and the process will fail if the user account does not belong to it. Additionally, keep in mind that this endpoint implements role-based access control in accordance with the RW API role-based access control guidelines.
Supported fields:
Name | Description | Accepted values |
---|---|---|
name | Short name for the dashboard | any valid text |
summary | Summary of the content of the dashboard | any valid text |
description | Description of the dashboard | any valid text |
content | Content of the dashboard, typically encoded as a JSON string | any valid text |
published | If the dashboard is in a publishable state | boolean |
photo | Object containing a set of image urls associated with the dashboard | object |
private | If the dashboard is private or publicly available. | boolean |
production | If the dashboard is available in the production environment. | boolean |
preproduction | If the dashboard is available in the preproduction environment. | boolean |
staging | If the dashboard is available in the staging environment. | boolean |
application | Application(s) to which the dashboard belongs. Defaults to ["rw"] . Read more about this field here. |
array of strings |
env | Environment to which the dashboard belongs. Read more about this field in the Environments concept section. | string |
is-highlighted | If this dashboard is highlighted (true /false ). Defaults to false . Only accessible to users with ADMIN role. |
boolean |
is-featured | If this dashboard is featured (true /false ). Defaults to false . Can only be set by user with ADMIN role. |
boolean |
author-title | The title of the author of the dashboard. | any valid text |
author-image | File for the image of the author of the dashboard. | valid image file (jpg, jpeg, png) |
Editing a dashboard
Example request for updating a dashboard:
curl -X PATCH https://api.resourcewatch.org/v1/dashboard/<id of the dashboard> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"data": {
"attributes": {
"description": "Dashboard that uses cities"
}
}
}'
Example response:
{
"data": {
"id": "243",
"type": "dashboards",
"attributes": {
"name": "Cities",
"slug": "cities-94bbc472-8970-4d9e-a3f2-d5422b1011e0",
"summary": "Traditional models of city development can lock us ...",
"description": "Dashboard that uses cities",
"content": "[{...}]",
"published": false,
"photo": {
"cover": "...",
"thumb": "...",
"original": "..."
},
"user-id": "eb63867922e16e34ef3ce862",
"private": true,
"env": "production",
"user": null,
"application": ["rw"],
"is-highlighted": false,
"is-featured": false,
"author-title": "",
"author-image": {
"cover": "...",
"thumb": "...",
"original": "..."
}
}
}
}
In order to perform this operation, the following conditions must be met:
- the user must comply with the RW API role-based access control guidelines.
- the user must be logged in and belong to the same application as the dashboard
When updating the application
field of a dashboard, a user cannot add values not associated with their user account.
Delete dashboard
Example request for deleting a dashboard:
curl -X DELETE https://api.resourcewatch.org/v1/dashboard/<id of the dashboard> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
In order to perform this operation, the following conditions must be met:
- the user must comply with the RW API role-based access control guidelines.
- the user must be logged in and belong to the same application as the dashboard
Clone dashboard
Example request for cloning a dashboard:
curl -X POST https://api.resourcewatch.org/v1/dashboard/<id>/clone \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"data": {
"attributes": {
"name": "Copy of Cities dashboard",
}
}
}'
Example response:
{
"data": {
"id": "224",
"type": "dashboards",
"attributes": {
"name": "Copy of Cities dashboard",
"slug": "cities-a9cb2c87-f6b6-48cf-9b52-9e0de4fd8d6f",
"summary": "Traditional models of city development can lock us into congestion, sprawl, and inefficient resource use. However, compact, ...",
"description": "",
"content": "[{\"id\":1511952250652,\"type\":\"widget\",\"content\":{\"widgetId\":\"b9186ce9-78ae-418b-a6d3-d521283ce485\",\"categories\":[]}},...}]",
"published": false,
"photo": {
"cover": "/system/dashboards/photos/data?1523301918",
"thumb": "/system/dashboards/photos/data?1523301918",
"original": "/system/dashboards/photos/data?1523301918"
},
"user-id": "1111167922e16e34ef3ce872",
"private": true,
"env": "production",
"application": ["rw"],
"is-highlighted": false,
"is-featured": false,
"author-title": "",
"author-image": {
"cover": "/author_images/cover/missing.png",
"thumb": "/author_images/thumb/missing.png",
"original": "/author_images/original/missing.png"
}
}
}
}
Clones an existing dashboard using its ID. If the original dashboard contains widgets, they will be duplicated and the new ids will be used by the new dashboard. Data can be provided in the body of the request in order to overwrite the data of the original dashboard. In the example on the side, the name
of the dashboard will be overwritten.
The following attributes can be overwritten by providing new values in the request body:
name
description
content
published
env
summary
photo
private
production
preproduction
staging
author-title
Static pages
Note: the documentation for these endpoints is not maintained and might not be up to date.
Tasks
What is a task?
In the context of this API, a task is a process in charge of performing certain actions on datasets of the document type. These actions can be creating a dataset or overwriting its content.
A task may contains the following fields:
Field | Description | Type |
---|---|---|
id | Id of the task | Text |
type | Task type - see full list here | Text |
message | Task message, which parametrizes the task | Object |
status | Status of the task - see full list here | Text |
reads | Number of data reads performed by the task | Number |
writes | Number of data writes performed by the task | Number |
index | Name of the Elasticsearch index used in this task | Text |
datasetId | Id of the dataset to which this task relates | Text |
logs | List of the individual operations carried out by this task | Array |
error | Error message generated should the task fail | Text |
createdAt | Date and time in which the task was created | DateTime |
updatedAt | Date and time in which the task was last updated | DateTime |
A task is fundamentally an internal element to the API, and it's visibility and interaction is limited to maintenance and debug actions. At its core, a task represents a single package that contains:
- An action to be carried out.
- A message that parametrises that action.
- A status that identifies the progress stage of the task.
- A dataset to which that action should relate.
- An Elasticsearch index identifier where the resulting data will be saved.
- Counters for read and write operations.
- Logs for those operations.
- An optional error field that identifies what happened in case of failure.
Get all tasks
To obtain all tasks:
curl -X GET https://api.resourcewatch.org/v1/doc-importer/task \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": [
{
"id": "55b02cfd-dabf-4ad0-a04d-5501cf248a0c",
"type": "task",
"attributes": {
"type": "TASK_CREATE",
"message": {
"id": "55b02cfd-dabf-4ad0-a04d-5501cf248a0c",
"type": "TASK_CREATE",
"datasetId": "65593fee-26e0-4c3c-84b3-cc0921bf8bc1",
"fileUrl": "http://gfw2-data.s3.amazonaws.com/country-pages/fire_alerts_all.csv",
"provider": "csv",
"legend": {
"date": [],
"region": [],
"country": [],
"nested": []
},
"verified": false,
"dataPath": "rows"
},
"status": "SAVED",
"reads": 973,
"writes": 973,
"createdAt": "2019-02-20T07:39:31.295Z",
"updatedAt": "2019-02-20T10:10:07.147Z",
"index": "index_65593fee26e04c3c84b3cc0921bf8bc1_1550648371365",
"datasetId": "65593fee-26e0-4c3c-84b3-cc0921bf8bc1",
"logs": [
{
"id": "a67f2557-9237-4435-82fd-3a0ad64b0292",
"type": "STATUS_INDEX_CREATED",
"taskId": "55b02cfd-dabf-4ad0-a04d-5501cf248a0c",
"index": "index_65593fee26e04c3c84b3cc0921bf8bc1_1550648371365"
},
{
"id": "53ac8e83-167b-4c77-9b61-6642b1764b32",
"type": "STATUS_READ_DATA",
"taskId": "55b02cfd-dabf-4ad0-a04d-5501cf248a0c"
}
]
}
},
{
"id": "415ecb4e-ed9a-4b0f-9f8b-7755775b08f5",
"type": "task",
"attributes": {
"type": "TASK_CREATE",
"message": {
"id": "415ecb4e-ed9a-4b0f-9f8b-7755775b08f5",
"type": "TASK_CREATE",
"datasetId": "638cce8c-3e97-4bdd-b4de-41cd28254370",
"fileUrl": "http://gfw2-data.s3.amazonaws.com/country-pages/fire_alerts_all.csv",
"provider": "csv",
"legend": {
"date": [],
"region": [],
"country": [],
"nested": []
},
"verified": false,
"dataPath": "rows"
},
"status": "SAVED",
"reads": 973,
"writes": 973,
"createdAt": "2019-02-20T07:39:36.421Z",
"updatedAt": "2019-02-20T10:10:09.175Z",
"index": "index_638cce8c3e974bddb4de41cd28254370_1550652900017",
"datasetId": "638cce8c-3e97-4bdd-b4de-41cd28254370",
"logs": [
{
"id": "8f5b6b0c-9132-4b5c-b7c4-b58582b3cb0b",
"type": "STATUS_INDEX_CREATED",
"taskId": "415ecb4e-ed9a-4b0f-9f8b-7755775b08f5",
"index": "index_638cce8c3e974bddb4de41cd28254370_1550652900017"
},
{
"id": "63c69b2b-31cd-4bdb-9794-f6d4ec155e7b",
"type": "STATUS_READ_DATA",
"taskId": "415ecb4e-ed9a-4b0f-9f8b-7755775b08f5"
}
]
}
}
],
"links": {
"self": "https://api.resourcewatch.org/v1/doc-importer/task?page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/v1/doc-importer/task?page[number]=1&page[size]=10",
"last": "https://api.resourcewatch.org/v1/doc-importer/task?page[number]=23&page[size]=10",
"prev": "https://api.resourcewatch.org/v1/doc-importer/task?page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/v1/doc-importer/task?page[number]=2&page[size]=10"
},
"meta": {
"total-pages": 23,
"total-items": 227,
"size": 10
}
}
Pagination
Example request to load page 2 using 25 results per page
curl -X GET https://api.resourcewatch.org/v1/doc-importer/task?page[number]=2&page[size]=25 \
-H "x-api-key: <your-api-key>"
The Tasks service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your tasks list.
Filter params
Available filters:
Field | Description | Type |
---|---|---|
type | Task type | Text |
status | Task status | Text |
datasetID | Id of the dataset to which the task refers | Text |
createdAt | Tasks created on the given date | Date |
updatedAt | Tasks last updated on the given date | Date |
createdBefore | Tasks created before the given date | Date |
createdAfter | Tasks created after the given date | Date |
updatedBefore | Tasks last updated before the given date | Date |
updatedAfter | Tasks last updated after the given date | Date |
Return tasks with type TASK_OVERWRITE
curl -X GET https://api.resourcewatch.org/v1/doc-importer/task?type=TASK_OVERWRITE \
-H "x-api-key: <your-api-key>"
Return the tasks with status SAVED
curl -X GET https://api.resourcewatch.org/v1/doc-importer/task?status=SAVED \
-H "x-api-key: <your-api-key>"
Return the tasks created on Feb 1st 2019
curl -X GET https://api.resourcewatch.org/v1/doc-importer/task?createdAt=2019-02-01 \
-H "x-api-key: <your-api-key>"
Return the tasks last updated between Jan 2nd and Feb 2nd 2019
curl -X GET https://api.resourcewatch.org/v1/doc-importer/task?updatedAfter=2019-01-02&updatedBefore=2019-02-02 \
-H "x-api-key: <your-api-key>"
Return the tasks last updated before and Feb 2nd 2019 and with status ERROR
curl -X GET https://api.resourcewatch.org/v1/doc-importer/task?updatedBefore=2019-02-02&status=ERROR \
-H "x-api-key: <your-api-key>"
Get a single task
To obtain the task:
curl -X GET https://api.resourcewatch.org/v1/doc-importer/task/55b02cfd-dabf-4ad0-a04d-5501cf248a0c \
-H "x-api-key: <your-api-key>"
Example response:
{
"data": {
"id": "55b02cfd-dabf-4ad0-a04d-5501cf248a0c",
"type": "task",
"attributes": {
"type": "TASK_CREATE",
"message": {
"id": "55b02cfd-dabf-4ad0-a04d-5501cf248a0c",
"type": "TASK_CREATE",
"datasetId": "65593fee-26e0-4c3c-84b3-cc0921bf8bc1",
"fileUrl": "http://gfw2-data.s3.amazonaws.com/country-pages/fire_alerts_all.csv",
"provider": "csv",
"legend": {
"date": [],
"region": [],
"country": [],
"nested": []
},
"verified": false,
"dataPath": "rows"
},
"status": "SAVED",
"reads": 973,
"writes": 973,
"createdAt": "2019-02-20T07:39:31.295Z",
"updatedAt": "2019-02-20T10:10:07.147Z",
"index": "index_65593fee26e04c3c84b3cc0921bf8bc1_1550648371365",
"datasetId": "65593fee-26e0-4c3c-84b3-cc0921bf8bc1",
"logs": [
{
"id": "a67f2557-9237-4435-82fd-3a0ad64b0292",
"type": "STATUS_INDEX_CREATED",
"taskId": "55b02cfd-dabf-4ad0-a04d-5501cf248a0c",
"index": "index_65593fee26e04c3c84b3cc0921bf8bc1_1550648371365"
},
{
"id": "53ac8e83-167b-4c77-9b61-6642b1764b32",
"type": "STATUS_READ_DATA",
"taskId": "55b02cfd-dabf-4ad0-a04d-5501cf248a0c"
}
]
}
}
}
Delete a task
You can delete a task if, for example, it is stuck on a running state, but it's not actually running. This should be considered a "only do it if you know what you are doing" operation, and requires ADMIN permission.
curl -X DELETE https://api.resourcewatch.org/v1/doc-importer/task/<task_id> \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json"
Salesforce integration
This service allows easy communication of RW API user data to Salesforce for convenient CRM purposes.
Searching for user details
Searches for users by email address
curl -X GET https://api.resourcewatch.org/v1/salesforce/contact/search?email=user@email.com \
-H "x-api-key: <your-api-key>"
Response:
{
"data": [
{
"Id": "0123456789abcdef",
"FirstName": "Test",
"LastName": "User",
"Email": "user@email.com",
"Personal_Email__c": "user@email.com",
"Work_Email__c": "user@email.com",
"Alternate_Email__c": null
}
]
}
Returns the details associated with users matching the provided search criteria. If more than one user matches the search criteria, only the first one (as sorted by Salesforce) is returned - this is likely to change in the future.
Filters
Parameter | Description | Type |
---|---|---|
Email address of the user | Text |
Currently, only filtering by email
is supported. It is also required.
Errors for searching for user details
Error code | Error message | Description |
---|---|---|
400 | "email" is required | The required email query parameter is missing in the request. |
Logging user data update
curl -X POST https://api.resourcewatch.org/v1/salesforce/contact/log-action \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"email": "user@email.com",
"firstName": "John",
"lastName": "Doe"
}'
Logs a change to a user's details. The user to update is identified by its email address, which is a required body parameter. If more than one user account matches the provided email address, the first one (as sorted by Salesforce) is used.
Changes logged using this endpoint are not applied synchronously, so they may not be reflected immediately on data loaded through other endpoints.
A successful user data update logging returns an empty HTTP 201 response.
Logging user data update parameters
Parameter | Type | Required |
---|---|---|
Text | Yes | |
countryOfInterest | Text | No |
firstName | Text | No |
lastName | Text | No |
primaryRole | Text | No |
primaryRoleOther | Text | No |
sector | Text | No |
areaOrRegionOfInterest | Text | No |
title | Text | No |
organizationName | Text | No |
topicsOfInterest | Text | No |
userCity | Text | No |
userState | Text | No |
userCountry | Text | No |
howDoYouUseGFW | Text | No |
howDoYouUseGFWOther | Text | No |
signUpForTesting | Text | No |
sourceOfContactCreation | Text | No |
Errors for logging user data update
Error code | Error message | Description |
---|---|---|
400 | "email" is required | The required email body parameter is missing in the request. |
400 | "<field name>" is an invalid field | The provided field name is not supported as a body parameter. |
User management
The following endpoints expose the RW API's functionality regarding user management. These endpoints will allow you to login, recover a forgotten password, create, edit or delete a user account. We've already covered the basics of getting a user account in the quickstart guide section, and here we'll dive deeper into all the functionality exposed by these endpoints.
These endpoints have a key difference from most of the endpoint covered so far. The great majority of the RW API endpoints are meant to be used by your applications, and as such produce JSON responses, which are easily interpreted by computers. However, some of the functionality we'll cover in this section is meant to be used only or also by humans, making JSON a less than ideal response format.
Some (but not all) of the endpoints documented here will produce a response in either JSON or HTML format, depending on
the value you provide on the Content-type
HTTP request header.
Use Content-Type: application/json
if you are calling the endpoint from an application, and would like to get a JSON
formatted response.
If you are accessing these endpoints from a browser, it will typically generate a request with
the Content-Type: text/html
header, in which case the reply will be in HTML format.
Keep in mind that not all endpoints support both formats, and will output either HTML or JSON, no matter
which Content-Type
value you provide.
General notes on RW API users
User accounts in the RW API work pretty much like you would expect: you create a user account, login with it, and use it on your day-to-day interactions to access certain actions and associate certain RW API resources with it.
Besides authentication, user accounts are also used for authorization. Authorization is implemented on a per-service basis, but is commonly built on top of 3 elements associated with your a user account:
id
role
application
id
is a unique identifier of your account. Certain actions may be limited to specific users, typically in the context
of a given resource being associated directly with a specific user id
.
role
can be one of 3 values: USER
, MANAGER
and ADMIN
and it is usually used for role-based access control - read
more about this field in the User roles concept documentation.
application
is a list of keys meant to identify the different client applications that are built using the RW API.
It's present not only on user accounts, but also on many of the resources found on the RW API, either as a single value
or as a list of values. Typically, in order to manipulate a given resource, that resource and the user account must have
at least one overlapping application
value. You can find out more about how the application
field
works here.
Keep in mind that it's up to each individual RW API service (dataset, widget, layer, etc) to define how they restrict or allow actions based on these or other factors, so the examples above may not be true for all cases. Refer to the documentation of each resource and endpoint for more details on restrictions they may have regarding user accounts and their properties.
Deprecation notice: Throughout these endpoints, you'll notice that many API responses contain both id
and _id
(
with and without an underscore prefix). Whenever both are present, they will always have the same value, and you should
rely on id
(no prefix) - _id
is present for BC reasons, but should be considered deprecated, and will be removed in
the near future.
User management and applications
As we've covered in previous sections, several RW API resources, like users, datasets or widgets, are associated with one or more applications. Applications are a way to identify the different tools that rely on the RW API, and are used to make resource management easier.
The user management service can also models its behavior based on the application that's making use of it - this can be
controlled by the origin
query parameter. This parameter can be passed on every request, or on the first request only,
if you are relying on cookie-based sessions. In it, you can identify the application using the RW API. If it's a known
application, certain elements will be adjusted:
- Logo and color scheme on HTML pages and emails.
- Fallback redirects on login.
- Available 3rd party authentication mechanisms and associated accounts on those platforms.
If you use an origin
application that's not known to the RW API, you will see a fallback configuration of these
elements, and 3rd party login will be disabled. If you'd like your application to be supported,
please contact us - we'd love to hear about how the RW API can help your
projects.
Login (email + password)
Login endpoints support both HTML and JSON output formats, depending on the Content-type
provided in the request. Keep
in mind that HTML-based requests will result in redirects - for example, after successfully logging in, you will be
taken to /auth/success
- while JSON based requests will simply return the matching HTTP code - 200 in case of a
successful login.
GET <BASE API URL>/auth/
Convenience URL that redirects to <BASE API URL>/auth/login
- the HTML login page.
GET <BASE API URL>/auth/login
HTML page that displays the login, registration and password reset links. This is the most common entry point when using the HTML UI provided by the RW API for user management.
POST <BASE API URL>/auth/login
Email + password based login - JSON format
curl -X POST "https://api.resourcewatch.org/auth/login" \
-H "Content-Type: application/json" -d \
'{
"email":"your-email@provider.com",
"password":"potato"
}'
Response:
{
"data": {
"id": "5bfd237767b3176dd63f2eb7",
"_id": "5bfd237767b3176dd63f2eb7",
"email": "your-email@provider.com",
"createdAt": "2018-11-15T04:46:35.313Z",
"updatedAt": "2018-11-15T04:46:35.313Z",
"role": "USER",
"provider": "local",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": [
"rw"
]
},
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjViZWNmYTJiNjdkYTBkM2VjMDdhMjdmNiIsInJvbGUiOiJVU0VSIiwicHJvdmlkZXIiOiJsb2NhbCIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImV4dHJhVXNlckRhdGEiOnsiYXBwcyI6WyJydyJdfSwiY3JlYXRlZEF0IjoxNTQzMzE1NzMxNzcwLCJpYXQiOjE1NDMzMTU3MzF9.kIdkSOb7mCMOxE2ipqVOBrK7IefAjLDhaPG9DT1qvCw"
}
}
Endpoint for email + password based login.
For HTML requests, it will redirect to either <BASE API URL>/auth/success
or <BASE API URL>/auth/fail
depending on
whether the login was successful or not. If successful, the HTTP reply will have a session cookie that may be used in
subsequent requests. An optional callbackUrl
query parameter can be provided, in which case the user will be
redirected to that URL in case of login success.
For JSON requests, in case of successful logins, the user details will be returned as a JSON object.
Errors for logging in
Error code | Error message | Description |
---|---|---|
401 | Invalid email or password. | Login credentials are missing or incorrect. |
GET <BASE API URL>/auth/fail
Displays login errors for HTML requests. Not supported on JSON requests.
GET <BASE API URL>/auth/check-logged
Check if the user is logged
curl -X GET "https://api.resourcewatch.org/auth/check-logged" \
-H 'Cookie: <your cookie values>'
Response
{
"id": "5bfd237767b3176dd63f2eb7",
"_id": "5bfd237767b3176dd63f2eb7",
"email": "your-email@provider.com",
"createdAt": "2018-11-27T10:59:03.531Z",
"updatedAt": "2018-11-27T10:59:03.531Z",
"role": "USER",
"provider": "local",
"extraUserData": {
"apps": [
"rw"
]
}
}
Checks if you are logged in. This is typically used to determine if a session has been established between the the user's browser and the RW API.
Errors for checking if the user is logged
Error code | Error message | Description |
---|---|---|
401 | Not authenticated. | You are not logged in. |
GET <BASE API URL>/auth/success
Successful login page for HTML requests. Not supported on JSON requests.
GET <BASE API URL>/auth/logout
Login invalidation endpoint. Only invalidates the session cookie set on login. If using JSON Web Token based authentication, this endpoint will NOT invalidate the token.
GET <BASE API URL>/auth/generate-token
Generate the user's JSON Web Token
curl -X GET "https://api.resourcewatch.org/auth/generate-token" \
-H 'Cookie: <your cookie values>'
Response:
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjViZWNmYTJiNjdkYTBkM2VjMDdhMjdmNiIsInJvbGUiOiJVU0VSIiwicHJvdmlkZXIiOiJsb2NhbCIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImV4dHJhVXNlckRhdGEiOnsiYXBwcyI6WyJydyJdfSwiY3JlYXRlZEF0IjoxNTQzMzE1NzMxNzcwLCJpYXQiOjE1NDMzMTU3MzF9.kIdkSOb7mCMOxE2ipqVOBrK7IefAjLDhaPG9DT1qvCw"
}
Generates a JSON Web Token for the current user session. This is useful when using the HTML UI through a browser, where a session is established using a cookie returned on login. This cookie authenticates the user, and allows retrieving the token.
Errors for generating a new token
Error code | Error message | Description |
---|---|---|
401 | Not authenticated. | You are not logged in. |
Login (3rd party oauth)
Besides its own email + password login mechanism, that you can interact with and build your own UI on top of, the RW API also provides authentication using 3rd party accounts, like Facebook, Apple or Google. These 4 authentication mechanisms use OAuth access delegation, meaning users can use their accounts on these platforms to access the RW API. For each mechanism, users will be informed, when logging in, which data the RW API requires to provide this access.
For each provider, there's a corresponding endpoint that starts the authentication flow. These endpoints simply redirect the user to the respective provider page, along with some data that allows the provider to contact the RW API when the login process is finished. You can forward users to these endpoints if, for example, you want to have your own login links on your UI.
Keep in mind that, depending on the origin
application you specify, different Facebook, Google or Apple applications
will be used. Also, not all origin
applications support all 3 providers.
3rd party authentication using Google
- GET
<BASE API URL>/auth/google
- Starts authentication using the configured Google settings - GET
<BASE API URL>/auth/google/token?access_token=<Google token>
- Endpoint that expects the Google token used by the API to validate the user session.
Note: For the access token based login with Google, you should make sure to request
the https://www.googleapis.com/auth/userinfo.email
scope. This scope will make sure that the RW API can find the user
email address in the payload returned by Google validating the access token. If the email is present in the payload
returned by Google, it will be used to login the RW API account. If not, the RW API will use "fake email", composed
using Google's unique user identifier, as the email address for the RW API account to log in.
3rd party authentication using Facebook
- GET
<BASE API URL>/auth/facebook
- Starts authentication using the configured Facebook settings - GET
<BASE API URL>/auth/facebook/token?access_token=<Facebook token>
- Endpoint that expects the Facebook token used by the API to validate the user session.
Note: For the access token based login with Facebook, you should make sure to request the email
scope. This scope
will make sure that the RW API can find the user email address in the payload returned by Facebook validating the access
token. If the email is present in the payload returned by Facebook, it will be used to login the RW API account. If not,
the RW API will use "fake email", composed using Facebook's unique user identifier, as the email address for the RW API
account to log in.
3rd party authentication using Apple
- GET
<BASE API URL>/auth/apple
- Starts authentication using the configured Apple settings - GET
<BASE API URL>/auth/apple/token?access_token=<Apple JSON Web Token>
- Endpoint that expects the Apple JSON Web Token obtained by the user while authenticating using another application. It validates that token using Apple's services, and if valid, creates/updates the user's RW API account. It returns a RW API JSON Web Token.
Common authorization callback
All forms of 3rd party login return to the same endpoint:
- POST
<BASE API URL>/auth/authorization-code/callback
Registration
Registration endpoints support both HTML and JSON output formats, depending on the Content-type
provided in the
request.
View the registration page
curl -X GET "https://api.resourcewatch.org/auth/sign-up"
Account creation page, for accounts using email-based login for HTML requests. Not supported on JSON requests.
Register a new user account
Account creation using email
curl -X POST "https://api.resourcewatch.org/auth/sign-up" \
-H "Content-Type: application/json" -d \
'{
"name: "Your name"
"email":"your-email@provider.com",
"apps": ["rw"]
}'
Response
{
"data": {
"id": "5bfd237767b3176dd63f2eb7",
"name": "Your name",
"email": "your-email@provider.com",
"createdAt": "2018-11-27T10:59:03.531Z",
"organizations": [],
"applications": [],
"role": "USER",
"extraUserData": {
"apps": [
"rw"
]
}
}
}
Account creation using email with a user defined origin app
curl -X POST "https://api.resourcewatch.org/auth/sign-up?origin=rw" \
-H "Content-Type: application/json" -d \
'{
"name: "Your name"
"email":"your-email@provider.com",
"apps": ["rw"]
}'
Account creation endpoint, for accounts using email-based login for both HTML and JSON requests. The email
must be
unique, otherwise a 422 HTTP response will be returned.
For HTML requests, it will display a message informing about any validation error, or informing the user in case of success.
For JSON requests, successful logins will return a JSON object containing the details of the user.
Keep in mind that this endpoint creates a deactivated user account. A successful call to this endpoint send an email to the user, with a link that the user must click in order to confirm their account and define their password. Once confirmed using this process, the user account becomes activated and fully functional, and the user will be able to log in.
While optional, it's highly recommended that you specify which apps the user will be granted access to, as most API
operation validate the user's apps match datasets, widgets, etc. All accounts created this way will have the USER
role.
This endpoint also supports receiving a callbackUrl
parameter (this can either be provided as query parameter or as
part of the request body). This field contains the URL where the user will be redirected to after confirming their
account. If not provided, it will default to the value of the HTTP Referrer
header of the sign-up request.
Errors for registering a new user account
Error code | Error message | Description |
---|---|---|
422 | Email exists. | An account already exists for the provided email address. |
422 | Email is required. | You are missing one of the required fields. |
Password recovery
Password recovery endpoints support both HTML and JSON output formats, depending on the Content-type
provided in the
request. These can be used either as part of your application (for example, if you want your UI to have these features
built in) or as a standalone, end user facing interface (for applications that prefer to rely on the existing UI
elements provided by the RW API).
GET <BASE API URL>/auth/reset-password
Displays the password reset form HTML page.
POST <BASE API URL>/auth/reset-password
Request a password reset
curl -X POST "https://api.resourcewatch.org/auth/reset-password" \
-H "Content-Type: application/json" -d \
'{
"email":"your-email@provider.com"
}'
Response (JSON)
{
"message": "Email sent"
}
Endpoint where the password reset request is sent. If an account associated with the provided email address exists, a message will be sent to it with a link that will allow the user to reset their account's password. That link will be valid for 24 hours.
Note that, for security reasons, if no account associated with the provided email address exists, the output will be the same.
This endpoint supports receiving a callbackUrl
parameter (this can either be provided as query parameter or as part of
the request body). This field contains the URL where the user will be redirected to after resetting their password. If
not provided, it will default to the value of the HTTP Referrer
header of the sign-up request.
Errors for requesting a password reset
Error code | Error message | Description |
---|---|---|
422 | Mail required. | You need to specify the email address in the request body. |
400 | Password recovery not allowed. Your email address is already associated with an account that uses a 3rd party login (Google/Facebook/Apple) | You are requesting a password request for an email address already associated with an existing user account, and said account was created using one of the available 3rd party social logins. You should log in using that social login provider (for security reasons, the RW API does not disclose which social login provider is associated with this email address). |
User details management
This section covers endpoints that focus on retrieving, modifying or deleting user accounts. Unlike previous endpoints, these are meant to be consumed by applications, and will always produce a JSON response.
Getting all users
Lists all currently active users belonging to the same apps as the requester
curl -X GET "https://api.resourcewatch.org/auth/user"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Response:
{
"data": [
{
"id": "5d2fadb3adf1dc74d2ad05dfb",
"_id": "5d2fadb3adf1dc74d2ad05dfb",
"email": "john.doe@vizzuality.com",
"provider": "local",
"createdAt": "2019-10-31T13:00:58.191Z",
"updatedAt": "2019-10-31T13:00:58.191Z",
"role": "USER",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": []
}
},
{
...
}
],
"links": {
"self": "https://api.resourcewatch.org/auth/user?page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/auth/user?page[number]=1&page[size]=10",
"prev": "https://api.resourcewatch.org/auth/user?page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/auth/user?page[number]=1&page[size]=10"
}
}
This endpoint allows users with ADMIN
role to list and filter existing user accounts. Through this endpoint, only 3rd
party-based and confirmed email-based user accounts are listed - user accounts that have not been confirmed will not be
listed. It's also important to keep in mind that, by default, only users belonging to the same apps as the requesting
user will be shown - you can use filters to modify this behavior.
Errors for getting all users
Error code | Error message | Description |
---|---|---|
401 | Not authenticated. | You need to be logged in to use this endpoint. |
Pagination
Example request using the "cursor" strategy:
curl -X GET "https://api.resourcewatch.org/auth/user?strategy=cursor"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Example request using the "offset" strategy:
curl -X GET "https://api.resourcewatch.org/auth/user?strategy=offset"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Currently, this endpoint supports 2 pagination strategies: "cursor" and "offset". Both strategies are available
via the "strategy" query parameter: strategy=offset
to use the "offset" strategy, and strategy=cursor
to use the "
cursor" strategy;
Until May 1st 2021, if nothing is provided, the default strategy used will be "offset". After May 1st, the "offset"
strategy will be officially deprecated, and the "cursor" strategy will become the default. During this period, the "
offset" strategy will still be accessible by passing the strategy=offset
parameter in the request.
After September 30th 2021, the "offset" strategy will be officially deprecated. Passing the strategy=offset
parameter will no longer be supported, and the "cursor" strategy will remain the default going forward.
If you are here for the first time, you should use the "cursor" strategy.
Pagination using cursor strategy
Example request to the first page with "cursor" strategy:
curl -X GET "https://api.resourcewatch.org/auth/user?strategy=cursor"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Example response, including the "links" object in the response body:
{
"data": [
{
"id": "57bc261af098ce980079873e",
"_id": "57bc261af098ce980079873e",
"email": "your@email.com",
"name": "",
"createdAt": "2021-03-24T09:19:25.000Z",
"updatedAt": "2021-03-26T09:54:08.000Z",
"role": "USER",
"provider": "local",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": [
"gfw"
]
}
},
{
...
},
{
...
},
{
...
},
{
...
},
{
...
},
{
...
},
{
...
},
{
...
},
{
...
}
],
"links": {
"self": "https://api.resourcewatch.org/auth/user?strategy=cursor&page[before]=00ucw0wd1cUIGDMed5d6&page[size]=10",
"first": "https://api.resourcewatch.org/auth/user?strategy=cursor&page[size]=10",
"next": "https://api.resourcewatch.org/auth/user?strategy=cursor&page[after]=00ucw0wd1cUIGDMed5d6&page[size]=10"
}
}
Example request to the page after the cursor provided with "cursor" strategy:
curl -X GET "https://api.resourcewatch.org/auth/user?strategy=cursor&page[after]=00ucw0wd1cUIGDMed5d6"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Cursor-based pagination works by returning a slice of results, and a pointer to the end of the slice returned. On
subsequent requests, you can then use the cursor to request the next slice of results after (or before) the cursor
provided. Cursor-paginated methods accept limiting the amount of returned results through the page[size]
query
parameter - defaults to 10, with a maximum supported value of 200 -, and control of the slice returned through
the page[after]
and page[before]
query parameters.
By default, if you don't pass a page[after]
or page[before]
parameter, you'll receive the first portion of results.
Paginated responses include a top-level links
object in the response body, that includes the link you should use to
fetch the previous or next page of data.
If the slice of data you received is smaller than the page[size]
provided (or 10, the default value), that indicates
no further results.
Please keep in mind that, until May 1st 2021, you need to provide strategy=cursor
to use this pagination strategy.
Pagination using offset strategy
DEPRECATED: Example request to load page 2 using 25 results per page using the "offset" strategy:
curl -X GET "https://api.resourcewatch.org/auth/user?strategy=offset&page[number]=2&page[size]=25"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Until September 30th 2021, like with many other resources across the RW API, you can also paginate results with a
strategy based on page number (page[number]
)
and page size (page[size]
).
You can read more about this pagination strategy in the Pagination guidelines for the RW API. Please keep in mind that:
- from May 1st 2021 onwards, you need to provide
strategy=offset
to use this pagination strategy; - from September 30th 2021 onwards, this strategy is officially deprecated and will be removed.
Also, due to the inner workings of the underlying system used by the RW API for user management, the higher the page number is, the longer the response will take to be returned. This is the principal reason we are deprecating this strategy, and a very valid reason why you should avoid using this strategy altogether.
Filters
List users with the ADMIN role (and associated with the current user's app)
curl -X GET "https://api.resourcewatch.org/auth/user?role=ADMIN"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
List users with the ADMIN role and associated with either
gfw
orrw
apps
curl -X GET "https://api.resourcewatch.org/auth/user?role=ADMIN&app=gfw,rw"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Response:
{
"data": [
{
"id": "5d2fadb3adf1dc74d2ad05dfb",
"_id": "5d2fadb3adf1dc74d2ad05dfb",
"provider": "local",
"email": "john.doe@vizzuality.com",
"createdAt": "2019-10-31T13:00:58.191Z",
"updatedAt": "2019-10-31T13:00:58.191Z",
"role": "ADMIN",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": [
"rw"
]
}
},
{
...
}
],
"links": {
"self": "https://api.resourcewatch.org/auth/user?page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/auth/user?page[number]=1&page[size]=10",
"last": "https://api.resourcewatch.org/auth/user?page[number]=1&page[size]=10",
"prev": "https://api.resourcewatch.org/auth/user?page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/auth/user?page[number]=1&page[size]=10"
},
"meta": {
"total-pages": 1,
"total-items": 3,
"size": 10
}
}
The users list provides a set of parameters that you can use to tailor your users listing. Please note that filtering users adheres to the conventions defined in the Filter guidelines for the RW API, so we strongly recommend reading that section before proceeding. in addition to these conventions, you can use the following fields as filters supported by the users list endpoint:
Filter | Description | Type | Expected values |
---|---|---|---|
name | Filter returned users by their name. | String | any valid text |
Filter returned users by their email address. Keep in mind that user accounts that rely on 3rd party authentication mechanisms may not have an email address. | String | any valid text | |
provider | Filter returned users by their provider. | String | local , google , twitter , facebook or apple |
role | Filter returned users by their role. | String | USER , MANAGER or ADMIN |
app | Filter returned users by their app. Multiple values can be passed, separated by commas, in which case any user associated with at least one of the applications will be returned. Pass all to show users for all apps. |
String | any valid text |
Get the current user
Shows info for user currently logged in
curl -X GET "https://api.resourcewatch.org/auth/user/me"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Response
{
"provider": "local",
"role": "ADMIN",
"_id": "5dbadb0adf24534d1ad05dfb",
"id": "5dbadb0adf24534d1ad05dfb",
"email": "test.user@example.com",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": [
"rw",
"gfw"
]
},
"createdAt": "2019-10-31T13:00:58.191Z",
"updatedAt": "2019-10-31T13:00:58.191Z"
}
This endpoint allows you to get the details of the user account associated with the current token. It's available to all authenticated users.
Errors for getting the current user
Error code | Error message | Description |
---|---|---|
401 | Not authenticated. | You need to be logged in to use this endpoint. |
Get a user by id
Shows info for user with the given id
curl -X GET "https://api.resourcewatch.org/auth/user/<user_id>"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Response
{
"provider": "local",
"role": "ADMIN",
"_id": "5dbadb0adf24534d1ad05dfb",
"id": "5dbadb0adf24534d1ad05dfb",
"email": "test.user@example.com",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": [
"rw",
"gfw"
]
},
"createdAt": "2019-10-31T13:00:58.191Z",
"updatedAt": "2019-10-31T13:00:58.191Z"
}
This endpoint allows you to get the details of the user account associated with the current token. It's available to
users with role ADMIN
.
Errors for getting a user by id
Error code | Error message | Description |
---|---|---|
401 | Not authenticated. | You need to be logged in to use this endpoint. |
403 | Not authorized. | You need to have the ADMIN role to use this endpoint. |
Create a user account
curl -X POST "https://api.resourcewatch.org/auth/user"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>" \
'{
"name":"new-name",
"email":"test@example.com",
"photo": "https://photo-url.com",
"extraUserData" : {
apps: ["rw", "gfw"]
},
"role": "MANAGER"
}'
Response:
{
"data": {
"id": "57bc2611f098ce9800798688",
"_id": "57bc2611f098ce9800798688",
"provider": "local",
"email": "test@example.com",
"name": "new-name",
"photo": "https://photo-url.com",
"createdAt": "2017-01-13T10:45:46.368Z",
"updatedAt": "2017-01-13T10:45:46.368Z",
"role": "MANAGER",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": [
"rw",
"gfw"
]
}
}
}
This endpoints allows existing users to create a new user account. It's available to any logged in user who have either
ADMIN
or MANAGER
roles, and supports providing the following fields:
name
photo
extraUserData.apps
(only allowed for users withADMIN
role)role
(only allowed for users withADMIN
role)organizations
: a list of objects, containing theid
of the organization the user will be associated with, and therole
it will have in said organizationapplications
: a list of applicationid
the user will own.
The response will contain the user details, reflecting the applied changes.
It's worth keeping in mind that applications can either belong to a single user or a single organization, so by updating
an user with applications
associated with it, you may be removing associations between the
provided applications
and other users/organizations.
Errors for creating user account details
Error code | Error message | Description |
---|---|---|
400 | Email exists. | An user account with the provided email address already exists. |
400 | Apps required. | You must provide at least one extraUserData.apps value. |
400 | "organizations[0].role" must be [ORG_MEMBER] | When creating a new user and associating it with an organization, you can only use the ORG_MEMBER organization role. |
401 | Not authenticated. | You need to be logged in to use this endpoint. |
403 | Forbidden. | You can only assign the new user extraUserData.apps values that your own user account has. |
403 | You don't have permissions to associate this/these organization(s) | You can only associate the new user with organizations if you have the ADMIN role or are the organization admin |
Update your user account details
Updates current user details
curl -X PATCH "https://api.resourcewatch.org/auth/user/me"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>" \
'{
"name":"new-name",
"photo": "https://photo-url.com",
"extraUserData" : {
apps: ["rw", "gfw"]
},
"role": "MANAGER"
}'
Response:
{
"data": {
"id": "57bc2611f098ce9800798688",
"_id": "57bc2611f098ce9800798688",
"provider": "local",
"email": "test@example.com",
"name": "new-name",
"photo": "https://photo-url.com",
"createdAt": "2017-01-13T10:45:46.368Z",
"updatedAt": "2017-01-13T10:45:46.368Z",
"role": "MANAGER",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": [
"rw",
"gfw"
]
}
}
}
This endpoints allows updating your user account details. It's available to any logged in user, allowing them to modify the following fields:
name
photo
extraUserData.apps
(only allowed for users withADMIN
role)role
(only allowed for users withADMIN
role)organizations
: a list of objects, containing theid
of the organization the user will be associated with, and therole
it will have in said organizationapplications
: a list of applicationid
the user will own.
The response will contain the user details, reflecting the applied changes.
It's worth keeping in mind that applications can either belong to a single user or a single organization, so by updating
an user with applications
associated with it, you may be removing associations between the
provided applications
and other users/organizations.
Errors for updating your user account details
Error code | Error message | Description |
---|---|---|
401 | Not authenticated. | You need to be logged in to use this endpoint. |
400 | "organizations[0].role" must be [ORG_MEMBER] | When updating your user and associating it with an organization, you can only use the ORG_MEMBER organization role. |
403 | You don't have permissions to associate application |
You are trying to create or modify an association between a user and an application for which you don't have permission. |
Update another user's account details
Updates details of user given its id
curl -X PATCH "https://api.resourcewatch.org/auth/user/57bc2611f098ce9800798688"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>" \
'{
"name":"new-name",
"photo": "https://photo-url.com",
"extraUserData" : {
apps: ["rw", "gfw"]
},
"role": "MANAGER"
}'
Response:
{
"data": {
"id": "57bc2611f098ce9800798688",
"_id": "57bc2611f098ce9800798688",
"provider": "local",
"email": "test@example.com",
"name": "new-name",
"photo": "https://photo-url.com",
"createdAt": "2017-01-13T10:45:46.368Z",
"updatedAt": "2017-01-13T10:45:46.368Z",
"role": "MANAGER",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": [
"rw",
"gfw"
]
}
}
}
This endpoints allows updating the user account details of another user. It's available to users with the ADMIN
role,
allowing them to modify the following fields:
name
photo
extraUserData.apps
role
organizations
: a list of objects, containing theid
of the organization the user will be associated with, and therole
it will have in said organizationapplications
: a list of applicationid
the user will own.
The response will contain the user details, reflecting the applied changes.
It's worth keeping in mind that applications can either belong to a single user or a single organization, so by updating
an user with applications
associated with it, you may be removing associations between the
provided applications
and other users/organizations.
Errors for updating another user's account details
Error code | Error message | Description |
---|---|---|
400 | "organizations[0].role" must be [ORG_MEMBER] | When updating another user and associating it with an organization, you can only use the ORG_MEMBER organization role. |
401 | Not authenticated. | You need to be logged in to use this endpoint. |
403 | Not authorized. | You need to have the ADMIN role to use this endpoint. |
Getting all resources for a user id
Get all resource for a user by its id
curl -L "https://api.resourcewatch.org/auth/user/<user_id>/resources"
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>"
Response
{
"datasets": {
"data": [],
"count": 0
},
"layers": {
"data": [],
"count": 0
},
"widgets": {
"data": [],
"count": 0
},
"userAccount": {
"data": {
"id": "<user_id>",
"_id": "<user_id>",
"email": "john.doe@sample.com",
"provider": "local",
"role": "USER",
"extraUserData": {
"apps": [
"gfw"
]
},
"createdAt": "2023-03-10T23:05:41.000Z",
"updatedAt": "2023-03-10T23:08:28.000Z"
},
"count": 1
},
"userData": {
"data": [],
"count": 0
},
"collections": {
"data": [],
"count": 0
},
"favourites": {
"data": [],
"count": 0
},
"areas": {
"data": [],
"count": 0
},
"stories": {
"data": [],
"count": 0
},
"subscriptions": {
"data": [],
"count": 0
},
"dashboards": {
"data": [],
"count": 0
},
"profiles": {
"data": [],
"count": 0
},
"topics": {
"data": [],
"count": 0
}
}
This endpoints allows users to get a list of all the resources they own (through their userId
or equivalent property)
on the RW API. It's available to users with the ADMIN
role, and will list resources of the following type:
- Dataset
- Layer
- Widget
- User data
- Collection
- Favourite
- Areas
- Stories
- Subscription
- Profile
- Topic
- Dashboard
Errors for getting all resources for a user id
Error code | Error message | Description |
---|---|---|
401 | Not authenticated. | You need to be logged in to use this endpoint. |
403 | Not authorized. | You need to have the ADMIN role to use this endpoint. |
Deleting a user
Deletes a user by its id
curl -X DELETE "https://api.resourcewatch.org/auth/user/<user_id>"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>"
Response
{
"data": {
"id": "57bc2611f098ce9800798688",
"_id": "57bc2611f098ce9800798688",
"provider": "local",
"email": "test@example.com",
"name": "new-name",
"photo": "https://photo-url.com",
"createdAt": "2017-01-13T10:45:46.368Z",
"updatedAt": "2017-01-13T10:45:46.368Z",
"role": "MANAGER",
"organizations": [],
"applications": [],
"extraUserData": {
"apps": [
"rw",
"gfw"
]
}
}
}
This endpoints deletes the user account with the given id. It's available to users with the ADMIN
role and to users
who want to delete their own account. The response will contain the details of the user account that was deleted.
Besides the actual user account, this action also deletes all resources of the following types that belong (through
their userId
or equivalent property) to the user:
- Dataset
- Layer
- Widget
- User data
- Collection
- Favourite
- Areas
- Stories
- Subscription
- Profile
- Topic
- Dashboard
- Applications
- Organization memberships of type "ORG_MEMBER"
- Organization memberships of type "ORG_ADMIN" will prevent a user deletion
- No actual organizations are deleted as part of this process. Only the user's membership is deleted.
The deletion of the above resources is done using a "best effort" approach: if some/all of them fail, the user deletion process will not be stopped or error, and the user account will be deleted anyways. When a user is deleted, a corresponding deletion is created, which can be used to track the success/failure of the different resource deletion process. Managing deletion resources is considered a RW API developer feature, and it's not meant to be used by regular RW API users.
Errors for deleting a user
Error code | Error message | Description |
---|---|---|
400 | Cannot delete user that is admin of an organization | Cannot delete user that is admin of an organization. Either delete the organization or promote another user to admin of that organization. |
401 | Not authenticated. | You need to be logged in to use this endpoint. |
403 | Not authorized. | You need to have ADMIN role or be logged as the user to delete to use this endpoint. |
Application
The following endpoints expose the RW API's functionality regarding application management.
Applications vs applications
Naming things is said to be one of the most challenging tasks software developers face, and the team behind the RW API
is no different, which is why the RW API effectively has 2 different notions of applications
:
- The "vanilla" applications concept:
- An
application
is identified solely by its name, present on a different resource (dataset, widget, etc) - Applications are not standalone resources
- It's used mostly for filtering/grouping said resources
- An
- The one presented in this section:
- An
application
is a complex data structure, that has a name and several other attributes - There are multiple endpoints to manage
applications
themselves, and their associations with other types of resources - It's used to manage RW API usage by different parties.
- An
This documentation section will focus on the second instance, while you can learn more about the first one in the link above.
What is an application?
In the context of the RW API, an application correspond to a unique software application which functionality relies on the RW API. Some examples of this are the Resource Watch or the Global Forest Watch websites. If you want to develop your own application that uses any of the RW API endpoints or data, you need to create an application.
Each application has, among other elements, an API key. Each API key is unique, and should be provided with each HTTP request your client application makes to the RW API. This key is used to identify your application, and serves to ensure fair usage of shared RW API resources, or allow you to request a higher request throttle limit, should you so require.
Note that applications and API keys do not replace user authentication, and they are meant to be used simultaneously, as they fundamentally serve two different purposes:
- Applications (through API keys) identify the client software application who is accessing the RW API
- User authentication (through JWT Tokens) identify the user who is accessing the RW API.
Application ownership
Before diving into application management endpoints, there is another important point that you should keep in mind when managing your applications - application ownership. Simply put, each application must have an owner, which must be either a user or an organization. A user identifies a single person using the RW API, while an organization groups different users and grants them shared privileges over applications. Each application must be owned by either a single user or a single organization, and only the owner of an application can modify it.
Whenever you create/edit an application you must/can provide either a user id or an organization id to set it as the application's owner. You cannot provide both simultaneously, and if you are editing an existing application, the newly passed ownership value will overwrite the previous one.
Getting all applications
Getting a list of applications
curl -X GET https://api.resourcewatch.org/v1/application
Response:
{
"data": [
{
"type": "applications",
"id": "63be3da993ea69eb458fc466",
"attributes": {
"name": "Sample application",
"organization": null,
"user": {
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe"
},
"apiKeyValue": "8a81e9de-517e-466f-a5d3-a1d4ccf0e290",
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
],
"links": {
"self": "https://api.resourcewatch.org/v1/application?page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/v1/application?page[number]=1&page[size]=10",
"last": "https://api.resourcewatch.org/v1/application?page[number]=99&page[size]=10",
"prev": "https://api.resourcewatch.org/v1/application?page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/v1/application?page[number]=2&page[size]=10"
},
"meta": {
"total-pages": 99,
"total-items": 990,
"size": 10
}
}
This endpoint will allow you to get the list of the applications available in the API. By default, this endpoint will give you a paginated list of 10 applications.
Depending on your user role, the behavior of this endpoint will vary:
- If you have the
ADMIN
orMANAGER
roles, you will see all applications for all users. - If you have the
USER
role, you will only see applications for which you are the owner.
For a detailed description of each field, check out the Application reference section.
Pagination
Example request to load page 2 using 25 results per page
curl -X GET https://api.resourcewatch.org/v1/application?page[number]=2&page[size]=25
The application service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your applications list.
Errors for getting all applications
Error code | Error message (example) | Description |
---|---|---|
400 | "page.size" must be less than or equal to 100 |
You cannot request page sizes larger than 100 |
401 | Not authenticated |
No authorization token was provided. |
Getting an application by id
Getting an application by id:
curl -X GET "https://api.resourcewatch.org/v1/application/51943691-eebc-4cb4-bdfb-057ad4fc2145"
Response:
{
"data": {
"type": "applications",
"id": "63be3da993ea69eb458fc4a6",
"attributes": {
"name": "Sample application",
"organization": null,
"user": {
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe"
},
"apiKeyValue": "8a81e9de-517e-466f-a5d3-a1d4ccf0e290",
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
}
If you know the id of an application, then you can access it directly. The id is case-sensitive.
To access the details of a given application using this endpoint, you need to meet one of the following conditions:
- Have the
ADMIN
orMANAGER
user role. - Own the application
- Be a member of the organization that owns the application.
Errors for getting an application by id
Error code | Error message (example) | Description |
---|---|---|
401 | Not authenticated |
No authorization token was provided. |
403 | Not authorized |
You don't have the necessary permissions to see the details for this application. |
404 | Application not found |
The application id provided is invalid or does not match any of the existing applications. |
Creating an application
curl -X POST "https://api.resourcewatch.org/v1/application" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>" \
-d \
'{
"name": "Sample application",
"user": "5bfd237767b3176dd63f2eb7"
}'
Response:
{
"data": {
"type": "applications",
"id": "63be3da993ea69eb458fc4a6",
"attributes": {
"name": "Sample application",
"organization": null,
"user": {
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe"
},
"apiKeyValue": "8a81e9de-517e-466f-a5d3-a1d4ccf0e290",
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
}
Creating an application should be one of your very first steps when using the RW API, as you will need it to make subsequent requests for other resources, like datasets, widgets, etc. If you haven't already, you should review the details of what is an application and application ownership before proceeding.
Creating an application is done using a POST request and passing the relevant data as body fields. The supported body
fields are as defined on the application reference section, but the minimum
value you need to provide is the name
.
Unless specified otherwise, an application owned by the user who created it. If you have the ADMIN
user role, you can
specify the id of the user who will own the application through the user
body field. You can alternatively use the
organization
body field to specify the id of the organization that will own the application - you can only do so if
you have the ADMIN
user role, or own that organization.
Any logged in user can create an application.
A successful application creation request will return a 200 HTTP code, and the application details as stored on the RW
API. Pay special attention to the id
, as it will allow you
to access your application later.
Errors for creating an application
Error code | Error message | Description |
---|---|---|
400 | <field> is required |
Your are missing a required field value. |
400 | <field> is not allowed |
You have provided a body value that is not supported by the endpoint. |
400 | "value" must contain at least one of [user, organization] | You must provided exactly one of either user or organization |
401 | Not authenticated | You are not authenticated. Only authenticated users can create applications. |
403 | Not authorized | You are authenticated but do not have the necessary permissions to create this application. |
403 | User can only create applications for themselves or organizations they own | You are trying to create an application for a user or organization to which you don't have permissions. |
Updating an application
Updating an application
curl -X PATCH "https://api.resourcewatch.org/v1/application/51943691-eebc-4cb4-bdfb-057ad4fc2145"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>" \
'{
"name":"new application name",
}'
Example response
{
"data": {
"type": "applications",
"id": "63be3da993ea69eb458fc4a6",
"attributes": {
"name": "new application name",
"organization": null,
"user": {
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe"
},
"apiKeyValue": "8a81e9de-517e-466f-a5d3-a1d4ccf0e290",
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
}
Modify an application to be owned by an organization
curl -X PATCH "https://api.resourcewatch.org/v1/application/51943691-eebc-4cb4-bdfb-057ad4fc2145"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>" \
'{
"organization":"6bfd237767b3176dd63f2eb7",
}'
Example response
{
"data": {
"type": "applications",
"id": "63be3da993ea69eb458fc4a6",
"attributes": {
"name": "new application name",
"user": null,
"organization": {
"id": "6bfd237767b3176dd63f2eb7",
"name": "Organization name"
},
"apiKeyValue": "8a81e9de-517e-466f-a5d3-a1d4ccf0e290",
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
}
Generate a new API key
curl -X PATCH "https://api.resourcewatch.org/v1/application/51943691-eebc-4cb4-bdfb-057ad4fc2145"
-H "Content-Type: application/json" -d \
-H "Authorization: Bearer <your-token>" \
'{
"regenApiKey":"true",
}'
Example response
{
"data": {
"type": "applications",
"id": "63be3da993ea69eb458fc4a6",
"attributes": {
"name": "Sample application",
"user": null,
"organization": {
"id": "6bfd237767b3176dd63f2eb7",
"name": "Organization name"
},
"apiKeyValue": "9811e9de-517e-466f-a5d3-a1d4ccf0e017",
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
}
This endpoint allows you to modify an existing application. You can modify the name, ownership (by passing the id
of
either the user
or orgnaization
). You can also request for a new API key to be issued for your application - in
which case the previous API key will become invalid, and all requests using it may stop functioning.
To be able to modify an application, you must either have the ADMIN
user role, be the owner of the application, or
belong to the organization that owns the application with the ORG_ADMIN
role.
Errors for updating an application
Error code | Error message | Description |
---|---|---|
400 | <field> is not allowed |
You have provided a body value that is not supported by the endpoint. |
400 | "value" contains a conflict between optional exclusive peers [user, organization] | You can only provide one of ether user or organization . |
401 | Not authenticated | You are not authenticated. Only authenticated users can update applications. |
403 | Not authorized | You are authenticated but do not have the necessary permissions to update this application. |
404 | Application with id |
An application with the provided id does not exist. |
Deleting an application
Deleting an application
curl -X DELETE https://api.resourcewatch.org/v1/application/<application-id> \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json"
Response:
{
"data": {
"type": "applications",
"id": "63be3da993ea69eb458fc4a6",
"attributes": {
"name": "Sample application",
"organization": null,
"user": {
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe"
},
"apiKeyValue": "8a81e9de-517e-466f-a5d3-a1d4ccf0e290",
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
}
Use this endpoint if you wish to delete an application. Deleting an application will render its API key invalid, and all requests made using it will return an error.
To be able to delete an application, you must either have the ADMIN
user role, be the owner of the application, or
belong to the organization that owns the application with the ORG_ADMIN
role.
Errors for deleting an application
Error code | Error message | Description |
---|---|---|
401 | Unauthorized | You need to be logged in to be able to delete an application. |
401 | Not authenticated | You are not authenticated. Only authenticated users can delete applications. |
403 | Not authorized | You are authenticated but do not have the necessary permissions to delete this application. |
404 | Application with id |
An application with the provided id does not exist. |
Application reference
This section gives you a complete view at the properties that are maintained as part of application. When interacting
with an application (on get, on create, etc) you will find most of these properties available to you, although they may
be organized in a slightly different structure (ie: on get, everything but the id
is nested inside an attributes
object).
You can find more details in the source code.
Field name | Type | Required | Default value | Description |
---|---|---|---|---|
id | String | Yes (autogenerated) | Unique Id of the application. Auto generated on creation. Cannot be modified by users. | |
name | String | Yes | Name of the application. | |
user | String | Yes (either user or organization ) |
Id of the user who owns the application. Either this or organization must be set. Only the id is stored. If set, responses will include the id and the name. |
|
organization | String | Yes (either user or organization ) |
Id of the organization who owns the application. Either this or user must be set. Only the id is stored. If set, responses will include the id and the name. |
|
createdAt | Date | No (autogenerated) | Automatically maintained date of when the application was created. Cannot be modified by users. | |
updatedAt | Date | No (autogenerated) | Automatically maintained date of when the application was last updated. Cannot be modified by users. |
Organization
The following endpoints expose the RW API's functionality regarding organization management.
What is an organization?
In the context of the RW API, an organization is an resource meant to group multiple users and grant them certain permissions and/or ownership over a group of applications. An example of an RW API organization would be WRI itself, the owner of the RW API - it's an entity that has multiple people (users) and that runs multiple software applications (GFW, RW, etc) that rely on the services of the RW API.
Organization ownership and user association
Each organization can have multiple users, yet not all users in the same organization have the same permissions to operate over said organization's resources. To differentiate between these types of access, every user associated with an organization does so through one of the following roles:
- Organization administrator, or
ORG_ADMIN
: users with this role have full access to the organization and its applications, and can perform any operation over them. Each organization must have one and only one user with this role at any given time. - Organization member, or
ORG_MEMBER
: users with this role can access but not modify the organization details and applications. Each organization can have any number of these users.
A user can be associated with any number of organizations, and can have a different role for each of them.
Getting all organizations
Getting a list of organizations
curl -X GET https://api.resourcewatch.org/v1/organization
Response:
{
"data": [
{
"type": "organizations",
"id": "63da7d2357499d85f8436cd9",
"attributes": {
"name": "Test org 1",
"applications": [
{
"id": "63be3da993ea69eb458fc466",
"name": "Sample application"
}
],
"users": [
{
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe",
"role": "ORG_ADMIN"
}
],
"createdAt": "2023-02-01T14:54:27.530Z",
"updatedAt": "2023-02-01T14:54:27.530Z"
}
}
],
"links": {
"self": "https://api.resourcewatch.org/v1/organization?page[number]=1&page[size]=10",
"first": "https://api.resourcewatch.org/v1/organization?page[number]=1&page[size]=10",
"last": "https://api.resourcewatch.org/v1/organization?page[number]=99&page[size]=10",
"prev": "https://api.resourcewatch.org/v1/organization?page[number]=1&page[size]=10",
"next": "https://api.resourcewatch.org/v1/organization?page[number]=2&page[size]=10"
},
"meta": {
"total-pages": 99,
"total-items": 990,
"size": 10
}
}
This endpoint will allow you to get the list of the organizations available in the API. By default, this endpoint will give you a paginated list of 10 organizations.
In order to use this endpoint, you need to be authenticated as an ADMIN
or MANAGER
user.
For a detailed description of each field, check out the Organization reference section.
Pagination
Example request to load page 2 using 25 results per page
curl -X GET https://api.resourcewatch.org/v1/organization?page[number]=2&page[size]=25
The organization service adheres to the conventions defined in the Pagination guidelines for the RW API, so we recommend reading that section for more details on how paginate your organizations list.
Getting an organization by id
Getting an organization by id:
curl -X GET "https://api.resourcewatch.org/v1/organization/51943691-eebc-4cb4-bdfb-057ad4fc2145"
Response:
{
"data": {
"type": "organizations",
"id": "63da7d2357499d85f8436cd9",
"attributes": {
"name": "Test org 1",
"applications": [
{
"id": "63be3da993ea69eb458fc466",
"name": "Sample application"
}
],
"users": [
{
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe",
"role": "ORG_ADMIN"
}
],
"createdAt": "2023-02-01T14:54:27.530Z",
"updatedAt": "2023-02-01T14:54:27.530Z"
}
}
}
If you know the id of an organization, then you can access it directly. The id is case-sensitive.
In order to use this endpoint, you must be logged in and either:
- have either
ADMIN
orMANAGER
user role. - be associated with the target organization, as either a member or as an admin - see Organization ownership and user association for more details.
Errors for getting an organization by id
Error code | Error message (example) | Description |
---|---|---|
401 | Not authenticated |
No authorization token was provided. |
403 | Not authorized |
You do not have the necessary permissions to see this organization's details. |
Creating an organization
curl -X POST "https://api.resourcewatch.org/v1/organization" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>" \
-d \
'{
"name": "Test org 1",
"user": [{
"id": "5bfd237767b3176dd63f2eb7",
"role": "ORG_ADMIN"
}]
}'
Response:
{
"data": {
"type": "organizations",
"id": "63be3da993ea69eb458fc4a6",
"attributes": {
"name": "Test org 1",
"applications": [],
"users": [
{
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe",
"role": "ORG_ADMIN"
}
],
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
}
Creating an organization is currently reserved for RW API administrators (users with
the ADMIN
role, so if you'd like to create your own,
please contact us letting us know about you and your
organization.
Creating an organization is done using a POST request and passing the relevant data as body files. The supported body fields are as defined on the organization reference section, but the minimum field list you must specify for any organization is:
name
users
, with a list of object, containing the userid
, and itsrole
in the organization. At least one user must be provided, and at least one user must have the roleORG_ADMIN
.
A successful organization creation request will return a 200 HTTP code, and the organization details as stored on the RW
API. Pay special attention to the id
, as it will allow you
to access your organization later.
When creating an organization, you can also pass an optional array of applications ids, as applications
in the request
body. These applications must already exist.
It's worth keeping in mind that applications can either belong to a single user or a single organization, so by creating
an organization with applications
associated with it, you may be removing associations between the
provided applications
and other users/organizations.
Errors for creating an organization
Error code | Error message | Description |
---|---|---|
400 | <field> is required |
Your are missing a required field value. |
400 | <field> is not allowed |
You have provided a body value that is not supported by the endpoint. |
400 | "users" must contain at least 1 items | You must provide at least one user. |
400 | "users" must contain a user with role ORG_ADMIN' | You must provide at least a user with ORG_ADMIN role. |
401 | Not authenticated | You are not authenticated. Only authenticated users can create organizations. |
403 | Not authorized | You are authenticated but do not have the necessary permissions to create this organization. |
Updating an organization
Updating an organization
curl -X PATCH "https://api.resourcewatch.org/v1/organization/51943691-eebc-4cb4-bdfb-057ad4fc2145"
-H "Content-Type: organization/json" -d \
-H "Authorization: Bearer <your-token>" \
'{
"name":"new organization name",
}'
Example response
{
"data": {
"type": "organizations",
"id": "63be3da993ea69eb458fc4a6",
"attributes": {
"name": "new organization name",
"applications": [],
"users": [
{
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe",
"role": "ORG_ADMIN"
}
],
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
}
Modify an organization and replacing its applications
curl -X PATCH "https://api.resourcewatch.org/v1/organization/51943691-eebc-4cb4-bdfb-057ad4fc2145"
-H "Content-Type: organization/json" -d \
-H "Authorization: Bearer <your-token>" \
'{
"applications": ["6bfd237767b3176dd63f2eb7"],
}'
Example response
{
"data": {
"type": "organizations",
"id": "63be3da993ea69eb458fc4a6",
"attributes": {
"name": "new organization name",
"applications": [
{
"id": "6bfd237767b3176dd63f2eb7",
"name": "application name"
}
],
"users": [
{
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe",
"role": "ORG_ADMIN"
}
],
"createdAt": "2023-01-11T04:40:09.455Z",
"updatedAt": "2023-01-11T04:40:09.455Z"
}
}
}
This endpoint allows you to modify an existing organization. When updating an organization, you can pass new values for any of these optional parameters:
name
: Modifies the organization's name.users
: A list of objects, withid
being the user's id, androle
being said user's role in the organization - must be eitherORG_ADMIN
orORG_MEMBER
. One and only oneORG_ADMIN
user must exist per organization.applications
: A list of applications ids to be owned by this organization.
When modifying either users
or applications
, keep in mind that the list of associations you provide will overwrite
the previous one.
It's worth keeping in mind that applications can either belong to a single user or a single organization, so by updating
an organization with applications
associated with it, you may be removing associations between the
provided applications
and other users/organizations.
In order to use this endpoint, you must be logged in and either:
- have the
ADMIN
user role. - be the organization admin - see Organization ownership and user association for more details.
Additionally, if you are using this endpoint to add existing applications to an organization, you must either
- have the
ADMIN
user role. - be the owner of the application.
Errors for updating an organization
Error code | Error message | Description |
---|---|---|
400 | <field> is not allowed |
You have provided a body value that is not supported by the endpoint. |
400 | "users" must contain at least 1 items | You must provide at least one user. |
400 | "users" must contain a user with role ORG_ADMIN | You must provide at least a user with ORG_ADMIN role. |
400 | "users" must contain single a user with role ORG_ADMIN | You must provide only one user with ORG_ADMIN role. |
401 | Not authenticated | You are not authenticated. Only authenticated users can update organizations. |
403 | Not authorized | You are authenticated but do not have the necessary permissions to update this organization, or to add one of the provided application to the organization. |
404 | Organization with id |
An organization with the provided id does not exist. |
Deleting an organization
Deleting an organization
curl -X DELETE https://api.resourcewatch.org/v1/organization/<organization-id> \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: organization/json"
Response:
{
"data": {
"type": "organizations",
"id": "63da7d2357499d85f8436cd9",
"attributes": {
"name": "Test org 1",
"applications": [
{
"id": "63be3da993ea69eb458fc466",
"name": "Sample application"
}
],
"users": [
{
"id": "5bfd237767b3176dd63f2eb7",
"name": "John Doe",
"role": "ORG_ADMIN"
}
],
"createdAt": "2023-02-01T14:54:27.530Z",
"updatedAt": "2023-02-01T14:54:27.530Z"
}
}
}
Use this endpoint if you wish to delete an organization. In order to use this endpoint, you must be logged in and have
the ADMIN
user role.
Only organizations that do not have any applications associated with them can be deleted.
Errors for deleting an organization
Error code | Error message | Description |
---|---|---|
400 | Organizations with associated applications cannot be deleted | You are trying to delete an organization that still has applications associated with it. Either transfer ownership or delete the applications. |
401 | Not authenticated | You are not authenticated. Only authenticated users can delete organizations. |
403 | Not authorized | You are authenticated but do not have the necessary permissions to delete this organization. |
404 | Organization with id |
An organization with the provided id does not exist. |
Organization reference
This section gives you a complete view at the properties that are maintained as part of organization. When interacting
with an organization (on get, on create, etc) you will find most of these properties available to you, although they may
be organized in a slightly different structure (ie: on get, everything but the id
is nested inside an attributes
object).
You can find more details in the source code.
Field name | Type | Required | Default value | Description |
---|---|---|---|---|
id | String | Yes (autogenerated) | Unique Id of the organization. Auto generated on creation. Cannot be modified by users. | |
name | String | Yes | Name of the organization. | |
users | Object array | Yes | List of objects, each containing the id of an user, and the role they have in the organization - which can be either ORG_ADMIN or ORG_MEMBER . Every organization must have at least one ORG_ADMIN user. |
|
applications | String array | No | List of applications owned by this organization | |
createdAt | Date | No (autogenerated) | Automatically maintained date of when the organization was created. Cannot be modified by users. | |
updatedAt | Date | No (autogenerated) | Automatically maintained date of when the organization was last updated. Cannot be modified by users. |
User data
The following endpoints expose the RW API's functionality regarding user data management. These endpoints will allow you to store and recover user-specific data related to the RW API, like application-specific preferences, that are not already covered by other endpoints.
These endpoints assume you already have a user account and are logged in using it - for more details on that, see this section.
What is user data?
The RW API endpoints allow users to upload their own customized data and share it with the world - it's its core mission. However, at times, you may want to store data that is specific to your usage of the RW API, and while not secret, it only makes sense to your specific user needs. Some examples of this may be a widget or layer personalization, an application' settings, or additional details about your user profile.
The User data service allows you to store data specific to your usage of the RW API, in an easy and convenient way.
Besides a few core, common fields, your data is indexed by application, allowing
different RW API ecosystem apps and tools to share this common data storage, while ensuring simplicity for RW API
developers. To ensure this, make sure to properly store you application's data in the correct form -
inside applicationData
, indexed by your application's name.
Important: User data, as defined managed by these endpoints, is not the same as user account, as managed by the User management endpoints. A user account is what you use to login and authenticate. User data is an optional data storage feature, made available to anyone with an user account. Creating/updating/deleting a user account does not automatically create/update/delete user data.
Warning: The data stored through these endpoints is individual to your user account, but it's not treated and confidential or sensitive. You should not store any sort of data that you would not like to see potentially disclosed, like passwords, sensitive and/or personal information, etc.
Deprecation notice: These docs cover the /v2
user data endpoints, which are currently maintained. A /v1
set of
endpoints also exists, but its deprecated, and should not be used. If your application is using the /v1
endpoints, you
should upgrade at your earliest convenience. Functionality and data wise, /v2
is a superset of /v1
.
Getting user data
Get user data for the current user
curl -X GET "https://api.resourcewatch.org/v2/user" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Get user data for a given user id
curl -X GET "https://api.resourcewatch.org/v2/user/5bfd237767b3176dd63f2eb7" \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
Response:
{
"data": {
"type": "user",
"id": "5bfd237767b3176dd63f2eb7",
"attributes": {
"fullName": "John Doe",
"email": "john.doe@wri.org",
"createdAt": "2017-04-25T14:15:58.469Z",
"applicationData": {
"gfw": {
"sector": "Private sector",
"state": "",
"city": "",
"howDoYouUse": [
""
],
"primaryResponsibilities": [
""
],
"signUpForTesting": false,
"language": "en",
"profileComplete": true,
"interests": [],
"signUpToNewsletter": false,
"topics": []
}
}
}
}
}
There are two endpoints that allow you to retrieve user data:
- If no user id is provided, the service will return the data for the current user.
- If a user id is provided, the provided authentication token must either match the requested user, or it must have
the
ADMIN
role.
Errors
Error code | Error message | Description |
---|---|---|
401 | Not authenticated. | You are not logged in. |
403 | Forbidden. | You do not have permission to access the requested data. |
404 | User not found | The requested user id does not have stored user data. |
Creating user data
Create user data for the current user
curl -X POST https://api.resourcewatch.org/v2/user \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"fullName": "John Doe",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@wri.org",
"applicationData": {
"gfw": {
"someKey": "someValue"
}
}
}'
{
"data": {
"type": "user",
"id": "5bfd237767b3176dd63f2eb7",
"attributes": {
"fullName": "John Doe",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@wri.org",
"createdAt": "2017-04-25T14:15:58.469Z",
"applicationData": {
"gfw": {
"sector": "Private sector",
"state": "",
"city": "",
"howDoYouUse": [
""
],
"primaryResponsibilities": [
""
],
"signUpForTesting": false,
"language": "en",
"profileComplete": true,
"interests": [],
"signUpToNewsletter": false,
"topics": [],
"someKey": "someValue"
}
}
}
}
}
This endpoint allows you to store user data for a user that did not previously have user data. Each user (by id) can only have a single user data record, and it will be shared and visible in other RW API applications that rely on these endpoints, so it's important to follow a few guidelines to help maintain coherence:
- User data root fields (around name and email address) are meant to be shared between multiple apps, so only modify those if the change is intentional by the user.
- All application-specific data must be stored in the applicationData
object, and in it, indexed by your application name. The included example shows how the gfw
application could store its data. This is not enforced, but disregarding this principle may lead to your data being deleted without prior notice.
- The gfw
application has special logic and fields, as seen in the included example. However, other application keys will not have this, and no manipulation will occur on your data stored. What you send is what gets stored, no more, no less.
Errors
Error code | Error message | Description |
---|---|---|
400 | Duplicated user. | This user already has data associated with it. |
400 | Unsupported sector. | The provided applicationData.gfw.sector value is not formatted correctly. |
401 | Not authenticated. | You are not logged in. |
403 | Forbidden. | You do not have permission to access the requested data. |
Updating user data
Update user data for the given user id
curl -X PATCH https://api.resourcewatch.org/v2/user/5bfd237767b3176dd63f2eb7 \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"fullName": "John Doe",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@wri.org",
"applicationData": {
"gfw": {
"someKey": "someOtherValue"
}
}
}'
{
"data": {
"type": "user",
"id": "5bfd237767b3176dd63f2eb7",
"attributes": {
"fullName": "John Doe",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@wri.org",
"createdAt": "2017-04-25T14:15:58.469Z",
"applicationData": {
"gfw": {
"sector": "Private sector",
"state": "",
"city": "",
"howDoYouUse": [
""
],
"primaryResponsibilities": [
""
],
"signUpForTesting": false,
"language": "en",
"profileComplete": true,
"interests": [],
"signUpToNewsletter": false,
"topics": [],
"someKey": "someOtherValue"
}
}
}
}
}
This endpoint allows you to update existing user data for a user. Similar to the user data creation process, there are a few things to keep in mind when updating user data, to help maintain coherence:
- User data root fields (around name and email address) are meant to be shared between multiple apps, so only modify those if the change is intentional by the user.
- All application-specific data must be stored in the applicationData
object, and in it, indexed by your application name. The included example shows how the gfw
application could store its data. This is not enforced, but disregarding this principle may lead to your data being deleted without prior notice.
- The gfw
application has special logic and fields, as seen in the included example. However, other application keys will not have this, and no manipulation will occur on your data stored. What you send is what gets stored, no more, no less.
- If updating a key within the applicationData
object, all its content will be replace with the values you provide. Keys not provided are kept as-is.
You can only update user data for the user provided in the authentication token.
Errors
Error code | Error message | Description |
---|---|---|
400 | Unsupported sector. | The provided applicationData.gfw.sector value is not formatted correctly. |
401 | Not authenticated. | You are not logged in. |
403 | Forbidden. | You do not have permission to access the requested data. |
404 | User not found | The requested user id does not have stored user data. |
Deleting user data
Delete user data for the given user id
curl -X DELETE https://api.resourcewatch.org/v2/user/5bfd237767b3176dd63f2eb7 \
-H "Authorization: Bearer <your-token>" \
-H "x-api-key: <your-api-key>"
{
"data": {
"type": "user",
"id": "5bfd237767b3176dd63f2eb7",
"attributes": {
"fullName": "John Doe",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@wri.org",
"createdAt": "2017-04-25T14:15:58.469Z",
"applicationData": {
"gfw": {
"sector": "Private sector",
"state": "",
"city": "",
"howDoYouUse": [
""
],
"primaryResponsibilities": [
""
],
"signUpForTesting": false,
"language": "en",
"profileComplete": true,
"interests": [],
"signUpToNewsletter": false,
"topics": [],
"someKey": "someOtherValue"
}
}
}
}
}
This endpoint allows you to delete user data. Keep in mind that this will delete all user data for all applications, and not just yours. If you want to delete user data for your application, use the update user data endpoint instead. Fully deleting user data will typically only be used when deleting the actual user account.
You can only delete user data for the user provided in the authentication token.
Errors
Error code | Error message | Description |
---|---|---|
401 | Not authenticated. | You are not logged in. |
403 | Forbidden. | You do not have permission to access the requested data. |
404 | User not found | The requested user id does not have stored user data. |
Troubleshooting
This section is meant to help you deal with common pitfalls of everyday usage of the API.
Authentication and authorization
401 Unauthorized
401 Unauthorized
errors mean that the API did not receive the necessary data to identify who you are. You may not be
logged in, there may be an issue with your usage of the user token, or the token you are using may be in the wrong
header.
Make sure you have followed the quickstart guide, which shows you how to create a JSON Web Token for
authorization and how to pass it correctly in the Authorization
header.
403 Forbidden
A 403 Forbidden
error means that you are identified as a valid user, but you do not have the required permissions for
the action you are trying to perform. Common scenarios where this happens are:
- You do not have the required user
ROLE
to carry out that operation. - You may be trying to operate on a resource that belongs to a different
application
than the ones you are associated with. Read more about how theapplication
field works here. - Certain resources have a concept of
owner
with certain actions being exclusively available to that particular user.
Check the specific documentation for the endpoint you are trying to use for more details on its behavior. Conditions
that trigger a 403 Forbidden
error will often vary beyond the ones listed above.
Contact
The following contact endpoints are available
Contact us
Example request with the minimum required data
curl -X POST https://api.resourcewatch.org/v1/form/contact-us \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"email": "example.example@vizzuality.com",
"message": "This is a test"
}'
Example request with complete data
curl -X POST https://api.resourcewatch.org/v1/form/contact-us \
-H "x-api-key: <your-api-key>" \
-H "Content-Type: application/json" -d \
'{
"email": "example.example@vizzuality.com",
"message": "This is a test",
"language": "es_MX",
"tool": "fw",
"topic": "data-related-inquiry"
}'
Sends a contact form including an origin email address and a message. It can also optionally include:
language
: One of the following supported values:en
,es_MX
,fr
,id
,pt_BR
orzh
. Defaults toen
.topic
: One of the following supported values:report-a-bug-or-error
,provide-feedback
,data-related-inquiry
orgeneral-inquiry
. Defaults togeneral-inquiry
.tool
: One of the following supported values:gfw
,gfw-pro
,fw
,blog
,map-builder
ornot-applicable
. Defaults tonot-applicable
The language
value is used as a reference for future communication with the user. topic
and tool
are used to
internally better determine the communication path the request must follow in order to reach the desired person that
will handle it.
On success, a 200 HTTP code with no response body is returned.
Requesting a webinar
Example request for a webinar
curl -X POST "https://api.resourcewatch.org/v1/form/request-webinar" \
-H "Content-Type: application/json" \
-H "x-api-key: <your-api-key>" \
-d \
'{
"name": "Example name",
"email": "example@email.com",
"request": "Example request text"
}'
This endpoint allows users to request a webinar. Internally, it sends the user submitted information to a WRI staff member, via email. The user must provide their name, email address, and a request text, all of which will be included in the above mentioned email. A successful request returns an HTTP 204 response.