Layers

Uploading a file or URL

The /upload endpoint can be used for both URL and file uploads:

  • For URL uploads, simply making a single POST request to the upload endpoint is enough

  • For file uploads, the response of the initial POST request will include a target URL and some pre-signed attributes, which will be used to upload the new file to Amazon S3.

post

/api/v2/maps/{map_id}/upload

Authorizations
Path parameters
map_idstringrequired

The ID of the map to upload the layer to.

Body
import_urlstring

A public URL containing geodata to import, in place of uploading a file.

latnumber

(Image uploads only) The latitude of the image center.

lngnumber

(Image uploads only) The longitude of the image center.

namestringrequired

The display name for the new layer.

zoomnumber

(Image uploads only) The zoom level of the image.

Responses
curl -L \
  --request POST \
  --url 'https://felt.com/api/v2/maps/{map_id}/upload' \
  --header 'Authorization: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data '{"name":"text"}'
{
  "layer_group_id": "RShuaEiiRTm19ALxAAf9Ar5B",
  "type": "upload_response",
  "layer_id": "grxbBVKoRUWKYh77urpGWD",
  "presigned_attribues": {},
  "url": "text"
}

This endpoint is used to create a layer, and obtain a pre-signed url to upload the layer files to S3.

Uploading the file to Amazon S3

Layer files aren’t uploaded directly to the Felt API. Instead, they are uploaded by your client directly to an S3 bucket.

You will receive a single set of URL and pre-signed params to upload the file. Only a single file may be uploaded — if you wish to upload several files at once, consider wrapping them in a zip file.

To upload the file using the pre-signed params, you must perform a multipart upload, and include the file contents in the file field:

# Requires requests library to be installed with: pip install requests
import requests

# Your API token should look like this:
# api_token = "felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
api_token = "<YOUR_API_TOKEN>"
map_id = "<YOUR_MAP_ID>"
path_to_file = "<YOUR_FILE_WITH_EXTENSION>" # Example: features.geojson

# Request  a pre-signed URL from Felt
layer_response = requests.post(
    f"https://felt.com/api/v2/maps/{map_id}/upload",
    headers={
        "authorization": f"Bearer {api_token}",
        "content-type": "application/json",
    },
    json={"name": "My new layer"},
)
presigned_upload = layer_response.json()
url = presigned_upload["data"]["attributes"]["url"]
presigned_attributes = presigned_upload["data"]["attributes"]["presigned_attributes"]
# A 204 response indicates that the upload was successful
with open(path_to_file, "rb") as file_obj:
    output = requests.post(
        url,
        # Order is important, file should come at the end
        files={**presigned_attributes, "file": file_obj},
    )

Refreshing a layer

After uploading a file or URL, you may want to update the resulting layer with some new data. The process is quite similar to the above:

  • For URL uploads, simply making a single POST request to the refresh endpoint is enough

  • For file uploads, the response of the initial POST request will include a URL and some presigned attributes, which will be used to upload the new file to Amazon S3. See Uploading the file to Amazon S3 for more details.

post

/api/v2/maps/{map_id}/layers/{layer_id}/refresh

Authorizations
Path parameters
map_idstringrequired

The ID of the map hosting the layer to refresh

layer_idstringrequired

The ID of the layer to refresh

Responses
curl -L \
  --request POST \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/refresh' \
  --header 'Authorization: YOUR_API_KEY'
{
  "layer_group_id": "RShuaEiiRTm19ALxAAf9Ar5B",
  "type": "upload_response",
  "layer_id": "grxbBVKoRUWKYh77urpGWD",
  "presigned_attribues": {},
  "url": "text"
}

Deleting a layer

delete

/api/v2/maps/{map_id}/layers/{layer_id}

Path parameters
map_idstringrequired

The ID of the map to delete the layer from

layer_idstringrequired

The ID of the layer to delete

Responses
curl -L \
  --request DELETE \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}'

No body

Styling layers

Update a layer's style

A layer's style may be updated by providing a new Felt Style Language object. Learn more in the guide:

Styling layers

post

/api/v2/maps/{map_id}/layers/{layer_id}/update_style

Path parameters
map_idstringrequired

The ID of the map where the layer is located

layer_idstringrequired

The ID of the layer to update the style of

Body
styleobjectrequired

The new layer style, specified in Felt Style Language format

Responses
curl -L \
  --request POST \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/update_style' \
  --header 'Content-Type: application/json' \
  --data '{"style":{}}'
{
  "hide_from_legend": true,
  "id": "k441enUxQUOnZqc1ZvNsDA",
  "is_spreadsheet": true,
  "name": "text",
  "progress": 1,
  "subtitle": "text",
  "geometry_type": "Line",
  "refresh_period": "15 min",
  "status": "uploading",
  "type": "layer",
  "ordering_key": 1,
  "style": {},
  "tile_url": "text",
  "links": {
    "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
  }
}

Managing layers

Get all the layers on a map

Get the details of all the layer on the map that are not within a layer group.

get

/api/v2/maps/{map_id}/layers

Path parameters
map_idstringrequired
Responses
curl -L \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers'
[
  {
    "hide_from_legend": true,
    "id": "k441enUxQUOnZqc1ZvNsDA",
    "is_spreadsheet": true,
    "name": "text",
    "progress": 1,
    "subtitle": "text",
    "geometry_type": "Line",
    "refresh_period": "15 min",
    "status": "uploading",
    "type": "layer",
    "ordering_key": 1,
    "style": {},
    "tile_url": "text",
    "links": {
      "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
    }
  }
]

Get a single layer

Get the details of a single layer on the map. These details include:

  • Name of the layer

  • Upload status and progress

  • Style, expressed in the Felt Style Language

  • Other metadata, such as the geometry type, visibility state in the legend, etc

get

/api/v2/maps/{map_id}/layers/{layer_id}

Path parameters
map_idstringrequired
layer_idstringrequired
Responses
curl -L \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}'
{
  "hide_from_legend": true,
  "id": "k441enUxQUOnZqc1ZvNsDA",
  "is_spreadsheet": true,
  "name": "text",
  "progress": 1,
  "subtitle": "text",
  "geometry_type": "Line",
  "refresh_period": "15 min",
  "status": "uploading",
  "type": "layer",
  "ordering_key": 1,
  "style": {},
  "tile_url": "text",
  "links": {
    "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
  }
}

Updating a layer's details

Update a layer's name or move it into or out of a layer group.

To move a layer into a group, set the layer_group_id to the id of the layer group you want to move the layer into. To move a layer out of a group, set the layer_group_id to null.

post

/api/v2/maps/{map_id}/layers

Path parameters
map_idstringrequired
Body
idstring felt_idrequired
Example: nOFB8jOFSne1DuDr2uFn4A
layer_group_idnullable string felt_id
Example: KFFhKAbvS4anD3wxtwNEpD
namestring
Example: My Layer
ordering_keyinteger
subtitlestring
Example: A very interesting dataset
refresh_periodenum
Options: 15 min, 30 min, hour, 3 hours, 6 hours, 12 hours, day, week, month, disabled
Responses
curl -L \
  --request POST \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers' \
  --header 'Content-Type: application/json' \
  --data '[{"id":"nOFB8jOFSne1DuDr2uFn4A","layer_group_id":"KFFhKAbvS4anD3wxtwNEpD","name":"My Layer","subtitle":"A very interesting dataset","refresh_period":"15 min"}]'
[
  {
    "hide_from_legend": true,
    "id": "k441enUxQUOnZqc1ZvNsDA",
    "is_spreadsheet": true,
    "name": "text",
    "progress": 1,
    "subtitle": "text",
    "geometry_type": "Line",
    "refresh_period": "15 min",
    "status": "uploading",
    "type": "layer",
    "ordering_key": 1,
    "style": {},
    "tile_url": "text",
    "links": {
      "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
    }
  }
]

Layer groups

Get details of a layer group

get

/api/v2/maps/{map_id}/layer_groups/{layer_group_id}

Path parameters
map_idstringrequired
layer_group_idstringrequired
Responses
curl -L \
  --url 'https://felt.com/api/v2/maps/{map_id}/layer_groups/{layer_group_id}'
{
  "id": "v13k4Ae9BRjCHHdPP5Fcm6D",
  "name": "text",
  "subtitle": "text",
  "type": "layer_group",
  "ordering_key": 1,
  "links": {
    "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
  },
  "layers": [
    {
      "hide_from_legend": true,
      "id": "k441enUxQUOnZqc1ZvNsDA",
      "is_spreadsheet": true,
      "name": "text",
      "progress": 1,
      "subtitle": "text",
      "geometry_type": "Line",
      "refresh_period": "15 min",
      "status": "uploading",
      "type": "layer",
      "ordering_key": 1,
      "style": {},
      "tile_url": "text",
      "links": {
        "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
      }
    }
  ]
}

Delete a layer group

delete

/api/v2/maps/{map_id}/layer_groups/{layer_group_id}

Path parameters
map_idstringrequired

The ID of the map to delete the layer group from

layer_group_idstringrequired

The ID of the layer group to delete

Responses
curl -L \
  --request DELETE \
  --url 'https://felt.com/api/v2/maps/{map_id}/layer_groups/{layer_group_id}'

No body

Create or update layer groups

Provide an array of layer group objects to create new groups or update existing ones.

For each layer group object, including an existing ID will result in the group's details (name, subtitle and legend order) being updated. If no layer group ID is provided (or a non-existent one is provided), a new layer group will be created.

post

/api/v2/maps/{map_id}/layer_groups

Path parameters
map_idstringrequired
Body
idstring felt_id
Example: OI22G7wJRzOo2p1RQeHIPB
namestringrequired
Example: My Layer Group
ordering_keyinteger
subtitlestring
Example: A very interesting group
Responses
curl -L \
  --request POST \
  --url 'https://felt.com/api/v2/maps/{map_id}/layer_groups' \
  --header 'Content-Type: application/json' \
  --data '[{"id":"OI22G7wJRzOo2p1RQeHIPB","name":"My Layer Group","subtitle":"A very interesting group"}]'
[
  {
    "id": "v13k4Ae9BRjCHHdPP5Fcm6D",
    "name": "text",
    "subtitle": "text",
    "type": "layer_group",
    "ordering_key": 1,
    "links": {
      "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
    },
    "layers": [
      {
        "hide_from_legend": true,
        "id": "k441enUxQUOnZqc1ZvNsDA",
        "is_spreadsheet": true,
        "name": "text",
        "progress": 1,
        "subtitle": "text",
        "geometry_type": "Line",
        "refresh_period": "15 min",
        "status": "uploading",
        "type": "layer",
        "ordering_key": 1,
        "style": {},
        "tile_url": "text",
        "links": {
          "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
        }
      }
    ]
  }
]

Layer library

Listing layers

List all layers in your workspace's Library

get

/api/v2/library

Authorizations
Query parameters
sourceenum

Defaults to listing library layers for your "workspace". Use "felt" to list layers from the Felt data library. Use "all" to list layers from both sources.

Options: workspace, felt, all
Responses
curl -L \
  --url 'https://felt.com/api/v2/library' \
  --header 'Authorization: YOUR_API_KEY'
{
  "type": "layer_library",
  "layer_groups": [
    {
      "id": "v13k4Ae9BRjCHHdPP5Fcm6D",
      "name": "text",
      "subtitle": "text",
      "type": "layer_group",
      "ordering_key": 1,
      "links": {
        "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
      },
      "layers": [
        {
          "hide_from_legend": true,
          "id": "k441enUxQUOnZqc1ZvNsDA",
          "is_spreadsheet": true,
          "name": "text",
          "progress": 1,
          "subtitle": "text",
          "geometry_type": "Line",
          "refresh_period": "15 min",
          "status": "uploading",
          "type": "layer",
          "ordering_key": 1,
          "style": {},
          "tile_url": "text",
          "links": {
            "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
          }
        }
      ]
    }
  ],
  "layers": [
    {
      "hide_from_legend": true,
      "id": "k441enUxQUOnZqc1ZvNsDA",
      "is_spreadsheet": true,
      "name": "text",
      "progress": 1,
      "subtitle": "text",
      "geometry_type": "Line",
      "refresh_period": "15 min",
      "status": "uploading",
      "type": "layer",
      "ordering_key": 1,
      "style": {},
      "tile_url": "text",
      "links": {
        "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
      }
    }
  ]
}

Publishing a layer

Publish a layer to your workspace's library

post

/api/v2/maps/{map_id}/layers/{layer_id}/publish

Path parameters
map_idstringrequired

The ID of the map where the layer is located

layer_idstringrequired

The ID of the layer to publish

Body
namestring

The name to publish the layer under

Example: My Layer
Responses
curl -L \
  --request POST \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/publish' \
  --header 'Content-Type: application/json' \
  --data '{"name":"My Layer"}'
{
  "hide_from_legend": true,
  "id": "k441enUxQUOnZqc1ZvNsDA",
  "is_spreadsheet": true,
  "name": "text",
  "progress": 1,
  "subtitle": "text",
  "geometry_type": "Line",
  "refresh_period": "15 min",
  "status": "uploading",
  "type": "layer",
  "ordering_key": 1,
  "style": {},
  "tile_url": "text",
  "links": {
    "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
  }
}

Publishing a layer group

Publish a layer group to your workspace's library

post

/api/v2/maps/{map_id}/layer_groups/{layer_group_id}/publish

Path parameters
map_idstringrequired

The ID of the map where the layer group is located

layer_group_idstringrequired

The ID of the layer group to publish

Body
namestring

The name to publish the layer group under

Example: My Layer Group
Responses
curl -L \
  --request POST \
  --url 'https://felt.com/api/v2/maps/{map_id}/layer_groups/{layer_group_id}/publish' \
  --header 'Content-Type: application/json' \
  --data '{"name":"My Layer Group"}'
{
  "id": "v13k4Ae9BRjCHHdPP5Fcm6D",
  "name": "text",
  "subtitle": "text",
  "type": "layer_group",
  "ordering_key": 1,
  "links": {
    "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
  },
  "layers": [
    {
      "hide_from_legend": true,
      "id": "k441enUxQUOnZqc1ZvNsDA",
      "is_spreadsheet": true,
      "name": "text",
      "progress": 1,
      "subtitle": "text",
      "geometry_type": "Line",
      "refresh_period": "15 min",
      "status": "uploading",
      "type": "layer",
      "ordering_key": 1,
      "style": {},
      "tile_url": "text",
      "links": {
        "self": "/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
      }
    }
  ]
}

Downloading layers

Get a link to export a layer as a GeoPackage (vector layers) or GeoTIFF (raster layers)

get

/api/v2/maps/{map_id}/layers/{layer_id}/get_export_link

Path parameters
map_idstringrequired

The ID of the map where the layer is located

layer_idstringrequired

The ID of the layer to export

Responses
curl -L \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/get_export_link'
{
  "export_link": "text"
}

Create Custom Export Request

Create an export request of a layer as a GeoPackage, GeoJSON, or CSV. Optionally include filters with the layer. Export requests are asynchronous. A successful response will return a poll_endpoint to check the status of the export.

post

/api/v2/maps/{map_id}/layers/{layer_id}/custom_export

Path parameters
map_idstringrequired

The ID of the map where the layer is located

layer_idstringrequired

The ID of the layer to export

Body
output_formatenumrequired
Example: csv
Options: csv, gpkg, geojson
email_on_completionboolean

Send an email to the requesting user when the export completes. Defaults to true

filtersarray

Filters for the layer in specified in Felt Style Language filter format

Responses
curl -L \
  --request POST \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/custom_export' \
  --header 'Content-Type: application/json' \
  --data '{"output_format":"csv","filters":[]}'
{
  "export_request_id": "OI22G7wJRzOo2p1RQeHIPB",
  "poll_endpoint": "http://felt.com/api/v2/maps/vAbZ5eKqRoGe4sCH8nHW8D/layers/7kF9Cfz45TUWIiuuWV8uZ7A/custom_exports/auFxn9BO4RrGGiKrGfaS7ZB"
}

Poll Custom Export Request

Check the status of an Custom Export. If successful, the response will include a download_url

get

/api/v2/maps/{map_id}/layers/{layer_id}/custom_exports/{export_id}

Path parameters
map_idstringrequired

The ID of the map where the layer is located

layer_idstringrequired

The ID of the layer to export

export_idstringrequired

The ID of the export

Responses
curl -L \
  --url 'https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/custom_exports/{export_id}'
{
  "download_url": "https://us1.data-pipeline.felt.com/fcdfd96c-06fa-40b9-9ae9-ad034b5a66df/Felt-Export.zip",
  "export_id": "FZWQjWZJSZWvW3yn9BeV9AyA",
  "filters": [],
  "status": "completed"
}

Duplicating layers

Duplicate an array of layers or layer groups to a map

post

/api/v2/duplicate_layers

Body
itemsone of
Responses
curl -L \
  --request POST \
  --url 'https://felt.com/api/v2/duplicate_layers' \
  --header 'Content-Type: application/json' \
  --data '[{"destination_map_id":"xXv83D7SSkmX9B3rxNGtYgB","source_layer_id":"OI22G7wJRzOo2p1RQeHIPB"}]'
{
  "layers": [
    {
      "hide_from_legend": true,
      "id": "k441enUxQUOnZqc1ZvNsDA",
      "is_spreadsheet": true,
      "name": "text",
      "progress": 1,
      "subtitle": "text",
      "geometry_type": "Line",
      "refresh_period": "15 min",
      "status": "uploading",
      "type": "layer",
      "ordering_key": 1,
      "style": {},
      "tile_url": "text",
      "links": {
        "self": "/api/v2/maps/fZsGO9C5oRFuM8Fn7nCcZ3B/layers/k441enUxQUOnZqc1ZvNsDA"
      }
    }
  ],
  "layer_groups": [
    {
      "id": "v13k4Ae9BRjCHHdPP5Fcm6D",
      "name": "text",
      "subtitle": "text",
      "type": "layer_group",
      "ordering_key": 1,
      "links": {
        "self": "/api/v2/maps/fZsGO9C5oRFuM8Fn7nCcZ3B/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
      },
      "layers": [
        {
          "hide_from_legend": true,
          "id": "k441enUxQUOnZqc1ZvNsDA",
          "is_spreadsheet": true,
          "name": "text",
          "progress": 1,
          "subtitle": "text",
          "geometry_type": "Line",
          "refresh_period": "15 min",
          "status": "uploading",
          "type": "layer",
          "ordering_key": 1,
          "style": {},
          "tile_url": "text",
          "links": {
            "self": "/api/v2/maps/fZsGO9C5oRFuM8Fn7nCcZ3B/layers/k441enUxQUOnZqc1ZvNsDA"
          }
        }
      ]
    }
  ]
}

Last updated

Was this helpful?