NAV Navbar
Logo rw
cURL

Introduction

Welcome to the Resource Watch API Documentation

About these docs

This documentation page aims to cover the Resource Watch API functionality and details. In it, you’ll find a top-level description of the services it provides, as well as a breakdown of the different endpoints, their functionality, parameters and output. The goal is to give you the tools to create powerful applications and data products.

The RW API is HTTP and JSON based, and these docs assume you are familiar with both technologies. Besides endpoint descriptions, the documentation will include example code snippets that use cURL to illustrate how you would use each endpoint. Knowing the basics of cURL will help you better understand those examples.

For readability, URLs and query parameters may be displayed without escaping/encoding, but be sure to encode your URLs before issuing a request to the API, or it may produce undesired results. If you are using the RW API to build your own application, there’s probably a library out there that does this for you automatically.

In these examples, you’ll also find references to a Authorization: Bearer <your-token> HTTP header. You can find more details about tokens in the authentication section, which you should read before you get started.

Last but not least, the RW API and its docs are made by humans, who will occasionally make mistakes. If you find something that you think is incorrect, could be improved, if you want to contribute yourself, or just want to say “thank you”, you can reach us through the RW API documentation Github project page.

Concepts

Dataset

One of the Resource Watch API’s (RW API) goals is to provide a common interface for interacting with data hosted in different sources and formats. A Dataset is the Resource Watch’s API way of providing users with access to data, while trying to, as much as possible, abstract and standardise operations that would otherwise fall on the user’s hands to figure out. It’s one of the cornerstones that many other API features build upon - and those features can help you get even more out of your data!

Example: A Resource Watch API dataset can represent data in a JSON file, hosted on Carto or Google Earth Engine, to name a few. However, when accessing that data, you don’t have to learn 3 different technologies - the Resource Watch API gives you a single, unified query interface.

On top of datasets, the RW API offers multiple resources that allow you to access data in multiple formats. These will be covered later in full detail, but as an example, here are some ways in which you can access and use datasets:

Dataset providers

Each dataset has a provider (json/carto/GEE/…) that must specified on creation - it’s this value that tells the RW API how to handle different data providers and formats, so you don’t have to. Below you’ll find a list of the different providers supported:

Carto

Carto is an open, powerful, and intuitive map platform for discovering and predicting key insights underlying the location data in our world.

ArcGIS feature layer

ArcGIS server is a complete, cloud-based mapping platform. You can learn more about ArcGIS here.

Google Earth Engine

Google Earth Engine combines a multi-petabyte catalog of satellite imagery and geospatial datasets with planetary-scale analysis capabilities and makes it available for scientists, researchers, and developers to detect changes, map trends, and quantify differences on the Earth’s surface.

Web Map Services

WMS connector provides access to data served through OGC WMS protocol standard.

Rasdaman (Raster Data Manager)

Rasdaman is a database with capabilities for storage, manipulation and retrieval of multidimensional arrays.

NEX-GDDP

The NASA Earth Exchange Global Daily Downscaled Projections (NEX-GDDP) dataset is comprised of downscaled climate scenarios for the globe that are derived from the General Circulation Model (GCM) runs conducted under the Coupled Model Intercomparison Project Phase 5 (CMIP5) and across two of the four greenhouse gas emissions scenarios known as Representative Concentration Pathways (RCPs).

Note: While you may find and use existing dataset of this type, creation of new NEX-GDDP based datasets is restricted to specific users.

BigQuery

BigQuery is a serverless, highly scalable, and cost-effective cloud data warehouse designed to help you make informed decisions quickly, so you can transform your business with ease.

Note: While you may find and use existing dataset of this type, creation of new BigQuery based datasets is restricted to specific users.

Loca

LOCA, which stands for Localized Constructed Analogs, is a technique for downscaling climate model projections of the future climate.

Note: While you may find and use existing dataset of this type, creation of new LOCA based datasets is restricted to specific users.

Comma-Separated Values (CSV)

Data provided in the form of a Comma-Separated Values (CSV) document.

Tab-Separated Values (TSV)

Data provided in the form of a Tab-Separated Values (TSV) document.

JavaScript Object Notation (JSON)

Data provided in the form of a JSON document.

Extensible (X) Markup Language (XML)

Data provided in the form of a XML document.

Dataset connector type

Each dataset provider has an associated connector type, which you can determine using the table below.

Connector type Providers
document csv, json, tsv, xml
rest cartodb, featureservice, gee, bigquery, rasdaman, nexgddp, loca
wms wms

The connector type reflects an important aspect of a dataset: where is the actual data kept, and how is it accessed:

Query

In the previous section, we covered the concept of a RW API dataset which, in simple terms, is a way to tell the RW API that your data exists, and where. While cataloging datasets in a public repository is useful, making that data easily accessible is one of the main goals of the RW API. This is where queries come in.

In the context of the RW API, a dataset query is very similar an SQL query would be to a database - it’s a specially crafted statement that allows you to express what data you want, from which dataset, and with which structure. The RW API will use that query to get you the data you need, in the format you asked for, so that it’s easy to use in the context of your applications. While it doesn’t comply (nor does it attempt to) with any of the formal SQL specifications, RW API queries use a SQL-like syntax that will be very familiar to anyone who has worked with a relational database in the past. If that’s not your case, there are many tutorials out there that will help you learn the basics in no time.

Using this common, SQL-based syntax, RW API queries allow you to query its datasets using a common API and syntax, no matter where the actual underlying data is hosted. Querying a carto dataset is the same as querying a JSON document or a BigQuery table. This is one of the main goals of the RW API, and one of most valuable features we offer you, the end user - using a single tool and language, you can quickly query data from a wide range of sources, on a broad set of topics.

In the query endpoint documentation below, we’ll go into more detail on how you can submit your queries to the API, the specifics of more advanced operations and detailed limitations of querying the RW API but, for now, there are 3 high-level ideas that you should keep in mind:

All queries should be SELECT queries

Querying in the RW API is meant to be used only to read data, not to manipulate it. If you have used SQL before, you know it can be used to modify data, but, as a rule of thumb, that’s not the approach used in the RW API. If you’d like to modify the data of a dataset, you should use the dataset update endpoints instead. The only exception to this is for deleting data from document-based datasets - check here for more details.

Not all SQL constructs are supported

If you’ve used SQL in the past, you know how powerful (and complex) it can be. Things like nested queries or joins can be hard to use and even more to maintain, even without the added complexity of an environment where multiple data providers coexist. That’s why the RW API limits its support to basic SQL syntax, so we can focus on delivering a tool that’s simple and easy to use for most users. The supported SQL syntax reference section below will go into more detail on what’s supported and what’s not, and will help you understand the specifics of what you can achieve with RW API queries.

Some operation will depend on the provider of the dataset you’re querying

Our goal is to provide a common querying interface across all datasets, independent of their provider. While we believe we’ve achieved it in most cases, RW API queries can only be as powerful as the underling provider (and their own APIs) allows them to be. There are cases in which a given SQL construct or function is supported for a given provider, but not for another. The supported SQL syntax reference below has more details on these limitations, per provider.

Layer

Apart from the possibility of fetching data from multiple data sources using a common interface, the RW API provides you with features to help you visualize such data. A layer is one of the resources that you can use to help you make custom visualizations for your data, and they play a very important role when visualizing datasets that contain geospatial data.

A layer is a visual specification of how the data of a dataset can be rendered and styled on a map. It stores data that will help your applications render dataset data as a map layer, using tools like Leaflet, Mapbox GL JS or Layer Manager. In this sense, it’s important to emphasise that a layer object does not store the actual data to be represented - it instead stores the information that those rendering tools will use to render your data. Rephrasing it: the data should come from the dataset (through queries), while a layer provides the information about how that data is meant to be rendered by the corresponding rendering tool.

In the layer endpoint documentation, we’ll go into more detail on how you can manage layers, as well as the existing limitations that you might run into when using layers. However, for now, there are 3 high-level ideas that you should keep in mind:

The layer does not interact with dataset data

Layers store visual configurations needed for rendering styling a given dataset’s data. However, they do not interact with the dataset data in any way. It is your responsibility, as a RW API user, to build the appropriate queries to retrieve the data that you want to display (read more about datasets or how you can query datasets to obtain their data). Remember, use layers as a complement of dataset queries, not a replacement.

Most of layer fields are free-form

Many of the fields in the layer object are free-form, meaning the RW API does not apply any restriction to whatever is saved in those fields. This is great, because it allows for a very high level of flexibility for users, but has the downside of making it harder to document how to use layers. We tried our best to provide clear and consistent specifications for all the fields of a layer, but keep in mind that this high level of flexibility makes it harder to deliver a concrete description.

Different applications and rendering tools use layers in different ways

At the moment, most applications using the layer endpoints have adapted layers to tailor fit their needs, taking advantage of the flexibility that free-form fields bring. This means that, when navigating through the catalog of available layers, you might run into very different ways of implementing and using layers. Once again, we will try our best to cover the different ways of using and managing layers, but keep in mind that there is currently no standard way of using layers.

As layers are typically managed within the realm of a RW API based application, they typically contain data that covers the needs of that application’s specific rendering tool. This again means that you may find varying structure in the data contained in a layer.

Widget

You have fetched your data from your dataset using queries. And you know how to build custom visualizations for geospatial data using layers. Yet, sometimes you want to build a plain graphical representation of your data - whether it is geo-referenced or not: this is when widgets come in handy.

A widget is a visual specification of how to style and render the data of a dataset (think pie, bar or line charts).

As with layers, each widget has a single dataset associated with it, and a dataset can be associated with many widgets. You can represent the same data in different ways by creating different widgets for the same dataset. The same widget can store independent configuration values for each RW API based application. It can also contain the required configuration for rendering the same visualization using different rendering tools.

However, this association between widgets and datasets is only for organizational purposes. As such, like in the case of layers, the widget itself does not interact with the dataset data. You can either use the widget’s queryUrl field to store the query to get the widget’s data or store it inside the free form widgetConfig object. In any of these cases, it is your responsibility as an API user to query the data that will be used for rendering the widget.

In the widget endpoint documentation, you can get into more detail on how you can manage widgets.

Widget configuration using Vega grammar

As in the case of layers (where many fields are free-form), the RW API does not apply any restriction to the data saved in the widget configuration field (widgetConfig). This allows for a very high level of flexibility for users but has the downside of making it harder to document how to use widgets.

However, the existing widgets’ standard approach for building widget configuration objects is using Vega grammar. Vega is a visualization grammar, a declarative format for creating interactive visualization designs. You can then use a chart library that supports Vega grammar syntax (such as d3.js) to render the widget and get your graphical representation.

Please note that, in any case, you can use whatever configuration format you wish since the widgetConfig field is free-form.

Authentication

The RW API provides most of its data through endpoints that are available to all users, without requiring any form of registration. However, some actions, like uploading data or flagging a resource as a favourite, require having a user account and using an access token when issuing requests to the API.

In this section you will learn the very basics of how you can quickly create a user account and use your token to authenticate requests. For more in-depth details on authentication, token and user management, refer to the User Management section of the documentation.

Logging in or registering a new user account

The easiest way to access your account is through the login page of the RW API. Here you can authenticate using your existing Facebook, Google or Twitter account, or you can register or login using your email address and password.

Note: if you create a new user account using email and password, a confirmation link will be sent to the email address you provided. Your account will only be active once you’ve clicked the link in that email, so ensure that you use a valid email address. If you don’t receive this email message within a few minutes, check your spam.

Once you’ve successfully logged in using your browser, you’ll see a “Welcome to the RW API message” on your browser. You can now generate user tokens.

Auth success

How to generate your private token

The RW API uses JWT (JSON Web Tokens) tokens to identify and authenticate its users. If your are not familiar with the details of JWT, just think of them as a very long strings of characters that you need to attach to your requests to the RW API, to prove that you are you.

To get you token, you first need to login using your browser and the steps above. No matter which login strategy you prefer, once you’ve logged in, you can visit https://api.resourcewatch.org/auth/generate-token to get your token.

Warning: treat a token in the same way you would treat a password - don’t share it and always store it in a safe place (like a password manager, for example). A token is sufficient to authenticate you on the RW API, meaning that, if someone else gains access to your token, they’ll be able to do anything that you would be able to do on the RW API, even without access to your Facebook/Google/Twitter login or your email and password.

How to use your private token to authenticate a request

Example of how a request with a token is structured

curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your token>" \
-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"
    ]
  }
}'

Once you have your token, you can use it to authenticate your requests to the RW API. Depending on which endpoints you are trying to use, certain actions may become available by simply authenticating your request. Other will require your account to have a special role or applications, which we’ll cover in more detail in the User Management documentation.

Tokens must be provided in HTTP request header, named as Authorization, with the structure Bearer <your token>.

Once generated, a token is valid until any of the associated user information (name, email, or associated applications) changes. If your token becomes invalid, you will need to log in and go to https://api.resourcewatch.org/auth/generate-token to generate a new token.

Contact

The following contact endpoints are available

Contact us

Sends a contact form including a topic, email address, and a message.

Example

Contact form sent using the type General question or feedback, the email address example@example.com and the message This is a text:

curl -X POST https://api.resourcewatch.org/v1/contact-us \
-H "Content-Type: application/json" -d \
    '{
        "topic": "General question or feedback",
        "email": "example.example@vizzuality.com",
        "text": "This is a test"
    }'

Collections

The users can save a collection of resources in the API.

Field Description Type
name Name of collection owner Text
ownerId Id of the owner Text
resources Resources in the collection Array of Objects
— type The type of resource Text (dataset, layer, widget)
— id The id of the resource Text

Create Collection

To create a collection, you need to define all next fields in the request body. The required fields that compose a collection are:

Field Description Type
name Name of collection owner Text

To create an empty collection, you have to do a POST with the following body:

curl -X POST https://api.resourcewatch.org/v1/collection \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json"  -d \
 '{
   "name": "<name>"
  }'

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 "Content-Type: application/json"  -d \
 '{
   "name": "<name>",
   "resources": [
     {
      "type": "<type>",
      "id": "<id>"
      }
   ]
  }'

Update 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/<collection-id> \
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json"  -d \
 '{
   "name": "<name>"
  }'

Add Resource to Collection

To create a collection, you need to define all next fields in the request body. The required fields that compose a collection are:

Field Description Type
type Type of resource being added Text (dataset, layer, widget)
id Id of the resource Text

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 "Content-Type: application/json"  -d \
 '{
   "type": "<type>",
   "id": "<id>"
  }'

Get Collections

This endpoint returns the collections of the logged user.

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>"

Get Collection by id

This endpoint returns the collection with id of the param. If the collection belongs to other user or not exist, the endpoint returns 400.

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>"

Delete Collection

This endpoint deletes the collection with id of the param. If the collection belongs to other user or not exist, the endpoint returns 400.

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>"

Delete Collection Resource

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.

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>"

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

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": "http://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": "http://api.resourcewatch.org/v1/dataset?page[number]=1&page[size]=10",
    "first": "http://api.resourcewatch.org/v1/dataset?page[number]=1&page[size]=10",
    "last": "http://api.resourcewatch.org/v1/dataset?page[number]=99&page[size]=10",
    "prev": "http://api.resourcewatch.org/v1/dataset?page[number]=1&page[size]=10",
    "next": "http://api.resourcewatch.org/v1/dataset?page[number]=2&page[size]=10"
  },
  "meta": {
    "total-pages": 99,
    "total-items": 990,
    "size": 10
  }
}

Pagination

The RW API lists many of its resources as pages, as opposed to showing all results at once. By default, datasets are listed in pages of 10 datasets each, and the first page is loaded. However, you can customize this behavior using the following query parameters:

Custom pagination: load page 2 using 25 results per page

curl -X GET https://api.resourcewatch.org/v1/dataset?page[number]=2&page[size]=25
Field Description Type Default
page[size] The number elements per page. Values above 100 are not officially supported. Number 10
page[number] The page number Number 1

Search for datasets

curl -X GET https://api.resourcewatch.org/v1/dataset?search=wind

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:

Filters

Filtering datasets

curl -X GET https://api.resourcewatch.org/v1/dataset?name=birds&provider=cartodb

Matching vocabulary tags

curl -X GET https://api.resourcewatch.org/v1/dataset?vocabulary[legacy]=umd

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. These parameters can be combined into a complex and logic query.

Here’s the comprehensive list of filters supported by datasets:

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. 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 trueor 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 trueor false
env Environment to which the dataset belongs. Multiple values can be combined using , as a separator. Does not support regexes. String any valid text. Defaults to production.
geoInfo If it contains interceptable geographical info Boolean trueor false
protected If the dataset is protected. Boolean trueor 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. 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

Please keep in mind the following:

Sorting

Basics of sorting

Sorting datasets

curl -X GET https://api.resourcewatch.org/v1/dataset?sort=name

Sorting datasets by multiple criteria

curl -X GET https://api.resourcewatch.org/v1/dataset?sort=name,description

Sort by name descending, description ascending

curl -X GET https://api.resourcewatch.org/v1/dataset?sort=-name,+description

Sorting datasets by the role of the user who owns the dataset

curl -X GET https://api.resourcewatch.org/v1/dataset?sort=user.role

The API currently supports sorting by means of the sort query parameter. Sorting can be done using any field from the dataset model, as well as user.name and user.role (sorting by user data is restricted to ADMIN users). Sorting by nested fields is not supported at the moment.

Multiple sorting criteria can be used, separating them by commas.

You can also specify the sorting order by prepending the criteria with either - for descending order or + for ascending order. By default, ascending order is assumed.

Special sorting criteria

Sorting datasets with special criteria

curl -X GET https://api.resourcewatch.org/v1/dataset?sort=-most-favorited
curl -X GET https://api.resourcewatch.org/v1/dataset?sort=relevance&status=saved&search=agriculture

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:

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
{
    "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": "http://api.resourcewatch.org/v1/dataset?includes=widget%2Cmetadata&page[number]=1&page[size]=10",
        "first": "http://api.resourcewatch.org/v1/dataset?includes=widget%2Cmetadata&page[number]=1&page[size]=10",
        "last": "http://api.resourcewatch.org/v1/dataset?includes=widget%2Cmetadata&page[number]=223&page[size]=10",
        "prev": "http://api.resourcewatch.org/v1/dataset?includes=widget%2Cmetadata&page[number]=1&page[size]=10",
        "next": "http://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 http://api.resourcewatch.org/dataset?includes=layer

Loading the information about the user who authored the dataset

curl -X GET https://api.resourcewatch.org/v1/dataset?includes=user

When fetching datasets, you can request additional entities to be loaded. The following entities are available:

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"

Getting a dataset by slug:

curl -X GET "https://api.resourcewatch.org/v1/dataset/Timber-Production-RDC"

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": "http://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

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"  -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:

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:

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 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 "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 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.

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 "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 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 "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:

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 'Content-Type: application/json' -d \
'{
   "dataset": {
     "application": [
       "rw"
     ],
     "name": "Seasonal variability",
     "connectorType": "wms",
     "provider":"wms",
     "connectorUrl":"http://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:

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 "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 "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. http://gis-gfw.wri.org/arcgis/rest/services/prep/nex_gddp_indicators/MapServer/6?f=pjson
sources List of URLs from which to source data. [‘http://gis-gfw.wri.org/arcgis/rest/services/prep/nex_gddp_indicators/MapServer/6?f=pjson’,'http://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 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:

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>" \
-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 "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 is bad file type. - 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 "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:

Additionally, certain fields have special behavior associated with them:

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:

Use this endpoint when:

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 doesn’t exist 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 "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 "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 "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:

While they ultimately achieve a very similar end result, concatenate and append rely on different internal processes, each with its own characteristics.

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:

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 "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 "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:

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:

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 "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 request requires two fields to be present:

Additionally, you can optionally specify these fields:

For the fields in the following list, values will be copied from the original dataset to the new one, unless specified:

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 : can not be empty. 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 doesn’t exist A dataset with the provided id does not exist.

Deleting a dataset

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:

Example request for deleting a dataset

curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id> \
-H "Authorization: Bearer <your-token>"
-H "Content-Type: application/json"

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 doesn’t exist A dataset with the provided id does not exist.

Dataset automatic synchronization

curl -X POST https://api.resourcewatch.org/v1/dataset \
-H "Authorization: Bearer <your-token>" \
-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:

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/0c630feb-8146-4fcc-a9be-be5adcb731c8/flush \
-H "Authorization: Bearer <your-token>"

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:

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 doesn’t exist 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>"

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 doesn’t exist 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.
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.
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.

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>'

In order to query a dataset, you’ll need two pieces of information:

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'

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'

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>"

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'

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:

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'
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'

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'
curl -i -X POST 'https://api.resourcewatch.org/v1/query/9be3bf63-97fc-4bb0-b913-775ccae3cf9e' \
-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'

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'

curl -i -X POST 'https://api.resourcewatch.org/v1/query' \
-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'
curl -i -X GET 'https://api.resourcewatch.org/v1/query/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date FROM data limit 10'

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>'

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'

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:

Like when querying datasets, in order to download the results of the execution of query, you’ll need two pieces of information:

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'

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'

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 "Authorization: Bearer <your-token>"

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'

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:

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'
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'

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'
curl -i -X POST 'https://api.resourcewatch.org/v1/download/9be3bf63-97fc-4bb0-b913-775ccae3cf9e' \
-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'

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'

curl -i -X POST 'https://api.resourcewatch.org/v1/download' \
-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'
curl -i -X GET 'https://api.resourcewatch.org/v1/download/9be3bf63-97fc-4bb0-b913-775ccae3cf9e?sql=SELECT alert__date FROM data limit 10'

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'
curl -i -X GET 'https://api.resourcewatch.org/v1/query/:dataset_id?sql=DELETE FROM index_bf86b945c4ec41d2b5b7af00f3f61423 WHERE x = "y"'

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:

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

CartoDB datasets

This section describes the SQL support for querying datasets with provider cartodb.

Supported Feature Example URL
YES SELECT: Selecting all columns using wildcard SELECT * FROM edi LIMIT 5
YES SELECT: Count all rows SELECT count(*) FROM edi
YES SELECT: Selecting specific columns SELECT region, overall_score FROM edi LIMIT 5
YES SELECT: Selecting DISTINCT values for specific columns SELECT DISTINCT(region) FROM edi LIMIT 5
NO SELECT: Selecting columns AND counting all rows SELECT region, count(*) FROM edi LIMIT 5
YES SELECT: Aliasing aggregate function results such as AVG in SELECT SELECT AVG(overall_score) as alias FROM edi LIMIT 5
YES SELECT: Usage of aggregate functions (AVG) in SELECT SELECT AVG(overall_score) FROM edi LIMIT 5
YES SELECT: Usage of aggregate functions (MAX) in SELECT SELECT MAX(overall_score) FROM edi LIMIT 5
YES SELECT: Usage of aggregate functions (MIN) in SELECT SELECT MIN(overall_score) FROM edi LIMIT 5
YES SELECT: Usage of aggregate functions (SUM) in SELECT SELECT SUM(overall_score) FROM edi LIMIT 5
YES FROM: Using dataset id in FROM statement SELECT * FROM 0b9f0100-ce5b-430f-ad8f-3363efa05481 LIMIT 5
YES FROM: Using dataset slug in FROM statement SELECT * FROM Environmental-Democracy-Index-1490086842552 LIMIT 5
YES FROM: Using dataset tableName in FROM statement SELECT * FROM edi LIMIT 5
YES WHERE: Greater than filtering SELECT * FROM edi WHERE overall_score > 2 LIMIT 5
YES WHERE: Greater than or equal filtering SELECT * FROM edi WHERE overall_score >= 2 LIMIT 5
YES WHERE: Equality filtering SELECT * FROM edi WHERE overall_score = 2.1 LIMIT 5
YES WHERE: Lower than filtering SELECT * FROM edi WHERE overall_score < 2.2 LIMIT 5
YES WHERE: Lower than or equal filtering SELECT * FROM edi WHERE overall_score <= 2.2 LIMIT 5
YES WHERE: Conjunction (AND) filtering SELECT * FROM edi WHERE overall_score <= 2.2 AND justice_pillar_score > 1 LIMIT 5
YES WHERE: Disjunction (OR) filtering SELECT * FROM edi WHERE overall_score <= 2.2 OR justice_pillar_score > 1 LIMIT 5
YES WHERE: BETWEEN filtering SELECT * FROM edi WHERE overall_score BETWEEN 2 AND 2.2 LIMIT 5
YES WHERE: LIKE filtering SELECT * FROM edi WHERE region LIKE ‘Europ%’ LIMIT 5
YES GROUP BY: Group results by a single column SELECT region FROM edi GROUP BY region LIMIT 5
YES GROUP BY: Group results by multiple columns SELECT region, overall_score FROM edi GROUP BY region, overall_score LIMIT 5
YES GROUP BY: Aggregate functions used with GROUP BY statements SELECT region, COUNT(*) as count FROM edi GROUP BY region LIMIT 5
NO GROUP BY: Special grouping by range function SELECT count(*) FROM edi GROUP BY range(overall_score, 0,1,2,3,4) LIMIT 5
YES ORDER BY: Ordering results by one column SELECT region FROM edi ORDER BY region LIMIT 5
YES ORDER BY: Ordering results by one column descending SELECT region FROM edi ORDER BY region DESC LIMIT 5
YES ORDER BY: Ordering results by multiple column SELECT region, overall_score FROM edi ORDER BY region, overall_score LIMIT 5
YES ORDER BY: Ordering results by multiple column descending SELECT region, overall_score FROM edi ORDER BY region, overall_score DESC LIMIT 5
YES LIMIT: Limit the number of returned results SELECT region FROM edi LIMIT 5
NO OFFSET: Offset the returned results SELECT region FROM edi LIMIT 5 OFFSET 10
NO OFFSET: Offset the returned results using short syntax SELECT region FROM edi LIMIT 5, 10

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

ArcGIS Feature Service datasets

This section describes the SQL support for querying datasets with connector type rest and provider featureservice.

Supported Feature Example URL
YES SELECT: Selecting all columns using wildcard SELECT * FROM cdonexradMapServer0 LIMIT 5
YES SELECT: Count all rows SELECT count(*) FROM cdonexradMapServer0
YES SELECT: Selecting specific columns SELECT STATION_NAME, ELEVATION FROM cdonexradMapServer0 LIMIT 5
NO SELECT: Selecting DISTINCT values for specific columns SELECT DISTINCT(STATION_NAME) FROM cdonexradMapServer0 LIMIT 5
NO SELECT: Selecting columns AND counting all rows SELECT STATION_NAME, count(*) FROM cdonexradMapServer0 LIMIT 5
YES SELECT: Aliasing aggregate function results such as AVG in SELECT SELECT AVG(ELEVATION) as alias FROM cdonexradMapServer0 LIMIT 5
YES SELECT: Usage of aggregate functions (AVG) in SELECT SELECT AVG(ELEVATION) FROM cdonexradMapServer0 LIMIT 5
YES SELECT: Usage of aggregate functions (MAX) in SELECT SELECT MAX(ELEVATION) FROM cdonexradMapServer0 LIMIT 5
YES SELECT: Usage of aggregate functions (MIN) in SELECT SELECT MIN(ELEVATION) FROM cdonexradMapServer0 LIMIT 5
YES SELECT: Usage of aggregate functions (SUM) in SELECT SELECT SUM(ELEVATION) FROM cdonexradMapServer0 LIMIT 5
YES FROM: Using dataset id in FROM statement SELECT * FROM 0b9e546c-f42a-4b26-bad3-7d606f58961c LIMIT 5
YES FROM: Using dataset slug in FROM statement SELECT * FROM NOAA-NEXt-Generation-RADar-NEXRAD-Products-Locations-1490086842546 LIMIT 5
YES FROM: Using dataset tableName in FROM statement SELECT * FROM cdonexradMapServer0 LIMIT 5
YES WHERE: Greater than filtering SELECT * FROM cdonexradMapServer0 WHERE ELEVATION > 3587 LIMIT 5
YES WHERE: Greater than or equal filtering SELECT * FROM cdonexradMapServer0 WHERE ELEVATION >= 3587 LIMIT 5
YES WHERE: Equality filtering SELECT * FROM cdonexradMapServer0 WHERE ELEVATION = 5870 LIMIT 5
YES WHERE: Lower than filtering SELECT * FROM cdonexradMapServer0 WHERE ELEVATION < 5000 LIMIT 5
YES WHERE: Lower than or equal filtering SELECT * FROM cdonexradMapServer0 WHERE ELEVATION <= 5000 LIMIT 5
YES WHERE: Conjunction (AND) filtering SELECT * FROM cdonexradMapServer0 WHERE ELEVATION <= 5000 AND LATITUDE > 35.23333 LIMIT 5
YES WHERE: Disjunction (OR) filtering SELECT * FROM cdonexradMapServer0 WHERE ELEVATION <= 5000 OR LATITUDE > 35.23333 LIMIT 5
YES WHERE: BETWEEN filtering SELECT * FROM cdonexradMapServer0 WHERE ELEVATION BETWEEN 3587 AND 5000 LIMIT 5
YES WHERE: LIKE filtering SELECT * FROM cdonexradMapServer0 WHERE STATION_NAME LIKE 'AMARI%’ LIMIT 5
YES GROUP BY: Group results by a single column SELECT STATION_NAME FROM cdonexradMapServer0 GROUP BY STATION_NAME LIMIT 5
YES GROUP BY: Group results by multiple columns SELECT STATION_NAME, ELEVATION FROM cdonexradMapServer0 GROUP BY STATION_NAME, ELEVATION LIMIT 5
NO GROUP BY: Aggregate functions used with GROUP BY statements SELECT STATION_NAME, COUNT(*) as count FROM cdonexradMapServer0 GROUP BY STATION_NAME LIMIT 5
YES GROUP BY: Special grouping by range function SELECT count(*) FROM cdonexradMapServer0 GROUP BY range(ELEVATION, 0,1,2,3,4) LIMIT 5
YES ORDER BY: Ordering results by one column SELECT STATION_NAME FROM cdonexradMapServer0 ORDER BY STATION_NAME LIMIT 5
YES ORDER BY: Ordering results by one column descending SELECT STATION_NAME FROM cdonexradMapServer0 ORDER BY STATION_NAME DESC LIMIT 5
YES ORDER BY: Ordering results by multiple column SELECT STATION_NAME, ELEVATION FROM cdonexradMapServer0 ORDER BY STATION_NAME, ELEVATION LIMIT 5
YES ORDER BY: Ordering results by multiple column descending SELECT STATION_NAME, ELEVATION FROM cdonexradMapServer0 ORDER BY STATION_NAME, ELEVATION DESC LIMIT 5
YES LIMIT: Limit the number of returned results SELECT STATION_NAME FROM cdonexradMapServer0 LIMIT 5
YES OFFSET: Offset the returned results SELECT STATION_NAME FROM cdonexradMapServer0 LIMIT 5 OFFSET 10
NO OFFSET: Offset the returned results using short syntax SELECT STATION_NAME FROM cdonexradMapServer0 LIMIT 5, 10

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.

Supported Feature Example URL
YES SELECT: Selecting all columns using wildcard SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
YES SELECT: Count all rows SELECT count(*) FROM users/resourcewatch_wri/foo_024_vegetation_health_index
YES SELECT: Selecting specific columns SELECT system:index, system:asset_size FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
NO SELECT: Selecting DISTINCT values for specific columns SELECT DISTINCT(system:index) FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
YES SELECT: Selecting columns AND counting all rows SELECT system:index, count(*) FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
NO SELECT: Aliasing aggregate function results such as AVG in SELECT SELECT AVG(system:asset_size) as alias FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
YES SELECT: Usage of aggregate functions (AVG) in SELECT SELECT AVG(system:asset_size) FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
YES SELECT: Usage of aggregate functions (MAX) in SELECT SELECT MAX(system:asset_size) FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
YES SELECT: Usage of aggregate functions (MIN) in SELECT SELECT MIN(system:asset_size) FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
YES SELECT: Usage of aggregate functions (SUM) in SELECT SELECT SUM(system:asset_size) FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
NO FROM: Using dataset id in FROM statement SELECT * FROM c12446ce-174f-4ffb-b2f7-77ecb0116aba LIMIT 5
NO FROM: Using dataset slug in FROM statement SELECT * FROM foo024nrt-Vegetation-Health-Index_replacement_4 LIMIT 5
YES FROM: Using dataset tableName in FROM statement SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
YES WHERE: Greater than filtering SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index WHERE system:asset_size > 36975655 LIMIT 5
YES WHERE: Greater than or equal filtering SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index WHERE system:asset_size >= 36975655 LIMIT 5
YES WHERE: Equality filtering SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index WHERE system:asset_size = 37153685 LIMIT 5
YES WHERE: Lower than filtering SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index WHERE system:asset_size < 37180450 LIMIT 5
YES WHERE: Lower than or equal filtering SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index WHERE system:asset_size <= 37180450 LIMIT 5
NO WHERE: Conjunction (AND) filtering SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index WHERE system:asset_size <= 37180450 AND system:time_start > 1572739200000 LIMIT 5
NO WHERE: Disjunction (OR) filtering SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index WHERE system:asset_size <= 37180450 OR system:time_start > 1572739200000 LIMIT 5
NO WHERE: BETWEEN filtering SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index WHERE system:asset_size BETWEEN 36975655 AND 37180450 LIMIT 5
NO WHERE: LIKE filtering SELECT * FROM users/resourcewatch_wri/foo_024_vegetation_health_index WHERE system:index LIKE 'foo_024_vegetation_health_index%’ LIMIT 5
NO GROUP BY: Group results by a single column SELECT system:index FROM users/resourcewatch_wri/foo_024_vegetation_health_index GROUP BY system:index LIMIT 5
NO GROUP BY: Group results by multiple columns SELECT system:index, system:asset_size FROM users/resourcewatch_wri/foo_024_vegetation_health_index GROUP BY system:index, system:asset_size LIMIT 5
NO GROUP BY: Aggregate functions used with GROUP BY statements SELECT system:index, COUNT(*) as count FROM users/resourcewatch_wri/foo_024_vegetation_health_index GROUP BY system:index LIMIT 5
NO GROUP BY: Special grouping by range function SELECT count(*) FROM users/resourcewatch_wri/foo_024_vegetation_health_index GROUP BY range(system:asset_size, 0,1,2,3,4) LIMIT 5
NO ORDER BY: Ordering results by one column SELECT system:index FROM users/resourcewatch_wri/foo_024_vegetation_health_index ORDER BY system:index LIMIT 5
NO ORDER BY: Ordering results by one column descending SELECT system:index FROM users/resourcewatch_wri/foo_024_vegetation_health_index ORDER BY system:index DESC LIMIT 5
NO ORDER BY: Ordering results by multiple column SELECT system:index, system:asset_size FROM users/resourcewatch_wri/foo_024_vegetation_health_index ORDER BY system:index, system:asset_size LIMIT 5
NO ORDER BY: Ordering results by multiple column descending SELECT system:index, system:asset_size FROM users/resourcewatch_wri/foo_024_vegetation_health_index ORDER BY system:index, system:asset_size DESC LIMIT 5
YES LIMIT: Limit the number of returned results SELECT system:index FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5
YES OFFSET: Offset the returned results SELECT system:index FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5 OFFSET 10
NO OFFSET: Offset the returned results using short syntax SELECT system:index FROM users/resourcewatch_wri/foo_024_vegetation_health_index LIMIT 5, 10

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.

Supported Feature Example URL
YES SELECT: Selecting all columns using wildcard SELECT * FROM data LIMIT 5
YES SELECT: Count all rows SELECT count(*) FROM data
YES SELECT: Selecting specific columns SELECT bra_biome__name, alert__count FROM data LIMIT 5
NO SELECT: Selecting DISTINCT values for specific columns SELECT DISTINCT(bra_biome__name) FROM data LIMIT 5
YES SELECT: Selecting columns AND counting all rows SELECT bra_biome__name, count(*) FROM data LIMIT 5
YES SELECT: Aliasing aggregate function results such as AVG in SELECT SELECT AVG(alert__count) as alias FROM data LIMIT 5
YES SELECT: Usage of aggregate functions (AVG) in SELECT SELECT AVG(alert__count) FROM data LIMIT 5
YES SELECT: Usage of aggregate functions (MAX) in SELECT SELECT MAX(alert__count) FROM data LIMIT 5
YES SELECT: Usage of aggregate functions (MIN) in SELECT SELECT MIN(alert__count) FROM data LIMIT 5
YES SELECT: Usage of aggregate functions (SUM) in SELECT SELECT SUM(alert__count) FROM data LIMIT 5
YES FROM: Using dataset id in FROM statement SELECT * FROM 9be3bf63-97fc-4bb0-b913-775ccae3cf9e LIMIT 5
YES FROM: Using dataset slug in FROM statement SELECT * FROM Glad-Alerts-Daily-Geostore-User-Areas_3 LIMIT 5
YES FROM: Using dataset tableName in FROM statement SELECT * FROM data LIMIT 5
YES WHERE: Greater than filtering SELECT * FROM data WHERE alert__count > 2 LIMIT 5
YES WHERE: Greater than or equal filtering SELECT * FROM data WHERE alert__count >= 2 LIMIT 5
YES WHERE: Equality filtering SELECT * FROM data WHERE alert__count = 5 LIMIT 5
YES WHERE: Lower than filtering SELECT * FROM data WHERE alert__count < 8 LIMIT 5
YES WHERE: Lower than or equal filtering SELECT * FROM data WHERE alert__count <= 8 LIMIT 5
YES WHERE: Conjunction (AND) filtering SELECT * FROM data WHERE alert__count <= 8 AND alert_area__ha > 0.1 LIMIT 5
YES WHERE: Disjunction (OR) filtering SELECT * FROM data WHERE alert__count <= 8 OR alert_area__ha > 0.1 LIMIT 5
YES WHERE: BETWEEN filtering SELECT * FROM data WHERE alert__count BETWEEN 2 AND 8 LIMIT 5
NO WHERE: LIKE filtering SELECT * FROM data WHERE bra_biome__name LIKE 'Amaz%’ LIMIT 5
YES GROUP BY: Group results by a single column SELECT bra_biome__name FROM data GROUP BY bra_biome__name LIMIT 5
YES GROUP BY: Group results by multiple columns SELECT bra_biome__name, alert__count FROM data GROUP BY bra_biome__name, alert__count LIMIT 5
YES GROUP BY: Aggregate functions used with GROUP BY statements SELECT bra_biome__name, COUNT(*) as count FROM data GROUP BY bra_biome__name LIMIT 5
YES GROUP BY: Special grouping by range function SELECT count(*) FROM data GROUP BY range(alert__count, 0,1,2,3,4) LIMIT 5
YES ORDER BY: Ordering results by one column SELECT bra_biome__name FROM data ORDER BY bra_biome__name LIMIT 5
YES ORDER BY: Ordering results by one column descending SELECT bra_biome__name FROM data ORDER BY bra_biome__name DESC LIMIT 5
YES ORDER BY: Ordering results by multiple column SELECT bra_biome__name, alert__count FROM data ORDER BY bra_biome__name, alert__count LIMIT 5
YES ORDER BY: Ordering results by multiple column descending SELECT bra_biome__name, alert__count FROM data ORDER BY bra_biome__name, alert__count DESC LIMIT 5
YES LIMIT: Limit the number of returned results SELECT bra_biome__name FROM data LIMIT 5
YES OFFSET: Offset the returned results SELECT bra_biome__name FROM data LIMIT 5 OFFSET 10
NO OFFSET: Offset the returned results using short syntax SELECT bra_biome__name FROM data LIMIT 5, 10

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:

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 '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'

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'

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:

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"

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"

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 '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 or prep applications

curl -X POST "https://api.resourcewatch.org/layer/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-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 and prep applications simultaneously

curl -X POST "https://api.resourcewatch.org/layer/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-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:

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

By default, layers are listed in pages of 10 layers each, and the first page is loaded. However, you can customize this behavior using the following query parameters:

Custom pagination: load page 2 using 25 results per page

curl -X GET "https://api.resourcewatch.org/v1/layer?page[number]=2&page[size]=25"
Field Description Type Default
page[size] The number elements per page. Values above 100 are not officially supported. Number 10
page[number] The page number Number 1

Filters

Return the layers filtered by those whose name contains emissions

curl -X GET "https://api.resourcewatch.org/v1/layer?name=emissions"

Return the layers filtered by dataset

curl -X GET "https://api.resourcewatch.org/v1/layer?dataset=11de2bc1-368b-42ed-a207-aaff8ece752b"
curl -X GET "https://api.resourcewatch.org/v1/dataset/11de2bc1-368b-42ed-a207-aaff8ece752b/layer"

Filter layers by published status

curl -X GET "https://api.resourcewatch.org/v1/layer?published=false"

Filter layers by environment

curl -X GET "https://api.resourcewatch.org/v1/layer?env=staging"

Return the layers filtered by those whose applications contain rw

curl -X GET "https://api.resourcewatch.org/v1/layer?app=rw"

The layer list endpoints provide a wide range of filters that you can use to tailor your layer listing. The great majority of the layer fields you’ll find on the layer reference section can be used as filters when listing layers, with the following exceptions:

Additionally, you can use the following filters:

Multiple parameters can be combined into a complex and logic filter. Depending on the type of the field you’re filtering by, the following behavior is available:

Sorting

The API currently supports sorting by means of the sort parameter. Sorting can be done using any field from the layer, as well as user.name and user.role (sorting by user data is restricted to ADMIN users).

Sorting by nested fields is not supported at the moment.

Sorting layers

curl -X GET "https://api.resourcewatch.org/v1/layer?sort=name"

Multiple sorting criteria can be used, separating them by commas.

Sorting layers by multiple criteria

curl -X GET "https://api.resourcewatch.org/v1/layer?sort=name,slug"

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.

Explicit order of sorting

curl -X GET "https://api.resourcewatch.org/v1/layer?sort=-name,+slug"

Sorting layers by the role of the user who owns the layer

curl -X GET "https://api.resourcewatch.org/v1/layer?sort=user.role"

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"

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 getting vocabularies associated to a resource 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.

curl -X GET "https://api.resourcewatch.org/v1/layer?includes=user"

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"

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>"
curl -X GET "https://api.resourcewatch.org/v1/layer/<layer_id>"

Getting a layer by slug:

curl -X GET "https://api.resourcewatch.org/v1/dataset/<dataset_id>/layer/<layer_slug>"
curl -X GET "https://api.resourcewatch.org/v1/layer/<layer_slug>"

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>" \
-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:

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:

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.

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 "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:

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 doesn’t exist 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 "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:

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 doesn’t exist A layer with the provided id does not exist.

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.
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.
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 uploading 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"

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"

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": "http://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959/widget?page[number]=1&page[size]=10",
        "first": "http://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959/widget?page[number]=1&page[size]=10",
        "last": "http://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959/widget?page[number]=2&page[size]=10",
        "prev": "http://api.resourcewatch.org/v1/dataset/06c44f9a-aae7-401e-874c-de13b7764959/widget?page[number]=1&page[size]=10",
        "next": "http://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 '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 or prep applications

curl -X POST "https://api.resourcewatch.org/widget/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-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 and prep applications simultaneously

curl -X POST "https://api.resourcewatch.org/widget/find-by-ids" \
-H "Authorization: Bearer <your-token>" \
-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:

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

By default, widgets are listed in pages of 10 widgets each, and the first page is loaded. However, you can customize this behavior using the following query parameters:

Custom pagination: load page 2 using 25 results per page

curl -X GET "https://api.resourcewatch.org/v1/widget?page[number]=2&page[size]=25"
Field Description Type Default
page[size] The number elements per page. Values above 100 are not officially supported. Number 10
page[number] The page number Number 1

Filters

Return the widgets filtered by those whose name contains emissions

curl -X GET "https://api.resourcewatch.org/v1/widget?name=emissions"

Return the widgets filtered by dataset

curl -X GET "https://api.resourcewatch.org/v1/widget?dataset=11de2bc1-368b-42ed-a207-aaff8ece752b"
curl -X GET "https://api.resourcewatch.org/v1/dataset/11de2bc1-368b-42ed-a207-aaff8ece752b/widget"

Filter widgets by default value

curl -X GET "https://api.resourcewatch.org/v1/widget?default=false"

Filter widgets by environment

curl -X GET "https://api.resourcewatch.org/v1/widget?env=staging"

Return the widgets filtered by those whose applications contain both rw and prep applications simultaneously

curl -X GET "https://api.resourcewatch.org/v1/widget?app=rw@prep"

The widget list endpoints provide a wide range of filters that you can use to tailor your widget listing. The great majority of the widget fields you’ll find on the widget reference section can be used as filters when listing widgets, with the following exceptions:

Additionally, you can use the following filters:

Multiple parameters can be combined into a complex and logic filter. Depending on the type of the field you’re filtering by, the following behavior is available:

Sorting

The API currently supports sorting by means of the sort parameter. Sorting can be done using any field from the widget, as well as user.name and user.role (sorting by user data is restricted to ADMIN users).

Sorting by nested fields is not supported at the moment.

Sorting widgets

curl -X GET "https://api.resourcewatch.org/v1/widget?sort=name"

Multiple sorting criteria can be used, separating them by commas.

Sorting widgets by multiple criteria

curl -X GET "https://api.resourcewatch.org/v1/widget?sort=name,slug"

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.

Explicit order of sorting

curl -X GET "https://api.resourcewatch.org/v1/widget?sort=-name,+slug"

Sorting widgets by the role of the user who owns the widget

curl -X GET "https://api.resourcewatch.org/v1/widget?sort=user.role"

Include entities associated with the widgets

When loading widget data, you can optionally pass an includes query argument to load additional data.

Vocabulary

Loads related vocabularies. If none are found, an empty array is returned.

curl -X GET "https://api.resourcewatch.org/v1/widget?includes=vocabulary"

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"
                        }
                    }
                ]
            }
        }
    ]
}

User

curl -X GET "https://api.resourcewatch.org/v1/widget?includes=user"

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.

Metadata

curl -X GET "https://api.resourcewatch.org/v1/widget?includes=metadata"

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"

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>"
curl -X GET "https://api.resourcewatch.org/v1/dataset/<dataset_id>/widget/<widget_id>"

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"

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:

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"

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"

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:

The widget service assumes these values are URLs, and will append your custom query parameters as such:

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 "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 "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:

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:

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>"

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 "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 "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:

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 doesn’t exist 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 "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 "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:

To perform this operation, the following conditions must be met:

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 "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 "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 doesn’t exist 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 "Content-Type: application/json"


curl -X DELETE "https://api.resourcewatch.org/v1/widget/<widget_id>" \
-H "Authorization: Bearer <your-token>" \
-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:

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.
widgetConfig Object No Schema-less object meant to host widget behavior configuration.
application Array Yes Applications associated with this widget.
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.

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 "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 "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 "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

Fields

What are fields?

Fields can be defined as the dataset properties. These fields are automatically generated when a dataset is created.

How to get the dataset fields

Once the dataset is properly created and saved, it is possible to access to its fields as well as getting some information about them.

To do that, it is necessary to use of the following endpoint:

curl -X GET https://api.resourcewatch.org/v1/fields/<dataset-id>

Real example

curl -X GET https://api.resourcewatch.org/v1/fields/1170030b-9725-4bfe-8fb4-1b0eb81020d2

Response

{
    "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"
        }
    }
}

Rasdaman

The structure of datacubes needs a more verbose field specification. The fields endpoint for rasdaman-backed datasets includes information on the spatial reference system, nodata values, axes, units, and bands. It looks like so:

Example

curl -i  -XGET 'http://api.resourcewatch.org/v1/fields/491ae6fe-6767-44d1-b5c3-c7b8b384bb7a'

Response

{
  "coverageId": "nightlights",
  "srs": {
    "srsDimension": "2",
    "srs": "crs/EPSG/0/4326"
  },
  "axisLabels": "Lat Long",
  "uomLabels": "degree degree",
  "fields": {
    "undefined": {
      "swe:nilValues": {
        "swe:NilValues": {
          "swe:nilValue": [
            {
              "reason": "",
              "$t": "1"
            },
            {
              "reason": "",
              "$t": "2"
            }
          ]
        }
      },
      "swe:uom": {
        "code": "10^0"
      }
    }
  },
  "coverageBounds": {
    "upperCorner": "89.999999999966665 180.000000000189335",
    "lowerCorner": "-89.999999999961335 -179.999999999666665"
  }
}

Metadata

Metadata definition

Metadata is data concerning another resource available on this API. It only exists when associated with another resource - currently supported resource types are datasets, widgets or layers. Note that, although there might be several metadata per resource, each resource will have - at most - one metadata element per application and language pair. As such, the application and language attributes are required and it is mandatory to include them in when creating/updating metadata.

Some fields are important to identify the entity properly; others are just optional and give extra information about it.

Field Description Type
application The metadata application String
language The metadata language String
dataset The associated dataset id to the metadata String
resource The resource associated to the metadata Object
– id Resource id String
– type Resource type String
name The metadata name String
description The metadata description String
source The metadata source String
citation The metadata citation String
license The metadata license type String
info Some info about the metadata Object
units Measurement units Object

Creating a metadata object

As previously discussed, a metadata entity is always associated with either a dataset, a widget or a layer resource, and the type of resource it is associated to dictates which of 3 endpoints you should use when creating a new metadata entity.

In all scenarios, you must be authenticated to be able to create a metadata entity, and meet the following requirements:

Any of these conditions are not met, the API will generate a 403 Forbidden error message.

Field Required/Optional
application required
language required
dataset required
name optional
description optional
source optional
citation optional
license optional
info optional
units optional

Create metadata for a dataset

curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata \
-H "Content-Type: application/json"  -d \
 '{
   "application": <app>,
   "language": <language>
  }'

Create metadata for a widget

curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/metadata \
-H "Content-Type: application/json"  -d \
 '{
   "application": <app>,
   "language": <language>
  }'

Create metadata for a layer

curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/metadata \
-H "Content-Type: application/json"  -d \
 '{
   "application": <app>,
   "language": <language>
  }'

Real example

curl -X POST https://api.resourcewatch.org/v1/dataset/942b3f38-9504-4273-af51-0440170ffc86/metadata \
-H "Content-Type: application/json"  -d \
 '{
   "application": "rw",
   "language": "en"
  }'

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",
        "createdAt": "2017-01-20T08:07:53.272Z",
        "updatedAt": "2017-01-20T08:07:53.272Z",
        "status": "published"
      }
    }
  ]
}

Getting metadata

application filter: application: gfw, gfw-climate, prep, rw, forest-atlas (select one or some of them)

language filter: language: select between available languages (select one or some of them)

limit filter: limit: the desired number

Custom param for /metadata endpoint: type: [dataset, widget, layer]

curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata
curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/metadata
curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/metadata

Real example

curl -X GET https://api.resourcewatch.org/v1/dataset/942b3f38-9504-4273-af51-0440170ffc86/metadata

Updating a metadata

As previously discussed, a metadata entity is always associated with either a dataset, a widget or a layer resource, and the type of resource it is associated to dictates which of 3 endpoints you should use when updating a metadata entity.

In all scenarios, you must be authenticated to be able to update a metadata entity, and meet the following requirements:

Any of these conditions are not met, the API will generate a 403 Forbidden error message.

When updating a metadata, you must always specify both language and application, those will be used to determine which metadata entity will be updated.

Update metadata for a dataset

curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata \
-H "Content-Type: application/json"  -d \
 '{
   "application": <app>,
   "language": <language>
  }'

Update metadata for a widget

curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>metadata \
-H "Content-Type: application/json"  -d \
 '{
   "application": <app>,
   "language": <language>
  }'

Update metadata for a layer

curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>metadata \
-H "Content-Type: application/json"  -d \
 '{
   "application": <app>,
   "language": <language>
  }'

Real example

curl -X PATCH https://api.resourcewatch.org/v1/dataset/942b3f38-9504-4273-af51-0440170ffc86/metadata \
-H "Content-Type: application/json"  -d \
 '{
   "application": "rw",
   "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"
   }
  }'

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"
      }
    }
  ]
}

Deleting a metadata

As previously discussed, a metadata entity is always associated with either a dataset, a widget or a layer resource, and the type of resource it is associated to dictates which of 3 endpoints you should use when deleting a metadata entity.

In all scenarios, you must be authenticated to be able to delete a metadata entity, and meet the following requirements:

Any of these conditions are not met, the API will generate a 403 Forbidden error message.

When deleting a metadata, you must always specify both language and application, those will be used to determine which metadata entity will be deleted.

Delete metadata for a dataset

curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/metadata?application=<app-id>&language=<language>

Delete metadata for a widget

curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/metadata?application=<app-id>&language=<language>

Delete metadata for a layer

curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/metadata?application=<app-id>&language=<language>

Real example

curl -X DELETE https://api.resourcewatch.org/v1/dataset/942b3f38-9504-4273-af51-0440170ffc86/metadata?application=rw&language=en \

Getting all

curl -X GET https://api.resourcewatch.org/v1/metadata

Real examples

curl -X GET https://api.resourcewatch.org/v1/metadata
curl -X GET https://api.resourcewatch.org/v1/metadata?type=dataset
curl -X GET https://api.resourcewatch.org/v1/metadata?type=widget
curl -X GET https://api.resourcewatch.org/v1/metadata?application=rw&language=es,en&limit=20
curl -X GET https://api.resourcewatch.org/v1/metadata?application=rw,gfw&language=en&type=dataset
curl -X GET https://api.resourcewatch.org/v1/metadata?language=en

Finding metadata by ids

The ids property is required in the body of the request. It can be either an array of ids or a string of comma-separated ids:

Filters

The metadata list provided by the endpoint can be filtered with the following attributes:

Filter Description Accepted values
application Application associated with the metadata entity any valid text
language Language of the metadata entity any valid text

Finding metadata by ids for a dataset

curl -X POST https://api.resourcewatch.org/v1/dataset/metadata/find-by-ids \
-H "Content-Type: application/json"  -d \
 '{
   "ids": [<ids>]
  }'

Finding metadata by ids for a widget

curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset/widget/metadata/find-by-ids \
-H "Content-Type: application/json"  -d \
 '{
   "ids": [<ids>]
  }'

Finding metadata by ids for a layer

curl -X POST https://api.resourcewatch.org/v1/dataset/:dataset/layer/metadata/find-by-ids \
-H "Content-Type: application/json"  -d \
 '{
   "ids": [<ids>]
  }'

Real example

curl -X POST https://api.resourcewatch.org/v1/dataset/metadata/find-by-ids \
-H "Content-Type: application/json"  -d \
 '{
     "ids": "b000288d-7037-43ba-aa34-165eab549613, 942b3f38-9504-4273-af51-0440170ffc86"
  }'

Response

{
  "data": [
    {
      "id": "b000288d-7037-43ba-aa34-165eab549613-dataset-b000288d-7037-43ba-aa34-165eab549613-prep-en",
      "type": "metadata",
      "attributes": {
        "dataset": "b000288d-7037-43ba-aa34-165eab549613",
        "application": "prep",
        "resource": {
          "type": "dataset",
          "id": "b000288d-7037-43ba-aa34-165eab549613"
        },
        "language": "en",
        "name": "Projected temperature change",
        "description": "The Puget Sound region is projected to warm rapidly during the 21st century. Prior to mid-century, the projected increase in air temperatures is about the same for all greenhouse gas scenarios, a result of the fact that a certain amount of warming is already “locked in” due to past emissions. After about 2050, projected warming depends on the amount of greenhouse gases emitted globally in the coming decades. For the 2050s (2040-2069, relative to 1970-1999), annual average air temperature is projected to rise +4.2°F to +5.9°F, on average, for a low (RCP 4.5) and a high (RCP 8.5) greenhouse gas scenario. These indicators are derived from the Multivariate Adaptive Constructed Analogs (MACA) CMIP5 Future Climate Dataset from the University of Idaho. For more information about this analysis, please see http://cses.washington.edu/picea/mauger/ps-sok/ps-sok_sec12_builtenvironment_2015.pdf. For more information about the MACA CMIP5 Future Climate Dataset please see http://maca.northwestknowledge.net/index.php",
        "source": "http://maca.northwestknowledge.net",
        "citation": "Abatzoglou, J. T.,   Brown, T. J. 2012. A comparison of statistical downscaling methods suited for wildfire applications. International Journal of Climatology, 32(5), 772-780. doi: http://dx.doi.org/10.1002/joc.2312 ",
        "license": "Public domain",
        "info": {
          "organization": "Joe Casola, University of Washington",
          "license": "Public domain",
          "source": "http://maca.northwestknowledge.net",
          "citation": "Abatzoglou, J. T.,   Brown, T. J. 2012. A comparison of statistical downscaling methods suited for wildfire applications. International Journal of Climatology, 32(5), 772-780. doi: http://dx.doi.org/10.1002/joc.2312 ",
          "description": "The Puget Sound region is projected to warm rapidly during the 21st century. Prior to mid-century, the projected increase in air temperatures is about the same for all greenhouse gas scenarios, a result of the fact that a certain amount of warming is already “locked in” due to past emissions. After about 2050, projected warming depends on the amount of greenhouse gases emitted globally in the coming decades. For the 2050s (2040-2069, relative to 1970-1999), annual average air temperature is projected to rise +4.2°F to +5.9°F, on average, for a low (RCP 4.5) and a high (RCP 8.5) greenhouse gas scenario. These indicators are derived from the Multivariate Adaptive Constructed Analogs (MACA) CMIP5 Future Climate Dataset from the University of Idaho. For more information about this analysis, please see http://cses.washington.edu/picea/mauger/ps-sok/ps-sok_sec12_builtenvironment_2015.pdf. For more information about the MACA CMIP5 Future Climate Dataset please see http://maca.northwestknowledge.net/index.php",
          "short-description": "Projected temperature change in the Puget Sound Lowlands relative to average temperature between 1950-2005. Light colored lines in the background show the range of projections. All climate scenarios project warming for the Puget Sound region during the 21st century.",
          "subtitle": "",
          "title": "Projected temperature change"
        },
        "createdAt": "2016-12-13T10:02:28.337Z",
        "updatedAt": "2016-12-13T10:03:02.445Z",
        "status": "published"
      }
    },
    {
      "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": {
          "link": "http://www.forbes.com/sites/louiscolumbus/2016/03/13/roundup-of-cloud-computing-forecasts-and-market-estimates-2016/#5875cf0074b0",
          "date": "MAR 13, 2016 @ 10:42 PM",
          "author": "Louis Columbus",
          "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)."
        },
        "createdAt": "2017-01-20T08:07:53.272Z",
        "updatedAt": "2017-01-20T08:40:30.190Z",
        "status": "published"
      }
    }
  ]
}

Vocabulary (and Tags)

Resource definition

A Resource represents an external entity that will be related with a Vocabulary. The most common resources used when creating relationships with vocabulary are datasets, layers and widgets.

Tags definition

A Tag is a way to categorize a resource within a vocabulary context.

Vocabulary definition

The Vocabulary can be described as a cluster of tags.

It is currently possible to just create a Vocabulary without any tags or relationships. To do it, the only parameter that is required is the name of the Vocabulary.

Field Description Type
name The name of the Vocabulary (it has to be unique and it represents the “primaryKey”) String
application The associated application for this vocabulary String

However, the most common use case relies on the relationships creation.

Relationships

This section describes how to associate an existing or new Vocabulary to a resource.

Some important points:

Creating a Vocabulary-Resource relationship

To create a relationship between a Resource and a Vocabulary (even if the Vocabulary or the Resource doesn’t exist yet) it is only required that you set the tags that define the relationship.

Some writing operations can take a little more time than reading ones. Even if the relationships are not strong, the writing operations have to ensure consistency along entities.

Remember that you can create relationshipts between Vocabulary and datasets, widgets or layers (the supported Resources).

Creating a relationship between a Vocabulary and a Dataset

curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary/<vocabulary-id> \
-H "Content-Type: application/json"  -d \
 '{
 "application": <application>,
   "tags": [<tags>]
  }'

Creating a relationship between a Vocabulary and a Widget

curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary/<vocabulary-id> \
-H "Content-Type: application/json"  -d \
 '{
 "application": <application>,
   "tags": [<tags>]
  }'

Creating a relationship between a Vocabulary and a Layer

curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary/<vocabulary-id> \
-H "Content-Type: application/json"  -d \
 '{
 "application": <application>,
   "tags": [<tags>]
  }'

Example of request with real data

curl -X POST https://api.resourcewatch.org/v1/dataset/942b3f38-9504-4273-af51-0440170ffc86/vocabulary/science
-H "Content-Type: application/json"  -d \
 '{
 "application": <application>,
   "tags": ["biology", "chemistry"]
  }'

Example of response with real data

{
  "data": [
    {
      "id": "vocabularyNameOne",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "tag1",
          "tag2",
          "tag3"
        ]
      }
    },
    {
      "id": "science",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "biology",
          "chemistry"
        ]
      }
    },
    {
      "id": "aaa",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "biology",
          "chemistry"
        ]
      }
    }
  ]
}

Updating an existing Vocabulary-Resource relationship

If a relationship has to be updated, it’s necessary to define it’s new tags. The previous tags will be deleted in benefit of the new ones.

Updating a relationship between a Vocabulary and a Dataset

curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary/<vocabulary-id> \
-H "Content-Type: application/json"  -d \
 '{
 "application": <application>,
   "tags": [<tags>]
  }'

Updating a relationship between a Vocabulary and a Widget

curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary/<vocabulary-id> \
-H "Content-Type: application/json"  -d \
 '{
 "application": <application>,
   "tags": [<tags>]
  }'

Updating a relationship between a Vocabulary and a Layer

curl -X PATCH https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary/<vocabulary-id> \
-H "Content-Type: application/json"  -d \
 '{
 "application": <application>,
   "tags": [<tags>]
  }'

Example of request with real data

curl -X PATCH https://api.resourcewatch.org/v1/dataset/942b3f38-9504-4273-af51-0440170ffc86/vocabulary/science
-H "Content-Type: application/json"  -d \
 '{
 "application": <application>,
   "tags": ["maths", "astronomy"]
  }'

Example of response with real data

{
  "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"
        ]
      }
    }
  ]
}

Creating several Vocabulary-Resource relationships

There is also an endpoint that allows you to create multiple relationships in the same request.

Creating multiple relationships between a Vocabulary and a Dataset

curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary \
-H "Content-Type: application/json"  -d \
 '{
   "vocabularyOne": {
   "application": <application>,
       "tags": [<tags>]
   },
   "vocabularyTwo": {
   "application": <application>,
       "tags": [<tags>]
   }
  }'

Creating multiple relationships between a Vocabulary and a Widget

curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary\
-H "Content-Type: application/json"  -d \
'{
  "vocabularyOne": {
  "application": <application>,
      "tags": [<tags>]
  },
  "vocabularyTwo": {
  "application": <application>,
      "tags": [<tags>]
  }
 }'

Creating multiple relationships between a Vocabulary and a Layer

curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary \
-H "Content-Type: application/json"  -d \
'{
  "vocabularyOne": {
  "application": <application>,
      "tags": [<tags>]
  },
  "vocabularyTwo": {
  "application": <application>,
      "tags": [<tags>]
  }
 }'

Example of request with real data

curl -X POST https://api.resourcewatch.org/v1/dataset/942b3f38-9504-4273-af51-0440170ffc86/vocabulary?application=<application>
-H "Content-Type: application/json"  -d \
 '{
     "country": {
         "tags": ["Spain", "Italy", "Portugal"]
     },
     "sport": {
         "tags": ["football", "basketball", "voleyball"]
     },
     "color": {
         "tags": ["red", "green", "blue"]
     }
  }'

Example of response with real data

{
  "data": [
    {
      "id": "vocabularyNameTwo",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "tag1",
          "tag2",
          "tag3"
        ]
      }
    },
    {
      "id": "vocabularyNameOne",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "tag1",
          "tag2",
          "tag3"
        ]
      }
    },
    {
      "id": "a",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "tag1",
          "tag2",
          "tag3"
        ]
      }
    },
    {
      "id": "b",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "tag1",
          "tag2",
          "tag3"
        ]
      }
    },
    {
      "id": "newV",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "test1",
          "test2"
        ]
      }
    },
    {
      "id": "country",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "Spain",
          "Italy",
          "Portugal"
        ]
      }
    },
    {
      "id": "sport",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "football",
          "basketball",
          "voleyball"
        ]
      }
    },
    {
      "id": "color",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "red",
          "green",
          "blue"
        ]
      }
    }
  ]
}

Deleting relationships

Deleting relationships between a Vocabulary and a Dataset

curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary/<vocabulary-id>

Deleting relationships between a Vocabulary and a Widget

curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary/<vocabulary-id>

Deleting relationships between a Vocabulary and a Layer

curl -X DELETE https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary/<vocabulary-id>

Example of request with real data

curl -X DELETE https://api.resourcewatch.org/v1/dataset/942b3f38-9504-4273-af51-0440170ffc86/vocabulary/science

Example of response with real data

{
  "data": [
    {
      "id": "country",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "Spain",
          "Italy",
          "Portugal"
        ]
      }
    },
    {
      "id": "color",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "red",
          "green",
          "blue"
        ]
      }
    }
  ]
}

Getting Vocabularies associated to a Resource

You can be request all vocabularies that are associated to a particular resource. It optionally accepts a app or application query parameter, that will filter the vocabulary’s application. If none is provided, rw is used as default.

Getting Vocabularies related with a Dataset

curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary

Getting Vocabularies related with a Widget

curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary

Getting Vocabularies related with a Layer

curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary

Example of request with real data

curl -X GET https://api.resourcewatch.org/v1/dataset/942b3f38-9504-4273-af51-0440170ffc86/vocabulary

Example of response with real data

{
  "data": [
    {
      "id": "country",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "Spain",
          "Italy",
          "Portugal"
        ]
      }
    },
    {
      "id": "color",
      "type": "vocabulary",
      "attributes": {
        "tags": [
          "red",
          "green",
          "blue"
        ]
      }
    }
  ]
}

Getting a single relationship (broken now)

Getting a single relationship between a Vocabulary and a Dataset

curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/vocabulary/<vocabulary-id>

Getting a single relationship between a Vocabulary and a Widget

curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/<widget-id>/vocabulary/<vocabulary-id>

Getting a single relationship between a Vocabulary and a Layer

curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/<layer-id>/vocabulary/<vocabulary-id>

Getting resources (COMMON USE CASE)

There is also an endpoint available which accepts requests just indicating resource type and the desired vocabulary-tag matching.

It currently supports DOUBLE-OR pattern matching, meaning the API will return all resources that at least have one (or more) tags in a particular vocabulary. At the same time it will also apply an OR to the entities of other vocabulary-tag matchings.

The query has to be set in the url by the query params.

curl -X GET https://api.resourcewatch.org/v1/dataset/vocabulary/find
curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/vocabulary/find
curl -X GET https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/vocabulary/find

Example of response with real data

curl -X GET http://api.resourcewatch.org/v1/dataset/vocabulary/find?legacy=cdi,coasts

Getting all vocabularies

This endpoint is quite useful to have a quick overview of all existing vocabularies and resources.

curl -X GET https://api.resourcewatch.org/v1/vocabulary

Finding vocabularies by ids

The ids property is required in the body of the request. It can be either an array of ids or a string of comma-separated ids:

curl -X POST https://api.resourcewatch.org/v1/dataset/vocabulary/find-by-ids \
-H "Content-Type: application/json"  -d \
 '{
   "ids": [<ids>]
  }'
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/widget/vocabulary/find-by-ids \
-H "Content-Type: application/json"  -d \
 '{
   "ids": [<ids>]
  }'
curl -X POST https://api.resourcewatch.org/v1/dataset/<dataset-id>/layer/vocabulary/find-by-ids \
-H "Content-Type: application/json"  -d \
 '{
   "ids": [<ids>]
  }'

Example of request with real data

curl -X POST https://api.resourcewatch.org/v1/dataset/vocabulary/find-by-ids \
-H "Content-Type: application/json"  -d \
 '{
    "ids": "942b3f38-9504-4273-af51-0440170ffc86, 08ff8183-48dc-457a-8924-bb4e7a87b8a8"
  }'

Example of response with real data

{
  "data": [
    {
      "type": "resource",
      "id": "08ff8183-48dc-457a-8924-bb4e7a87b8a8",
      "attributes": {
        "legacy": [
          "cdi",
          "inundation",
          "national",
          "united states",
          "local",
          "coasts",
          "flooding",
          "health"
        ]
      }
    },
    {
      "type": "resource",
      "id": "942b3f38-9504-4273-af51-0440170ffc86",
      "attributes": {
        "country": [
          "Spain",
          "Italy",
          "Portugal"
        ],
        "color": [
          "red",
          "green",
          "blue"
        ]
      }
    }
  ]
}

Vocabulary Creation

As was mentioned before, it is possible to just create a new and empty vocabulary

curl -X POST https://api.resourcewatch.org/v1/vocabulary/vocabularyName \
-H "Content-Type: application/json"  -d \
 '{
   "application": <application>,
   "name": <vocabularyName>
  }'

It is also possible to update and delete an entire vocabulary. Said that, because it’s necessary to keep consistency between entities with weak relationship, these operations are only available to SUPERADMINS.

Bulk delete of resource’s vocabulary

Deleting all Vocabulary associated with a Dataset

curl -X DELETE https://api.resourcewatch.org/v1/dataset/:datasetId/vocabulary \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>"

Deleting all Vocabulary associated with a Widget

curl -X DELETE https://api.resourcewatch.org/v1/dataset/datasetId/widget/:widgetId/vocabulary \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>"

Deleting all Vocabulary associated with a Layer

curl -X DELETE https://api.resourcewatch.org/v1/dataset/datasetId/layer/:layerId/vocabulary \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your-token>"

In order to use these endpoints, you need to meet one of the following criteria:

All endpoints return 200 OK in case of success, along with the list of the deleted entities.

Geostore

What is Geostore?

Geostore is a geojson database. You can save your geojson or obtain geojson by country, region, Protected areas, etc.

Geostore object contains the following fields:

Field Description Type
id Id of the geostore Text
geojson Geojson with the geometry Object
hash MD5 hash generated from geojson. Is the same that the id Object
provider This field should be completed if the geostore was created from a provider Object
– type Provider type Text
– table Table name Text
– user User of the account Text
– filter Conditions to obtain the geojson. It is possible use AND & OR conditions. This conditions must only return one row. Text
areaHa Area in Hectares of the geojson Number
bbox Bounding box of the geojson Array

Create Geostore

You can create a geostore in 4 different ways:

With a Geojson

If you have your own geojson, you can save it in geostore. To create the geostore, you need to define all the required fields in the request body. The fields that compose a geostore are:

Field Description Type Values Required
geojson Geojson with your geometry Object Yes

To create a Geostore, you have to do a POST query with the following body:

curl -X POST https://api.resourcewatch.org/v1/geostore \
-H "Content-Type: application/json"  -d \
 '{
   "geojson": <yourGeoJSONObject>
  }'

Real example

curl -X POST https://api.resourcewatch.org/v1/geostore \
-H "Content-Type: application/json"  -d \
 '{
   "geojson":{
      "type":"FeatureCollection",
      "features":[
         {
            "type":"Feature",
            "properties":{

            },
            "geometry":{
               "type":"LineString",
               "coordinates":[
                  [
                     -3.9942169189453125,
                     41.044922165782175
                  ],
                  [
                     -3.995418548583985,
                     41.03767166215326
                  ],
                  [
                     -3.9842605590820312,
                     41.03844854003296
                  ],
                  [
                     -3.9844322204589844,
                     41.04589315472392
                  ],
                  [
                     -3.9942169189453125,
                     41.044922165782175
                  ]
               ]
            }
         },
         {
            "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
                     ]
                  ]
               ]
            }
         }
      ]
   }
}'

The response will be 200 if the geostore saves correctly and returns the geostore object with all information:

Example response

{
   "data":{
      "type":"geoStore",
      "id":"c9bacccfb9c3fe225dc67545bb93a5cb",
      "attributes":{
         "geojson":{
            "features":[
               {
                  "type":"Feature",
                  "geometry":{
                     "type":"Polygon",
                     "coordinates":[
                        [
                           [
                              -4.4549560546875,
                              40.84706035607122
                           ],
                           [
                              -4.4549560546875,
                              41.30257109430557
                           ],
                           [
                              -3.5211181640624996,
                              41.30257109430557
                           ],
                           [
                              -3.5211181640624996,
                              40.84706035607122
                           ],
                           [
                              -4.4549560546875,
                              40.84706035607122
                           ]
                        ]
                     ]
                  }
               }
            ],
            "crs":{

            },
            "type":"FeatureCollection"
         },
         "hash":"c9bacccfb9c3fe225dc67545bb93a5cb",
         "provider":{

         },
         "areaHa":397372.34122605197,
         "bbox":[
            -4.4549560546875,
            40.84706035607122,
            -3.5211181640624996,
            41.30257109430557
         ]
      }
   }
}

From country

If you need obtain the geostore of a country, you can obtain it with the ISO3 code in the Geostore API.

GET https://api.resourcewatch.org/v1/geostore/admin/<ISO3>

curl -X GET https://api.resourcewatch.org/v1/geostore/admin/<ISO3>

Real example obtaining the geostore of Spain shell curl -X GET https://api.resourcewatch.org/v1/geostore/admin/ESP

Country list

A list of countries can be obtained from this endpoint.

curl -X GET https://api.resourcewatch.org/v1/geostore/admin/list

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"
    }]
}

From country and region

If you need obtain the geostore of a region in a country, you can obtain it with the ISO3 and region code:

GET https://api.resourcewatch.org/v1/geostore/admin/<ISO3>/<regionCode>

curl -X GET https://api.resourcewatch.org/v1/geostore/admin/<ISO3>/<regionCode>

Real example obtaining the geostore of Madrid’s Comunity in Spain

curl -X GET https://api.resourcewatch.org/v1/geostore/admin/ESP/8

From World Database on Protected Areas (wdpa)

Is possible obtain the geostore of a World Database on Protected Areas of the world. You only need the id of the protected area (WDPA). World Database on Protected Areas web

GET https://api.resourcewatch.org/v1/geostore/wdpa/<wdpaId>

curl -X GET https://api.resourcewatch.org/v1/geostore/wdpa/<wdpaId>

Real example obtaining the geostore of ‘Sierra de Guadarrama’ protected area

curl -X GET https://api.resourcewatch.org/v1/geostore/wdpa/555538160

From land use areas

Geostore has the geojson of 4 different lands use:

Oil palm

GET https://api.resourcewatch.org/v1/geostore/use/oilpalm/<id>

curl -X GET https://api.resourcewatch.org/v1/geostore/use/oilpalm/<id>

Real example obtaining the geostore of one Oil palm area

curl -X GET https://api.resourcewatch.org/v1/geostore/use/oilpalm/556

Mining

GET https://api.resourcewatch.org/v1/geostore/use/mining/<id>

curl -X GET https://api.resourcewatch.org/v1/geostore/use/mining/<id>

Real example obtaining the geostore of one mining area

curl -X GET https://api.resourcewatch.org/v1/geostore/use/mining/573

Wood fiber

GET https://api.resourcewatch.org/v1/geostore/use/fiber/<id>

curl -X GET https://api.resourcewatch.org/v1/geostore/use/fiber/<id>

Real example obtaining the geostore of one Wood fiber area

curl -X GET https://api.resourcewatch.org/v1/geostore/use/fiber/346

Congo Basin logging roads

GET https://api.resourcewatch.org/v1/geostore/use/logging/<id>

curl -X GET https://api.resourcewatch.org/v1/geostore/use/logging/<id>

Real example obtaining the geostore of Oil palm area

curl -X GET https://api.resourcewatch.org/v1/geostore/use/logging/102

From Carto

If your geojson is in carto table, is possible import this geojson in geostore. To import the geojson in geostore, you need to define all of the required fields in the request body. The fields that compose a import are:

Field Description Type Values Required
provider Provider of data Object Yes
– type Provider type Text carto Yes
– table Table name Text Yes
– user User of the account Text Yes
– filter Conditions to obtain the geojson. Is possible put and and or conditions. This conditions must only return one row. Text Yes

To import a Geostore, you have to do a POST with the following body:

curl -X POST https://api.resourcewatch.org/v1/geostore \
-H "Content-Type: application/json"  -d \
 '{
    "provider":{
        "type": "carto",
        "table": <tableName>,
        "user": <userName>,
        "filter": <conditions>
    }
}'

Real example

curl -X POST https://api.resourcewatch.org/v1/geostore \
-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": "26f8975c4c647c19a2edaa11f23880a2",
    "attributes": {
      "geojson": {
        "features": [
          {
            "type": "Feature",
            "geometry": {
              "type": "MultiPolygon",
              "coordinates": [
                [
                  [
                    [
                      -74.0957370284411,
                      10.6814701233475
                    ],
                    [
                      -74.0957357154309,
                      10.654348341203
                    ],
                    [
                      -74.1100850695703,
                      10.6543473339623
                    ],
                    [
                      -74.1100876551212,
                      10.6814691125096
                    ],
                    [
                      -74.0957370284411,
                      10.6814701233475
                    ]
                  ]
                ]
              ]
            }
          }
        ],
        "crs": {},
        "type": "FeatureCollection"
      },
      "hash": "26f8975c4c647c19a2edaa11f23880a2",
      "provider": {
        "filter": "cartodb_id=573",
        "user": "wri-01",
        "table": "gfw_mining",
        "type": "carto"
      },
      "areaHa": 471.001953054716,
      "bbox": [
        -74.1100876551212,
        10.6543473339623,
        -74.0957357154309,
        10.6814701233475
      ]
    }
  }
}

Obtain a Geostore

To obtain a geostore, you only need the id of the Geostore. You can perform a GET request for the geostore with its id.

curl -X GET https://api.resourcewatch.org/v1/geostore/<geostoreId>

Real example obtaining one geostore

curl -X GET https://api.resourcewatch.org/v1/geostore/use/logging/26f8975c4c647c19a2edaa11f23880a2

Example response

{
  "data": {
    "type": "geoStore",
    "id": "26f8975c4c647c19a2edaa11f23880a2",
    "attributes": {
      "geojson": {
        "features": [
          {
            "type": "Feature",
            "geometry": {
              "type": "MultiPolygon",
              "coordinates": [
                [
                  [
                    [
                      -74.0957370284411,
                      10.6814701233475
                    ],
                    [
                      -74.0957357154309,
                      10.654348341203
                    ],
                    [
                      -74.1100850695703,
                      10.6543473339623
                    ],
                    [
                      -74.1100876551212,
                      10.6814691125096
                    ],
                    [
                      -74.0957370284411,
                      10.6814701233475
                    ]
                  ]
                ]
              ]
            }
          }
        ],
        "crs": {},
        "type": "FeatureCollection"
      },
      "hash": "26f8975c4c647c19a2edaa11f23880a2",
      "provider": {
        "filter": "cartodb_id=573",
        "user": "wri-01",
        "table": "gfw_mining",
        "type": "carto"
      },
      "areaHa": 471.001953054716,
      "bbox": [
        -74.1100876551212,
        10.6543473339623,
        -74.0957357154309,
        10.6814701233475
      ]
    }
  }
}

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:

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:

Subscription email example

Summary of the subscription lifecycle

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>"

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. String ‘gfw’
env The environment to which the subscription is associated. 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>"

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 "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:

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:

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 "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 "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 "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 "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 geostore

Creating a subscription providing the id of a geostore in the params field:

curl -X POST "https://api.resourcewatch.org/v1/subscriptions" \
-H "Authorization: Bearer <your-token>" \
-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 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 "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:

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 "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:

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>"

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.

Confirming a subscription

Example GET request to confirm a subscription:

curl -X GET "https://api.resourcewatch.org/v1/subscriptions/<subscription_id>/confirm"

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>"

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>"

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>"

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. 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>"

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. 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.
env String Yes 'production' Environment to which the subscription belongs.
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 "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>"

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>"

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>"

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>"

Graph

The following graph endpoints are available

List concepts

Returns a list including all the concepts present in the graph

curl -X GET https://api.resourcewatch.org/v1/graph/query/list-concepts

Query example

{
  "data": [
    {
      "id": "europe",
      "label": "Europe",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ],
      "numberOfDatasetsTagged": 0
    },
    {
      "id": "damage",
      "label": "Damage",
      "synonyms": [
        "destruction"
      ],
      "labels": [
        "CONCEPT",
        "TOPIC"
      ],
      "numberOfDatasetsTagged": 2
    },
    {
      "id": "guernsey",
      "label": "Guernsey",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ],
      "numberOfDatasetsTagged": 0
    }
  ]
}

Get inferred concepts

This endpoint returns the set of concepts that are inferred from the set passed as a parameter

Parameters

Parameter Description Type Values Required
concepts List of concepts Text Any Text, values separated by commas Yes
curl -X GET https://api.resourcewatch.org/v1/graph/query/concepts-inferred?concepts=<concept_list>

Example

Concepts inferred from the set: [‘spain’, 'raster’]

https://api.resourcewatch.org/v1/graph/query/concepts-inferred?concepts=spain,raster
{
  "data": [
    {
      "id": "location",
      "label": "Location",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "TOPIC"
      ]
    },
    {
      "id": "eu",
      "label": "EU",
      "synonyms": [
        "European Union"
      ],
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ]
    },
    {
      "id": "raster",
      "label": "Raster",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "DATA_TYPE"
      ]
    },
    {
      "id": "oecd",
      "label": "OECD",
      "synonyms": [
        "Organisation for Economic Co-operation and Development"
      ],
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ]
    },
    {
      "id": "schengen_area",
      "label": "Schengen Area",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ]
    },
    {
      "id": "country",
      "label": "Country",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ]
    },
    {
      "id": "continent",
      "label": "Continent",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ]
    },
    {
      "id": "global",
      "label": "Global",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ]
    },
    {
      "id": "general",
      "label": "General",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "TOPIC"
      ]
    },
    {
      "id": "spain",
      "label": "Spain",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ]
    },
    {
      "id": "dataset",
      "label": "Dataset",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "DATA_TYPE"
      ]
    },
    {
      "id": "europe",
      "label": "Europe",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "GEOGRAPHY"
      ]
    }
  ]
}

Concepts’ ancestors

This endpoint returns the ancestors from the list of concepts provided

Parameters

Parameter Description Type Values Required
concepts List of concepts Text Any Text, values separated by commas Yes
https://api.resourcewatch.org/v1/graph/query/concepts-ancestors?concepts=<concept_list>

Example

Ancestors of the concepts from the set: ['forest_cover’, 'landslide’]

https://api.resourcewatch.org/v1/graph/query/concepts-ancestors?concepts=forest_cover,landslide
{
  "data": [
    {
      "id": "indicator",
      "label": "Indicator",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "TOPIC"
      ]
    },
    {
      "id": "forest",
      "label": "Forest",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "TOPIC"
      ]
    },
    {
      "id": "natural_disaster",
      "label": "Natural disaster",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "TOPIC"
      ]
    },
    {
      "id": "natural_phenomena",
      "label": "Natural phenomena",
      "synonyms": "",
      "labels": [
        "CONCEPT",
        "TOPIC"
      ]
    }
  ]
}

Similar datasets

Returns a set of datasets that are similar to the dataset provider sorted by their degree of similarity.

curl -X GET https://api.resourcewatch.org/v1/graph/query/similar-dataset/<dataset-id>

Parameters available

Parameter Description Type Values Required
published Include only published datasets Boolean true/false No
app List of applications datasets should belong to (at least one of them) Text Any text, values separated by commas No
env Include only datasets with at least one of the specified environments Text One or more values from ['production’, 'preproduction’] No
limit Maximum number of datasets returned by the endpoint Integer A positive integer (3 by default) No

Example

Datasets that are similar to the dataset with id 63a7a997-695d-4629-b6e9-9b169f5c69b including only those that are published with a limit of 6 results in total, datasets from both production and preproduction environments are included.

https://api.resourcewatch.org/v1/graph/query/similar-dataset/63a7a997-695d-4629-b6e9-9b169f5c69bf?published=true&env=production,preproduction&app=rw&limit=6
{
  "data": [
    {
      "dataset": "0a59f415-ee0b-4d19-96f7-c7304c152e1b",
      "concepts": [
        "global",
        "raster",
        "geospatial"
      ]
    },
    {
      "dataset": "0087944f-871c-44bc-b4d9-cd5acfc27023",
      "concepts": [
        "global",
        "raster",
        "geospatial"
      ]
    },
    {
      "dataset": "0303127a-70b0-4164-9251-d8162615d058",
      "concepts": [
        "raster",
        "geospatial"
      ]
    },
    {
      "dataset": "05b7c688-09ba-4f33-90ea-185a1039df43",
      "concepts": [
        "global",
        "geospatial"
      ]
    },
    {
      "dataset": "050f4146-566c-4a6d-9aaa-b49ab66a3090",
      "concepts": [
        "global",
        "geospatial"
      ]
    },
    {
      "dataset": "00abb46f-34e2-4bf7-be30-1fb0b1de022f",
      "concepts": [
        "global",
        "geospatial"
      ]
    }
  ]
}

Similar datasets including ancestors

Returns a set of datasets that are similar to the dataset provider sorted by their degree of similarity as well as taking into account ancestor concepts.

curl -X GET https://api.resourcewatch.org/v1/graph/query/similar-dataset-including-descendent/<dataset-id>

Parameters available

Parameter Description Type Values Required
published Include only published datasets Boolean true/false No
app List of applications datasets should belong to (at least one of them) Text Any text, values separated by commas No
env Include only datasets with at least one of the specified environments Text One or more values from ['production’, 'preproduction’] No
limit Maximum number of datasets returned by the endpoint Integer A positive integer (3 by default) No

Example

Datasets that are similar to the dataset with id 03bfb30e-829f-4299-bab9-b2be1b66b5d4 including only those that are published with a limit of 6 results in total, datasets from both production and preproduction environments are included.

https://api.resourcewatch.org/v1/graph/query/similar-dataset-including-descendent/03bfb30e-829f-4299-bab9-b2be1b66b5d4?published=true&env=production,preproduction&app=rw&limit=6
{
  "data": [
    {
      "dataset": "05b7c688-09ba-4f33-90ea-185a1039df43",
      "concepts": [
        "country",
        "forest",
        "geospatial",
        "table"
      ],
      "numberOfOcurrences": 1
    },
    {
      "dataset": "0448c79d-0ee0-42ff-9331-aeee70cef301",
      "concepts": [
        "forest_cover",
        "forest_gain",
        "forest_loss",
        "geospatial"
      ],
      "numberOfOcurrences": 1
    },
    {
      "dataset": "098b33df-6871-4e53-a5ff-b56a7d989f9a",
      "concepts": [
        "country",
        "geospatial"
      ],
      "numberOfOcurrences": 1
    },
    {
      "dataset": "0be2ce12-79b3-434b-b557-d6ea92d787fe",
      "concepts": [
        "geospatial",
        "table"
      ],
      "numberOfOcurrences": 1
    },
    {
      "dataset": "050f4146-566c-4a6d-9aaa-b49ab66a3090",
      "concepts": [
        "geospatial",
        "table"
      ],
      "numberOfOcurrences": 1
    },
    {
      "dataset": "00abb46f-34e2-4bf7-be30-1fb0b1de022f",
      "concepts": [
        "geospatial",
        "table"
      ],
      "numberOfOcurrences": 1
    }
  ]
}

Search datasets by concepts

This endpoint performs a dataset search based on the concepts provided and the tags that have been associated to all the different datasets that are part of the application. Ancestors of the tags directly associated to a datasets are taken into account in the search.

curl -X GET https://api.resourcewatch.org/v1/graph/query/search-datasets?concepts[0][0]='water'

Up to three sets of concepts can be provided as shown in the example below. Given the following sets of concepts:

The url should be formed as follows:

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

AND logical operators are applied among the sets while OR is used for set elements.

Parameters available

Parameter Description Type Values Required
published Include only published datasets Boolean true/false No
app List of applications datasets should belong to (at least one of them) Text Any text, values separated by commas No
env Include only datasets with at least one of the specified environments Text One or more values from ['production’, 'preproduction’] No
page[size] Maximum number of results returned by the endpoint Number No

Example

Search for datasets with the tag global and water and at least one of the two tags: raster, geospatial. The resulting datasets should also be published and be categorized either as production or preproduction and belong to the application rw. The total number of results returned won’t be limited since a very high number has been provided as limit (999999).

https://api.resourcewatch.org/v1/graph/query/search-datasets?concepts[0][0]=global&concepts[1][0]=water&concepts[2][0]=raster&concepts[2][1]=geospatial&published=true&env=production,preproduction&app=rw&page[size]=999999

{
  "data": [
    "11f43558-d703-4b9d-aff0-f2354a11b359",
    "1b97e47e-ca18-4e50-9aae-a2853acca3f0",
    "20c70a51-4ddf-4f6c-ad2c-1a6729b95fa4",
    "21ac3cd2-9c19-47c7-ad18-4bcad118870f",
    "33bed1fb-9261-41bf-8b50-127a4d0c80c5",
    "3624554e-b240-4edb-9110-1f010642c3f3",
    "36803484-c413-49a9-abe2-2286ee99b624",
    "371e700e-bc9a-4526-af92-335d888de309",
    "60be01b0-99fb-459c-8a08-b934270f8c4b",
    "63a7a997-695d-4629-b6e9-9b169f5c69bf",
    "894f43a8-ce8e-43a5-a4c7-fa80faa43d63",
    "99075509-df36-461e-abb0-659cee555bd0",
    "9e9a5c50-b825-4f12-838f-1650943c2be1",
    "c17fab24-f71a-4c3e-bb87-6b753a944e6b",
    "c9eadefd-4a06-4f3b-a2eb-3e3f45624c24",
    "d7c3d954-ac86-4d1a-bb6a-c8c432a94e26",
    "e63bb157-4b98-4ecb-81d6-c1b15e79895a",
    "e7582657-9c16-4eb1-89e8-0211d94015c6",
    "e94f0e2d-2b5f-41ed-967f-d97e54dd81ea",
    "ede84747-0116-45c2-accb-1dfe141c00ff",
    "f717ac77-6f06-493f-8336-4e660a18f74c",
    "fa6443ff-eb95-4d0f-84d2-f0c91682efdf"
  ]
}

Get most liked datasets

This endpoint returns the list of the most liked datasets in descending order.

curl -X GET https://api.resourcewatch.org/v1/graph/query/most-liked-datasets

Response:

{
    "data": [
        {
            "id": "e2971008-029f-441b-97cd-ee0555728182",
            "count": {
                "low": 2,
                "high": 0
            }
        },
        {
            "id": "f6bb99af-541a-4d41-9e47-cc36cb479d4b",
            "count": {
                "low": 2,
                "high": 0
            }
        },
        {
            "id": "223b936e-06b8-4970-abd9-4f123904d95d",
            "count": {
                "low": 2,
                "high": 0
            }
        },
        {
            "id": "0b9f0100-ce5b-430f-ad8f-3363efa05481",
            "count": {
                "low": 2,
                "high": 0
            }
        }
    ]
}

Get most viewed datasets list

This endpoint returns the list of the most viewed datasets in descending order of total views.

Parameters

Parameter Description Type Values Required
limit Maximum number of results Number Any positive number No
curl -X GET https://api.resourcewatch.org/v1/graph/query/most-viewed

Response:

{
  "data": [
    {
      "dataset": "0087944f-871c-44bc-b4d9-cd5acfc27023",
      "views": 172
    },
    {
      "dataset": "00abb46f-34e2-4bf7-be30-1fb0b1de022f",
      "views": 68
    },
    {
      "dataset": "01b0b8cf-6638-4a9b-9896-d919d0656a64",
      "views": 5
    },
    {
      "dataset": "01ae2fd7-b818-429f-a27e-a36c8def971a",
      "views": 2
    },
    {
      "dataset": "00b5c224-8a78-41c4-89a6-8299dec8609e",
      "views": 0
    }
  ]
}

Update view counter for dataset and user

Updates the total view counter for the corresponding dataset. If the request is authenticated, it will also increment the counter of number of times the user has viewed the dataset.

curl -X POST https://api.resourcewatch.org/v1/graph/dataset/<dataset-id>/visited
-H "Authorization: Bearer <your-token>"

Areas

The following area endpoints are available

Get user areas

Returns the list of areas created by the user provided

Parameters

Parameter Description Type Values Required
application Application Text Any Text, values separated by commas No
curl -X POST https://api.resourcewatch.org/v1/area?application=<application>
-H "Authorization: Bearer <your-token>"

Example

Areas created by an user for the application RW.

curl -X POST https://api.resourcewatch.org/v1/area?application=rw
-H "Authorization: Bearer <your-token>"
{
  "data": [
    {
      "type": "area",
      "id": "59ca3213d08a7d001054522b",
      "attributes": {
        "name": "Test area France",
        "application": "rw",
        "geostore": "8f77fe62cf15d5098ba0ee11c5126aa6",
        "userId": "58e22f662071c01c02f76a0f",
        "createdAt": "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",
        "createdAt": "2017-09-26T10:58:50.226Z",
        "image": "",
        "datasets": [

        ],
        "use": {

        },
        "iso": {

        }
      }
    }
  ]
}

Create area

Creates a new area

Parameters

Parameter Description Type Values Required
application Application 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
curl -X POST https://api.resourcewatch.org/v1/area \
-H "Authorization: Bearer <your-token>" \
-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 "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",
      "createdAt": "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>" \

Example

curl -X POST https://api.resourcewatch.org/v1/area/59ca3213d08a7d001054522b \
-H "Authorization: Bearer <your-token>" \

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>" \

Example

curl -X GET https://api.resourcewatch.org/v1/area/59ca32ea3209db0014e9a7b7 \
-H "Authorization: Bearer <your-token>" \
{
    "data": {
        "type": "area",
        "id": "59ca32ea3209db0014e9a7b7",
        "attributes": {
            "name": "Test custom area",
            "application": "rw",
            "geostore": "b12640deba9d3c5012c5359dd5572e2d",
            "userId": "58e22f662071c01c02f76a0f",
            "createdAt": "2017-09-26T10:58:50.226Z",
            "image": "",
            "datasets": [],
            "use": {},
            "iso": {}
        }
    }
}

Areas v2

The following endpoints merge together areas of interest and subscriptions. This means they can be used to transition away from subscriptions without the users losing the subscriptions that they have already created.

Please ensure that you are using v2 in the URL when requesting these endpoints.

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>"

Example response:

{
    "data": [
        {
            "type": "area",
            "id": "5e4d74c3ef240412c2d56a71",
            "attributes": {
                "application": "gfw",
                "userId": "5e2f0eaf9de40a6c87dd9b7d",
                "createdAt": "2020-02-19T12:17:01.176Z",
                "datasets": [],
                "use": {},
                "iso": {},
                "admin": {},
                "tags": [],
                "status": "saved",
                "public": false,
                "fireAlerts": false,
                "deforestationAlerts": false,
                "webhookUrl": "",
                "monthlySummary": false,
                "subscriptionId": "5e4d273dce77c53768bc24f9",
                "email": "your.email@resourcewatch.org",
                "language": "en"
            }
        }
    ]
}

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>"

Example response:

{
    "data": [
        {
            "type": "area",
            "id": "5e4d74c3ef240412c2d56a71",
            "attributes": {
                "application": "gfw",
                "userId": "5e2f0eaf9de40a6c87dd9b7d",
                "createdAt": "2020-02-19T12:17:01.176Z",
                "datasets": [],
                "use": {},
                "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": "http://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10",
        "first": "http://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10",
        "last": "http://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10",
        "prev": "http://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10",
        "next": "http://api.resourcewatch.org/v2/area?all=true&page[number]=1&page[size]=10"
    },
    "meta": {
        "total-pages": 1,
        "total-items": 1,
        "size": 10
    }
}

Returns the list of areas for the user who made the request. This endpoint requires authentication.

This endpoint supports the following query parameters as filters:

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
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
page[number] The number of the page to fetch. Only taken into account when using the all=true filter. Number 1
page[size] The size of the page to fetch. Only taken into account when using the all=true filter. Maximum value is 100. Number 10

Note: Due to performance and memory management issues, when the all=true filter is applied, the returned result is always paginated.

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.

Note: if the all=true query filter is provided, then the /find-all endpoint of the subscriptions is used to find all existing subscriptions.

Getting a single user area

curl -X GET https://api.resourcewatch.org/v2/area/:id
-H "Authorization: Bearer <your-token>"

Example response:

{
    "data": {
        "type": "area",
        "id": "5e4d787bef240412c2d56a74",
        "attributes": {
            "application": "gfw",
            "userId": "5e2f0eaf9de40a6c87dd9b7d",
            "createdAt": "2020-02-19T12:17:01.176Z",
            "datasets": [],
            "use": {},
            "iso": {},
            "admin": {},
            "tags": [],
            "status": "saved",
            "public": false,
            "fireAlerts": false,
            "deforestationAlerts": false,
            "webhookUrl": "",
            "monthlySummary": false,
            "subscriptionId": "5e4d273dce77c53768bc24f9",
            "email": "tiago.garcia@vizzuality.com",
            "language": "en"
        }
    }
}

Returns the information for the area with the id provided. This endpoint requires authentication.

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. Otherwise, a 401 Unauthorized response will be returned.

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.

Implementation details

Try to find an area with the id provided:

  1. If the area exists:
    1. If the area has an associated subscription, the subscription is fetched, its data is merged over the area and the result is returned.
    2. If the area has no subscription associated, the area data is returned.
  2. If the area does not exist:
    1. 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.

Creating an area

curl -X POST https://api.resourcewatch.org/v2/area
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json" -d \
 '{
    "name": "Example area",
    "application": "gfw",
    "image": "",
    "tags": [],
    "public": false,
    "fireAlerts": true,
    "deforestationAlerts": true,
    "webhookUrl": "http://example.com",
    "monthlySummary": true,
    "email": "youremail@resourcewatch.org",
    "language": "en"
}'

Example response:

{
    "data": {
        "type": "area",
        "id": "5e4d7c47ef240412c2d56a78",
        "attributes": {
            "name": "Example area",
            "application": "gfw",
            "wdpaid": null,
            "userId": "5e2f0eaf9de40a6c87dd9b7d",
            "createdAt": "2020-02-19T18:19:51.485Z",
            "image": "",
            "datasets": [],
            "tags": [],
            "status": "pending",
            "public": false,
            "fireAlerts": true,
            "deforestationAlerts": true,
            "webhookUrl": "http://example.com",
            "monthlySummary": true,
            "subscriptionId": "5e4d7c47dd8fa31290d548ae",
            "email": "youremail@resourcewatch.org",
            "language": "en"
        }
    }
}

Use this endpoint to create new areas. This endpoint requires authentication.

This endpoint supports the following request body parameters:

Field Description Type Example
name The name of the area being created. String 'Example’
image Image associated with the dataset - in GET areas, this attribute will have the URL for the image. String https://www.google.com/example.jpg
application The application to which this area is associated with. Defaults to 'gfw’. String 'gfw’
language The language of this area. Defaults to 'en’. String 'es’
geostore An ID of a geostore to which this area relates to. String '123’
public If the area is public or not. Defaults to false. Boolean true
fireAlerts If the area is intended to subscribe to fire alerts. Defaults to false. Boolean true
deforestationAlerts If the area is intended to subscribe to deforestation alerts. Defaults to false. Boolean true
monthlySummary If the area is intended to subscribe to monthly summaries. Defaults to false. Boolean true
email Email to be provided to the subscription. String youremail@resourcewatch.org
webhookUrl Webhook URL to be provided to the subscription (only used in case the email is not set). String https://www.google.com/
status The status of the area - either 'saved’ or 'pending’. Read-only attribute. String 'saved’
subscriptionId The ID of the subscription associated with this area. Read-only attribute. String 5e4d7c47dd8fa31290d548ae

Email notification

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'.

After creating an area, if the email field of the area has a valid email, an email is sent to the user. The email content varies according to the status of the area:

Email substitution parameters

The following parameters are provided to the email service and can be used in the construction of the email:

(5d517b3fb8cfd4001061d0b2 is an example of an area ID).

Implementation details

POST of a new area always starts by creating the area and, 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:

Updating an area

curl -X PATCH https://api.resourcewatch.org/v2/area/:id
-H "Authorization: Bearer <your-token>" \
-H "Content-Type: application/json" -d \
 '{
    "name": "Example area",
    "application": "gfw",
    "image": "",
    "tags": [],
    "public": false,
    "fireAlerts": true,
    "deforestationAlerts": true,
    "webhookUrl": "http://example.com",
    "monthlySummary": true,
    "email": "youremail@resourcewatch.org",
    "language": "en"
}'

Example response:

{
    "data": {
        "type": "area",
        "id": "5e4d7c47ef240412c2d56a78",
        "attributes": {
            "name": "Example area",
            "application": "gfw",
            "wdpaid": null,
            "userId": "5e2f0eaf9de40a6c87dd9b7d",
            "createdAt": "2020-02-19T18:19:51.485Z",
            "image": "",
            "datasets": [],
            "tags": [],
            "status": "pending",
            "public": false,
            "fireAlerts": true,
            "deforestationAlerts": true,
            "webhookUrl": "http://example.com",
            "monthlySummary": true,
            "subscriptionId": "5e4d7c47dd8fa31290d548ae",
            "email": "youremail@resourcewatch.org",
            "language": "en"
        }
    }
}

Use this endpoint to update an existing area. This endpoint requires authentication and, in order to PATCH an area, you need to be either the owner of the area or be an ADMIN user.

This endpoint supports the following request body parameters:

Field Description Type Example
name The name of the area being created. String 'Example’
image Image associated with the dataset - in GET areas, this attribute will have the URL for the image. String https://www.google.com/example.jpg
application The application to which this area is associated with. Defaults to 'gfw’. String 'gfw’
language The language of this area. Defaults to 'en’. String 'es’
geostore An ID of a geostore to which this area relates to. String '123’
public If the area is public or not. Defaults to false. Boolean true
fireAlerts If the area is intended to subscribe to fire alerts. Defaults to false. Boolean true
deforestationAlerts If the area is intended to subscribe to deforestation alerts. Defaults to false. Boolean true
monthlySummary If the area is intended to subscribe to monthly summaries. Defaults to false. Boolean true
email Email to be provided to the subscription. String youremail@resourcewatch.org
webhookUrl Webhook URL to be provided to the subscription (only used in case the email is not set). String https://www.google.com/
status The status of the area - either 'saved’ or 'pending’. Read-only attribute. String 'saved’
subscriptionId The ID of the subscription associated with this area. Read-only attribute. String 5e4d7c47dd8fa31290d548ae

Email notification

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'.

After updating an area, if it has status saved and if the email field of the area has a valid email, an email is sent to the user, to let him know the area of interest is ready to be viewed.

Email substitution parameters

The following parameters are provided to the email service and can be used in the construction of the email:

(5d517b3fb8cfd4001061d0b2 is an example of an area ID).

Implementation details

PATCHing an area is a bit more complex, and it comes down to 3 major cases:

  1. The area already exists and has subscriptions preference (deforestationAlerts, fireAlerts or monthlySummary set to true) in the request data:
    1. If the area doesn’t have a subscription associated, a new one is created and associated.
    2. If the area already had a subscription, then the subscription is PATCHed according to the data provided in the request body.
  2. The area already exists and doesn’t has subscription preferences (deforestationAlerts, fireAlerts or monthlySummary set to true) in the request data:
    1. If the area had a subscription associated, then the subscription associated is deleted.
    2. Otherwise, just save the area.
  3. 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):
    1. First, create a new area, and then:
      1. If the request data has subscriptions preference (deforestationAlerts, fireAlerts or monthlySummary set to true), also PATCH the subscription.
      2. If the request data doesn’t have subscriptions preference (deforestationAlerts, fireAlerts or monthlySummary set to true), delete the associated subscription.

Deleting an area

curl -X DELETE https://api.resourcewatch.org/v2/area/:id
-H "Authorization: Bearer <your-token>" \

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 be an ADMIN user.

Implementation details

DELETing an area deletes the area if it exists, and then if an associated subscription exists, it is also deleted.

If the ID of a subscription is provided, then that subscription is deleted.

Update areas by geostore

curl -X POST https://api.resourcewatch.org/v2/area/update
-H "Authorization: Bearer <your-token>" \
-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",
                "datasets": [],
                "use": {},
                "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.

After updating the areas, for each area that was updated (if it has a valid email associated), an email will be sent to the user to let them know that the area is ready to be viewed.

The following parameters are provided to the email service and can be used in the construction of the email:

Sync areas

curl -X POST https://api.resourcewatch.org/v2/area/sync
-H "Authorization: Bearer <your-token>" \

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).

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:

PDF

This endpoint expects a URL as a query parameter and generates a pdf containing a rendered version of that page:

curl -X GET \
  'http://api.resourcewatch.org/v1/webshot/pdf?url=http://google.com&filename=my-google-screenshoz.pdf' \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \

The endpoint accepts the following optional parameters:

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

This endpoint generates a thumbnail image for the provided widget and stores it on AWS S3.

curl -X POST \
  http://api.resourcewatch.org/v1/webshot/widget/7b540186-9a9f-4e13-a6e8-f38e64fab2e1/thumbnail \
  -H 'Authorization: Bearer <your-token>' \
  -H 'Content-Type: application/json' \
{
    "data": {
        "widgetThumbnail": "http://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.

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'

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,
                "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 Text (single value)
curl -X GET https://api.resourcewatch.org/v1/topic?user=57bc2608f098ce98007985e4&private=false
# Deprecated syntax
curl -X GET https://api.resourcewatch.org/v1/topic?filter[user]=57bc2608f098ce98007985e4&filter[private]=false

Sorting

There’s currently no support for custom sorting of topics. The topics are listed on a pseudo-random order.

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.

curl -X GET https://api.resourcewatch.org/v1/topic?includes=user

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,
          "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"]. array of strings
curl -X POST https://api.resourcewatch.org/v1/topics \
-H "Authorization: Bearer <your-token>" \
-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,
              "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,
            "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:

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 "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,
            "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'
{
    "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,
            "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

What is a dashboard

A dashboard contains the information to display a web page belonging to a user.

Getting all dashboards

This endpoint will allow to get all dashboards belonging to a user:

curl -X GET https://api.resourcewatch.org/v1/dashboard -H 'Authorization: Bearer <your-token>'

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,
                "production": true,
                "preproduction": false,
                "staging": false,
                "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": "http://staging-api.globalforestwatch.org/v1/dashboard?page%5Bnumber%5D=1&page%5Bsize%5D=10",
        "first": "http://staging-api.globalforestwatch.org/v1/dashboard?page%5Bnumber%5D=1&page%5Bsize%5D=10",
        "prev": null,
        "next": "http://staging-api.globalforestwatch.org/v1/dashboard?page%5Bnumber%5D=2&page%5Bsize%5D=10",
        "last": "http://staging-api.globalforestwatch.org/v1/dashboard?page%5Bnumber%5D=14&page%5Bsize%5D=10"
    },
    "meta": {
        "total-pages": 14,
        "total-items": 140,
        "size": 10
    }
}

Filters

Example request using query string filters:

curl -X GET https://api.resourcewatch.org/v1/dashboard?name=text&private=false

Deprecated filter syntax:

curl -X GET https://api.resourcewatch.org/v1/dashboard?filter[name]=text&filter[private]=false

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. Text (single value)
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

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 using query string parameters for paging the result:

curl -X GET https://api.resourcewatch.org/v1/dashboard?page[size]=15&page[number]=2
Field Description Type Default value
page[size] The number elements per page. The maximum allowed value is 100 Number 10
page[number] The page number Number 1

Sorting

Sorting dashboards

curl -X GET https://api.resourcewatch.org/v1/dashboard?sort=name

Sorting dashboards by multiple criteria

curl -X GET https://api.resourcewatch.org/v1/dashboard?sort=name,slug

Explicit order of sorting

curl -X GET https://api.resourcewatch.org/v1/dashboard?sort=-name,+slug

Sorting dashboards by the role of the user who owns the dashboard

curl -X GET https://api.resourcewatch.org/v1/dashboard?sort=user.role

Multiple sorting criteria can be used, separating them by commas.

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.

The API currently supports sorting by means of the sort parameter. Sorting can be done using any field from the dashboard, as well as user.name and user.role (sorting by user data is restricted to ADMIN users).

Sorting by nested fields is not supported at the moment.

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

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,
          "production": true,
          "preproduction": false,
          "staging": false,
          "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.

Getting a dashboard by its ID

How to get a dashboard by its ID:

curl -X GET http://api.resourcewatch.org/dashboard/24

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,
      "production": true,
      "preproduction": false,
      "staging": false,
      "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 "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,
              "production": true,
              "preproduction": false,
              "staging": false,
              "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,
            "production": true,
            "preproduction": false,
            "staging": false,
            "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. Any role can create a dashboard.

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"]. array of strings
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 "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,
            "production": true,
            "preproduction": false,
            "staging": false,
            "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:

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 "Content-Type: application/json"

In order to perform this operation, the following conditions must be met:

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 "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,
            "production": true,
            "preproduction": false,
            "staging": false,
            "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:

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:

Get all tasks

To obtain all tasks:

curl -X GET https://api.resourcewatch.org/v1/doc-importer/task

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

Field Description Type Default value
page[size] The number elements per page. The maximum allowed value is 100 Number 10
page[number] The page number Number 1

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

Return the tasks with status SAVED

curl -X GET https://api.resourcewatch.org/v1/doc-importer/task?status=SAVED

Return the tasks created on Feb 1st 2019

curl -X GET https://api.resourcewatch.org/v1/doc-importer/task?createdAt=2019-02-01

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

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

Get a single task

To obtain the task:

curl -X GET https://api.resourcewatch.org/v1/doc-importer/task/55b02cfd-dabf-4ad0-a04d-5501cf248a0c

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 "Content-Type: application/json"

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 authentication 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 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. While not required nor enforced, typically they are used hierarchically in that order, from least to most permissive. A common pattern you’ll find on some services is: USER accounts can only create new resources, MANAGER accounts can create new resources, and edit or delete resources created by them, while ADMIN accounts can do all of the above even for resources created by other users.

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.

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.

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:

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": {
    "email": "your-email@provider.com",
    "createdAt": "2018-11-15T04:46:35.313Z",
    "role": "USER",
    "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

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

{
  "data": {
    "id": "5bfd237767b3176dd63f2eb7",
    "email": "your-email@provider.com",
    "createdAt": "2018-11-27T10:59:03.531Z",
    "role": "USER",
    "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

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 JWT token based authentication, this endpoint will NOT invalidate the token.

GET <BASE API URL>/auth/generate-token

Generate the user’s JWT token

curl -X GET "https://api.resourcewatch.org/auth/generate-token" \
    -H 'Cookie: <your cookie values>'

Response:

{
    "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjViZWNmYTJiNjdkYTBkM2VjMDdhMjdmNiIsInJvbGUiOiJVU0VSIiwicHJvdmlkZXIiOiJsb2NhbCIsImVtYWlsIjoidGVzdEBleGFtcGxlLmNvbSIsImV4dHJhVXNlckRhdGEiOnsiYXBwcyI6WyJydyJdfSwiY3JlYXRlZEF0IjoxNTQzMzE1NzMxNzcwLCJpYXQiOjE1NDMzMTU3MzF9.kIdkSOb7mCMOxE2ipqVOBrK7IefAjLDhaPG9DT1qvCw"
}

Generates a JWT 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

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, Twitter or Google. These 3 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 Twitter, Facebook or Google applications will be used. Also, not all origin applications support all 3 providers.

3rd party authentication using Twitter

3rd party authentication using Google

3rd party authentication using Facebook

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 + password based login for HTML requests. Not supported on JSON requests.

Register a new user account

Account creation using email + password

curl -X POST "https://api.resourcewatch.org/auth/sign-up" \
-H "Content-Type: application/json"  -d \
 '{
    "email":"your-email@provider.com",
    "password":"potato",
    "repeatPassword":"potato",
    "apps": ["rw"]
}'

Response

{
  "data": {
    "id": "5bfd237767b3176dd63f2eb7",
    "email": "your-email@provider.com",
    "createdAt": "2018-11-27T10:59:03.531Z",
    "role": "USER",
    "extraUserData": {
      "apps": ["rw"]
    }
  }
}

Account creation using email + password with a user defined origin app

curl -X POST "https://api.resourcewatch.org/auth/sign-up?origin=rw" \
-H "Content-Type: application/json"  -d \
 '{
    "email":"your-email@provider.com",
    "password":"potato",
    "repeatPassword":"potato",
    "apps": ["rw"]
}'

Account creation endpoint, for accounts using email + password based login for both HTML and JSON requests.

The combination of both user email and provider must be unique - a given email address may be associated with multiple, non-related user accounts by using different authentication providers (email+password, facebook, twitter, etc).

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. Once confirmed using this process, the user account becomes activated and fully functional, and the user will be able to log in.

The email sent to the user will have the identity of the origin app provided on the request, with a system-wide fallback (GFW) being used in case none is provided.

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.

Errors

Error code Error message Description
422 Email exists. An account already exists for the provided email address.
422 Email, Password and Repeat password are required. You are missing one of the required fields.

Confirm user account

JSON Request:

curl -X GET "https://api.resourcewatch.org/auth/confirm/:token" \
-H "Content-Type: application/json"

JSON Response:

{
    "data": {
        "id": "5dbadc495eae7358322dd64b",
        "email": "info@vizzuality.com",
        "createdAt": "2019-10-31T13:06:17.676Z",
        "updatedAt": "2019-10-31T13:06:17.676Z",
        "role": "USER",
        "extraUserData": {
            "apps": []
        }
    }
}

Request with callback:

curl -X GET "https://api.resourcewatch.org/auth/confirm/:token?callbackUrl=https://your-app.com"

Endpoint used in the user validation email to confirm the address upon registration.

It accepts an optional callbackUrl query parameter with an URL to which the user will be redirect if the confirmation succeeds.

Should no callbackUrl be provided, the user is redirected to an URL based on the first application associated to their user account - see ct-oauth-plugin configuration for more info.

Should that application have no configured redirect URL, or the user have no configured app, they are redirect to a platform-wide default URL - see ct-oauth-plugin configuration for more info.

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.

Errors

Error code Error message Description
422 Mail required. You need to specify the email address in the request body.

GET <BASE API URL>/auth/reset-password/:token

Endpoint used when the user clicks the link sent in the reset password email. This endpoint is meant to be used only by the end user.

Errors

Error code Error message Description
422 Token expired. The reset password link is more than 24 hours old and is no longer valid.

POST <BASE API URL>/auth/reset-password/:token

New password submission

curl -X POST "https://api.resourcewatch.org/auth/reset-password/<email token>" \
-H "Content-Type: application/json"  -d \
 '{
    "password":"potato",
    "repeatPassword":"potato"
}'

Response

{
    "provider": "local",
    "role": "ADMIN",
    "_id": "5dbadb0adf24534d1ad05dfb",
    "email": "test.user@example.com",
    "extraUserData": {
        "apps": [
            "rw",
            "gfw"
        ]
    },
    "createdAt": "2019-10-31T13:00:58.191Z",
    "updatedAt": "2019-10-31T13:00:58.191Z"
}

Endpoint used to submit the new password.

For HTML requests, it will redirect the user to the configured redirect URL on success, or return to the “Reset your password” form on error.

For JSON requests, it will return the user object on success, or a JSON object containing details in case of error.

Errors

Error code Error message Description
422 Token expired. The reset password link is more than 24 hours old and is no longer valid.
422 Password and Repeat password are required. You need to specify both the password and the repeatPassword values.
422 Password and Repeat password not equal. You need to specify equal password and repeatPassword values.

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",
            "email": "john.doe@vizzuality.com",
            "createdAt": "2019-10-31T13:00:58.191Z",
            "updatedAt": "2019-10-31T13:00:58.191Z",
            "role": "USER",
            "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",
         "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
     }
}

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

Error code Error message Description
401 Not authenticated. You need to be logged in to use this endpoint.

Pagination

Custom pagination: load page 2 using 25 results per page

curl -X GET "https://api.resourcewatch.org/auth/user?page[number]=2&page[size]=25"
-H "Content-Type: application/json"  -d \
-H "Authorization: Bearer <your-token>" \

By default, users are listed in pages of 10 results each, and the first page is loaded. However, you can customize this behavior using the following query parameters:

Field Description Type Default
page[size] The number elements per page. Values above 100 are not officially supported. Number 10
page[number] The page number Number 1

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 or rw 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",
            "email": "john.doe@vizzuality.com",
            "createdAt": "2019-10-31T13:00:58.191Z",
            "updatedAt": "2019-10-31T13:00:58.191Z",
            "role": "ADMIN",
            "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. These parameters can be combined into a complex and logic query.

Here’s the comprehensive list of filters supported by the users list endpoint:

Filter Description Type Expected values
name Filter returned users by their name. String any valid text
email 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 or facebook
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

Please keep in mind that all filter values except app support and expect a regex value. Although typically they will match exact strings, you may have to escape certain characters (PCRE v8.42 spec).

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",
    "email": "test.user@example.com",
    "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

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",
    "email": "test.user@example.com",
    "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

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.

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",
        "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",
        "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:

The response will contain the user details, reflecting the applied changes.

Errors

Error code Error message Description
401 Not authenticated. You need to be logged in to use this endpoint.

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",
        "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",
        "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:

The response will contain the user details, reflecting the applied changes.

Errors

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",
        "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",
        "extraUserData": {
           "apps": ["rw", "gfw"]
        }
    }
}

This endpoints deletes the user account with the given id. It’s available to users with the ADMIN role. The response will contain the details of the user account that was deleted.

Microservices

A list of information related to the microservices

List all registered microservices

To obtain a list of all the registered microservices:

curl -X GET https://api.resourcewatch.org/api/v1/microservice \
-H "Authorization: Bearer <your-token>"

Example response:

[
    {
        "infoStatus": {
            "numRetries": 0,
            "error": null,
            "lastCheck": "2019-02-04T14:05:30.748Z"
        },
        "pathInfo": "/info",
        "pathLive": "/ping",
        "status": "active",
        "cache": [],
        "uncache": [],
        "tags": [
            "dataset"

        ],
        "_id": "id",
        "name": "Dataset",
        "url": "http://dataset.default.svc.cluster.local:3000",
        "version": 1,
        "endpoints": [
            {
                "redirect": {
                    "method": "GET",
                    "path": "/api/v1/dataset"
                },
                "path": "/v1/dataset",
                "method": "GET"
            },
            {
                "redirect": {
                    "method": "POST",
                    "path": "/api/v1/dataset/find-by-ids"
                },
                "path": "/v1/dataset/find-by-ids",
                "method": "POST"
            }
        ],
        "updatedAt": "2019-01-24T13:04:46.728Z",
        "swagger": "{}"
    },
    {
        "infoStatus": {
            "numRetries": 0,
            "error": null,
            "lastCheck": "2019-02-04T14:05:30.778Z"
        },
        "pathInfo": "/info",
        "pathLive": "/ping",
        "status": "active",
        "cache": [
            "layer"
        ],
        "uncache": [
            "layer",
            "dataset"
        ],
        "tags": [
            "layer"
        ],
        "_id": "5aa667d1aee7ae16fb419c23",
        "name": "Layer",
        "url": "http://layer.default.svc.cluster.local:6000",
        "version": 1,
        "endpoints": [
            {
                "redirect": {
                    "method": "GET",
                    "path": "/api/v1/layer"
                },
                "path": "/v1/layer",
                "method": "GET"
            },
            {
                "redirect": {
                    "method": "POST",
                    "path": "/api/v1/dataset/:dataset/layer"
                },
                "path": "/v1/dataset/:dataset/layer",
                "method": "POST"
            },
            {
                "redirect": {
                    "method": "GET",
                    "path": "/api/v1/dataset/:dataset/layer"
                },
                "path": "/v1/dataset/:dataset/layer",
                "method": "GET"
            }
        ],
        "updatedAt": "2018-11-08T12:07:38.014Z",
        "swagger": "{}"
    }
]

Filters

The microservice list provided by the endpoint can be filtered with the following attributes:

Filter Description Accepted values
status Status of the microservice pending, active or error
url Internal URL of the microservice within the cluster String

Filtering by status

curl -X GET https://api.resourcewatch.org/api/v1/microservice?status=active \
-H "Authorization: Bearer <your-token>"

Get a microservice by id

To obtain the details of a single microservice, use:

curl -X GET https://api.resourcewatch.org/api/v1/microservice/5aa667d1aee7ae16fb419c23 \
-H "Authorization: Bearer <your-token>"

Example response:

{
  "data": {
    "id": "5aa667d1aee7ae16fb419c23",
    "infoStatus": {
        "numRetries": 0,
        "error": null,
        "lastCheck": "2019-02-04T14:05:30.778Z"
    },
    "pathInfo": "/info",
    "pathLive": "/ping",
    "status": "active",
    "cache": [
        "layer"
    ],
    "uncache": [
        "layer",
        "dataset"
    ],
    "tags": [
        "layer"
    ],
    "name": "Layer",
    "url": "http://layer.default.svc.cluster.local:6000",
    "version": 1,
    "endpoints": [
        {
            "redirect": {
                "method": "GET",
                "path": "/api/v1/layer"
            },
            "path": "/v1/layer",
            "method": "GET"
        },
        {
            "redirect": {
                "method": "POST",
                "path": "/api/v1/dataset/:dataset/layer"
            },
            "path": "/v1/dataset/:dataset/layer",
            "method": "POST"
        },
        {
            "redirect": {
                "method": "GET",
                "path": "/api/v1/dataset/:dataset/layer"
            },
            "path": "/v1/dataset/:dataset/layer",
            "method": "GET"
        }
    ],
    "updatedAt": "2018-11-08T12:07:38.014Z",
    "swagger": "{}"
   }
}

Delete microservice

To remove a microservice:

curl -X DELETE https://api.resourcewatch.org/api/v1/microservice/:id \
-H "Authorization: Bearer <your-token>"

This will delete the microservice and its associated endpoints from the gateway’s database. It does not remove the actual running microservice application instance, which may re-register and become available once again.

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.

Start by following the steps detailed here for obtaining your private token. At the end you should have your JWT token, a large string of random-looking characters.

If you are sure you have an up-to-date token but are still experiencing 401 Unauthorized errors, there may be an issue with the way the token is transmitted to the API. Be sure to use in Authorization header and Bearer <your token goes here> value.

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. - 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.

Errors

The Resource Watch API uses the following error codes:

Error Code Meaning
400 Bad Request – Your request is incomplete or contains errors
401 Unauthorized – Your API key is incorrect
403 Forbidden – The kitten requested is hidden for administrators only
404 Not Found – The specified kitten could not be found
405 Method Not Allowed – You tried to access a kitten with an invalid method
406 Not Acceptable – You requested a format that is not json
410 Gone – The kitten requested has been removed from our servers
429 Too Many Requests – You’re requesting too many kittens! Slow down!
500 Internal Server Error – We had a problem with our server. Try again later.
503 Service Unavailable – We’re temporarily offline for maintenance. Please try again later.

API attribution requirements

By using the Resource Watch API, you agree to the Resource Watch terms of service and attribution requirements.