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 enoughFor 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.
The ID of the map to upload the layer to.
A public URL containing geodata to import, in place of uploading a file.
(Image uploads only) The latitude of the image center.
(Image uploads only) The longitude of the image center.
The display name for the new layer.
(Image uploads only) The zoom level of the image.
POST /api/v2/maps/{map_id}/upload HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 311
{
"hints": [
{
"attributes": {
"lat": "text",
"lng": "text"
}
}
],
"import_url": "text",
"lat": 1,
"lng": 1,
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"zoom": 1
}
{
"layer_group_id": "luCHyMruTQ6ozGk3gPJfEB",
"layer_id": "luCHyMruTQ6ozGk3gPJfEB",
"presigned_attributes": {},
"type": "upload_response",
"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 enoughFor 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.
The ID of the map hosting the layer to refresh
The ID of the layer to refresh
POST /api/v2/maps/{map_id}/layers/{layer_id}/refresh HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Accept: */*
{
"layer_group_id": "luCHyMruTQ6ozGk3gPJfEB",
"layer_id": "luCHyMruTQ6ozGk3gPJfEB",
"presigned_attributes": {},
"type": "upload_response",
"url": "text"
}
Deleting a layer
The ID of the map to delete the layer from
The ID of the layer to delete
DELETE /api/v2/maps/{map_id}/layers/{layer_id} HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Accept: */*
No content
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 layersThe ID of the map where the layer is located
The ID of the layer to update the style of
The new layer style, specified in Felt Style Language format
POST /api/v2/maps/{map_id}/layers/{layer_id}/update_style HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 12
{
"style": {}
}
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
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 HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Accept: */*
[
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
]
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} HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Accept: */*
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
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
.
A very interesting dataset
luCHyMruTQ6ozGk3gPJfEB
luCHyMruTQ6ozGk3gPJfEB
My Layer
Deprecated: use caption
instead.
POST /api/v2/maps/{map_id}/layers HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 373
[
{
"caption": "A very interesting dataset",
"id": "luCHyMruTQ6ozGk3gPJfEB",
"layer_group_id": "luCHyMruTQ6ozGk3gPJfEB",
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "My Layer",
"ordering_key": 1,
"refresh_period": "15 min"
}
]
[
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
]
Layer groups
Get details of a layer group
GET /api/v2/maps/{map_id}/layer_groups/{layer_group_id} HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Accept: */*
{
"caption": "text",
"id": "luCHyMruTQ6ozGk3gPJfEB",
"layers": [
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
],
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
},
"name": "text",
"ordering_key": 1,
"type": "layer_group",
"visibility_interaction": "default"
}
Delete a layer group
The ID of the map to delete the layer group from
The ID of the layer group to delete
DELETE /api/v2/maps/{map_id}/layer_groups/{layer_group_id} HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Accept: */*
No content
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.
A very interesting group
luCHyMruTQ6ozGk3gPJfEB
My Layer Group
Deprecated: use caption
instead.
Controls how the layer group is displayed in the legend. Defaults to "default"
.
POST /api/v2/maps/{map_id}/layer_groups HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 146
[
{
"caption": "A very interesting group",
"id": "luCHyMruTQ6ozGk3gPJfEB",
"name": "My Layer Group",
"ordering_key": 1,
"visibility_interaction": "default"
}
]
[
{
"caption": "text",
"id": "luCHyMruTQ6ozGk3gPJfEB",
"layers": [
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
],
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
},
"name": "text",
"ordering_key": 1,
"type": "layer_group",
"visibility_interaction": "default"
}
]
Update a single layer group
A very interesting group
luCHyMruTQ6ozGk3gPJfEB
My Layer Group
Deprecated: use caption
instead.
Controls how the layer group is displayed in the legend. Defaults to "default"
.
POST /api/v2/maps/{map_id}/layer_groups/{layer_group_id} HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 144
{
"caption": "A very interesting group",
"id": "luCHyMruTQ6ozGk3gPJfEB",
"name": "My Layer Group",
"ordering_key": 1,
"visibility_interaction": "default"
}
{
"caption": "text",
"id": "luCHyMruTQ6ozGk3gPJfEB",
"layers": [
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
],
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
},
"name": "text",
"ordering_key": 1,
"type": "layer_group",
"visibility_interaction": "default"
}
Layer library
Listing layers
List all layers in your workspace's library, or the felt layer library. You can add a layer from the library to a map by using the duplicate_layers
API endpoint and the layer ID provided by this endpoint.
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.
workspace
Possible values: GET /api/v2/library HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Accept: */*
{
"layer_groups": [
{
"caption": "text",
"id": "luCHyMruTQ6ozGk3gPJfEB",
"layers": [
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
],
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
},
"name": "text",
"ordering_key": 1,
"type": "layer_group",
"visibility_interaction": "default"
}
],
"layers": [
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
],
"type": "layer_library"
}
Publishing a layer
Publish a layer to your workspace's library
The ID of the map where the layer is located
The ID of the layer to publish
The name to publish the layer under
My Layer
POST /api/v2/maps/{map_id}/layers/{layer_id}/publish HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 19
{
"name": "My Layer"
}
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
Publishing a layer group
Publish a layer group to your workspace's library
The ID of the map where the layer group is located
The ID of the layer group to publish
The name to publish the layer group under
My Layer
POST /api/v2/maps/{map_id}/layer_groups/{layer_group_id}/publish HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 19
{
"name": "My Layer"
}
{
"caption": "text",
"id": "luCHyMruTQ6ozGk3gPJfEB",
"layers": [
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
],
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
},
"name": "text",
"ordering_key": 1,
"type": "layer_group",
"visibility_interaction": "default"
}
Downloading layers
Get a link to export a layer as a GeoPackage (vector layers) or GeoTIFF (raster layers)
The ID of the map where the layer is located
The ID of the layer to export
GET /api/v2/maps/{map_id}/layers/{layer_id}/get_export_link HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Accept: */*
{
"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.
The ID of the map where the layer is located
The ID of the layer to export
Send an email to the requesting user when the export completes. Defaults to true
csv
Possible values: POST /api/v2/maps/{map_id}/layers/{layer_id}/custom_export HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 63
{
"email_on_completion": true,
"filters": [],
"output_format": "csv"
}
{
"export_request_id": "luCHyMruTQ6ozGk3gPJfEB",
"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
The ID of the map where the layer is located
The ID of the layer to export
The ID of the export
GET /api/v2/maps/{map_id}/layers/{layer_id}/custom_exports/{export_id} HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Accept: */*
{
"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 HTTP/1.1
Host: felt.com
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Accept: */*
Content-Length: 92
[
{
"destination_map_id": "luCHyMruTQ6ozGk3gPJfEB",
"source_layer_id": "luCHyMruTQ6ozGk3gPJfEB"
}
]
{
"layer_groups": [
{
"caption": "text",
"id": "luCHyMruTQ6ozGk3gPJfEB",
"layers": [
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
],
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
},
"name": "text",
"ordering_key": 1,
"type": "layer_group",
"visibility_interaction": "default"
}
],
"layers": [
{
"caption": "text",
"geometry_type": "Line",
"hide_from_legend": true,
"id": "luCHyMruTQ6ozGk3gPJfEB",
"is_spreadsheet": true,
"links": {
"self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA"
},
"metadata": {
"attribution_text": "text",
"attribution_url": "text",
"description": "text",
"license": "text",
"source_abbreviation": "text",
"source_name": "text",
"source_url": "text",
"updated_at": "2025-03-24"
},
"name": "text",
"ordering_key": 1,
"progress": 1,
"refresh_period": "15 min",
"status": "uploading",
"style": {},
"tile_url": "text",
"type": "layer"
}
]
}
Last updated
Was this helpful?