Only this pageAll pages
Powered by GitBook
1 of 66

Home

Loading...

REST API

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

JS SDK

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Felt Style Language

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Layer Uploads

APIs to upload data

With these APIs, you can upload your data to create new layers.

API Reference

Styling layers

Understanding layer styles

A layer's style is defined in a JSON-based format called the Felt Style Language, or FSL for short. Editors can view the current style of a layer inside a Felt map by clicking on Actions > Edit style language in a layer's overflow menu (three dots).

Here is an example of a simple visualization, expressed in FSL:

{
  "config": {"labelAttribute": ["type"]},
  "legend": {},
  "paint": {
    "color": "blue",
    "opacity": 0.9,
    "size": 30,
    "strokeColor": "auto",
    "strokeWidth": 1
  },
  "type": "simple",
  "version": "2.3.1"
}

Fetching a layer's current style

A layer's FSL can be retrieved by performing a simple GET request to a layer's endpoint — the response's style field contains the current style object:

# Your API token should look like this:
# FELT_API_TOKEN="felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
FELT_API_TOKEN="<YOUR_API_TOKEN>"
MAP_ID="<YOUR_MAP_ID>"
LAYER_ID="<YOUR_LAYER_ID>"

curl \
  -H "Authorization: Bearer ${FELT_API_TOKEN}" \
  "https://felt.com/api/v2/maps/${MAP_ID}/layers/${LAYER_ID}"
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>"
layer_id = "<YOUR_LAYER_ID>"

r = requests.get(
  f"https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}",
  headers={"Authorization": f"Bearer {api_token}"}
)
assert r.ok
print(r.json())
import os

from felt_python import get_layer_details

# Setting your API token as an env variable can save
# you from repeating it in every function call
os.environ["FELT_API_TOKEN"] = "<YOUR_API_TOKEN>"

map_id = "<YOUR_MAP_ID>"
layer_id = "<YOUR_LAYER_ID>"

layer_details = get_layer_details(map_id, layer_id)
current_style = layer_details["style"]

Updating an existing layer's style

To update a layer's style, we can send a POST request with the new FSL to the same layer's /update_style endpoint.

You can find examples of FSL for different visualization types in of these docs:

  • : same color and size for all features (vector) or pixels (raster).

  • : different color per feature or pixel, based on a categorical attribute

  • : different color or size per feature or pixel, based on a numeric attribute.

  • : a density-based visualization style, for vector point layers.

: aggregate points into hexagonal bins.

  • : imagery, single/multiband numeric, categorical, and hillshade styling for raster layers.

  • curl \
      -X POST \
      "https://felt.com/api/v2/maps/${MAP_ID}/layers/${LAYER_ID}/update_style" \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      --data '{"style": {"paint": {"color": "green", "opacity": 0.9, "size": 30, "strokeColor": "auto", "strokeWidth": 1}, "legend": {}, "type": "simple", "version": "2.3.1"}}'
    new_fsl = {
      "paint": {
        "color": "green",
        "opacity": 0.9,
        "size": 30,
        "strokeColor": "auto",
        "strokeWidth": 1
      },
      "legend": {},
      "type": "simple",
      "version": "2.3.1"
    }
    
    r = requests.post(
      f"https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/update_style",
      json={"style": new_fsl},
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    print(r.json())
    from felt_python import update_layer_style
    
    new_fsl = {
      "paint": {
        "color": "green",
        "opacity": 0.9,
        "size": 30,
        "strokeColor": "auto",
        "strokeWidth": 1
      },
      "legend": {},
      "type": "simple",
      "version": "2.3.1"
    }
    
    update_layer_style(
        map_id=map_id,
        layer_id=layer_id,
        style=new_fsl,
    )

    FSL examples

    the Felt Style Language section
    Simple visualizations
    Categorical visualizations
    Numeric visualizations
    Heatmaps
    H3
    Raster visualizations

    Users

    APIs for user information

    Users represent the people in your workspace.

    With these APIs, you can retrieve user profile information.

    Navigating maps and workspaces

    Workspaces and API tokens

    Workspaces are the place where users in the same organization collaborate and share maps. A user may form part of several workspaces but, at the very least, always forms part of one.

    API tokens are created per-workspace. If you wish to interact with several workspaces via the Felt API, you must create a different API token for each one.

    Working with maps

    Creating a new map

    Creating a new map is as simple as making a POST request to the maps endpoint.

    # Your API token should look like this:
    # FELT_API_TOKEN="felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    FELT_API_TOKEN="
    
    import requests
    
    # Your API token should look like this:
    # api_token = "felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    
    import os
    
    from felt_python import create_map
    
    # Setting your API token as an env variable can save
    # you from repeating it in every function call
    os.environ["FELT_API_TOKEN"] = "<YOUR_API_TOKEN>"
    
    response = create_map(
        title="My newly created map",
        lat=40,
        lon=-3,
        public_access="private",
    )
    map_id = response["id"]

    You should see a response like this (trimmed for brevity):

    {
      "id": "CjU1CMJPTAGofjOK3ICf1D",
      "type": "map",
      "title": "My newly created map",
      "url": "https://felt.com/map/My-newly-created-map-CjU1CMJPTAGofjOK3ICf1D",
      "public_access": "view_only",
      "layers": [],
      "created_at": "2024-05-25T15:51:34"
    }

    Notice the "id" property. Every map has a unique ID, which is also part of the map's URL. Let's take note of it for future API calls.

    Also part of the response is a "url" property, which is the URL to your newly-created map.

    Performing a GET request to a map URL will give you useful information about that map, including title, URL, layers, thumbnail URL, creation and visited timestamps.

    To remove a map from your workspace, simply perform a DELETE request to the map's URL:

    To move a map to a different folder or project, send a POST request to the map's move URL with either a project_id or a folder_id in the body. You can find project IDs by listing your projects with GET /api/v2/projects:

    <YOUR_API_TOKEN>
    "
    curl \
    -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${FELT_API_TOKEN}" \
    "https://felt.com/api/v2/maps" \
    -d '{"title": "My newly created map"}'
    api_token = "<YOUR_API_TOKEN>"
    r = requests.post(
    "https://felt.com/api/v2/maps",
    json={"title": "My newly created map"},
    headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    map_id = r.json()["id"]
    print(r.json())

    Getting a map's details

    Deleting a map

    Moving a map

    curl \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps/${MAP_ID}"
    r = requests.get(
      f"https://felt.com/api/v2/maps/{map_id}",
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    print(r.json())
    from felt_python import get_map
    
    get_map(map_id)
    curl \
      -X DELETE \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps/${MAP_ID}"
    r = requests.delete(
      f"https://felt.com/api/v2/maps/{map_id}",
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    from felt_python import delete_map
    
    delete_map(map_id)
    curl \
      -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps/${MAP_ID}/move" \
      -d "{\"project_id\": \"${PROJECT_ID}\"}"
    r = requests.post(
      f"https://felt.com/api/v2/maps/{map_id}/move",
      json={"project_id": project_id},
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    print(r.json())
    from felt_python import move_map
    
    move_map(map_id, project_id)

    Overview

    Felt’s Developer Tools

    There are a variety of ways to interact with Felt’s modern GIS platform outside of the user interface. They can be grouped into two buckets: tools for programmatically creating and modifying maps, and tools for building custom experiences for map viewers. These tools can be used to solve distinct challenges and also be used in tandem with one another.

    Creating and modifying maps

    Felt’s REST API allows editors to interact with the Felt platform via code, performing actions such as creating new maps, adding data to maps, styling layers, and more. The REST API can be leveraged from any environment that is capable of sending GET and POST requests.

    For Python users, interactions with the REST API are simplified through the felt-python module, which can be installed with pip and used to call the REST API endpoints directly from Python functions.

    Creating custom applications

    Felt’s user interface allows a large amount of customization, offering the ability to generate complex cartographic designs, adding components to create a dashboard, and much more.

    However, sometimes application developers need further control over the experience of viewing and/or interacting with a map. For example, they may want to run custom logic after a user clicks on a feature in a layer, or animate data on the map based on other types of user input elsewhere on the webpage. For these situations and many more, Felt’s JavaScript SDK allows developers to programmatically control maps in two ways: Extensions let you write custom code directly within Felt maps, with access to all SDK functionality. Alternatively, you can Felt maps into your own applications and use the SDK to control the embedded map experience.

    References have been updated in the app and documentation, while naming in the REST API and JS SDK remains unchanged. See and for more.

    embed

    Embed Tokens

    APIs to share maps securely

    Embed tokens enable safely sharing your private maps.

    With these APIs, you can generate secure tokens for embedding maps.

    Maps

    APIs for building maps

    Maps are the centerpiece of Felt.

    With these APIs, you can create, retrieve, update, delete, move, and duplicate maps programmatically.

    Note: looking for Element-related documentation? They are now called Annotations.

    Working with annotations
    Drawing annotations

    Print Exports

    APIs to export map images

    With these APIs, you can render a map to a PNG, JPG or PDF image.

    Layers

    APIs to visualize spatial data

    Layers enable you to visualize, style and interact with your spatial data.

    With these APIs, you can upload data, manage layer styling, publish and refresh live data layers.

    Types of visualizations

    The type field chooses how a layer's data is turned into a picture. Pick the type that matches your data and message:

    Type
    Use it for
    Works on

    One uniform style for every feature; raster imagery as-is

    Each page lists the geometry types it applies to, the properties that matter, and worked examples. For the values you'll plug into these styles, see , , and .

    Elements

    APIs for drawing spatially

    Elements enable you to annotate maps with custom shapes, text, and markers.

    With these APIs, you can create, update, and delete map elements.

    Points, lines, polygons, raster

    Categorical

    Color (or icon) by a discrete category

    Points, lines, polygons, raster

    Numeric

    Vary color or size by a numeric value (choropleths, proportional symbols)

    Points, lines, polygons, raster

    Heatmaps

    Point density as a smooth surface

    Points

    H3

    Aggregate points into hexagonal bins

    Points

    Raster

    Imagery, single/multiband numeric, categorical, and hillshade

    Raster

    Colors & palettes
    Icons
    Classification methods
    Simple

    Examples

    A compact, one-per-type overview. For fuller, captioned examples — line casing, proportional symbols, icon-per-category, H3 aggregation popups, raster algebra — see the individual Types of visualizations pages.

    Minimal

    Point (simple)

    Line (simple)

    Polygon (simple)

    Categorical

    Numeric

    Heatmap

    H3

    Raster

    {"version": "2.3.1", "type": "simple", "config": {}, "paint": {}, "label": {}}
    {
      "version": "2.3.1",
      "type": "simple",
      "config": {"labelAttribute": ["name"]},
      "paint": {"color": "#8F7EBF", "size": 4, "strokeColor": "auto", "strokeWidth": 1},
      "label": {"color": "auto", "haloColor": "auto", "placement": ["E"], "offset": [6, 0]}
    }
    {
      "version": "2.3.1",
      "type": "simple",
      "config": {"labelAttribute": ["river_name"]},
      "paint": {"color": "hsl(217, 80%, 40%)", "size": 2},
      "label": {"color": "auto", "fontStyle": "italic", "placement": "Above", "repeatDistance": 200}
    }
    {
      "version": "2.3.1",
      "type": "simple",
      "config": {"labelAttribute": ["name"]},
      "paint": {"color": "#3B82F6", "strokeColor": "auto", "strokeWidth": 1, "opacity": 0.8},
      "label": {"color": "auto", "haloColor": "auto", "placement": ["Center"]}
    }
    {
      "version": "2.3.1",
      "type": "categorical",
      "config": {
        "categoricalAttribute": "primary_fuel",
        "categories": {"type": "top", "count": 6},
        "showOther": true
      },
      "paint": {"color": "@catPalette1", "size": 4, "strokeColor": "auto", "strokeWidth": 1},
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {"numericAttribute": "Renter occupied (%)", "steps": {"type": "jenks", "count": 5}},
      "paint": {"color": "@galaxy", "opacity": 0.9, "strokeColor": "auto", "strokeWidth": 0.5},
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "heatmap",
      "config": {},
      "paint": {"color": "@purpYlPink", "size": 10, "intensity": 0.2, "opacity": 0.9},
      "legend": {"displayName": {"0": "Low", "1": "High"}}
    }
    {
      "version": "2.3.1",
      "type": "h3",
      "config": {
        "aggregation": "sum",
        "numericAttribute": "capacity_mw",
        "baseBinLevel": 3,
        "binMode": "fixed",
        "steps": {"type": "quantiles", "count": 5}
      },
      "paint": {"color": "@riverine"},
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {"band": 1, "steps": {"type": "continuous"}, "noData": [-9999], "rasterResampling": "linear"},
      "paint": {"color": "@mplVirdis", "opacity": 1},
      "legend": {"displayName": "auto"}
    }

    H3

    H3 visualization is a way to aggregate point data into a grid of H3 cells.

    H3 visualizations are defined using "type": "h3" . They generally share the same properties and behaviors as color range visualizations for polygons. Properties of specific relevance to H3 are:

    Field name
    Description

    aggregation

    This is an example of an H3 visualization

    defined with the following style

    aggregation: "count" doesn't need a numericAttribute — it counts the points in each cell:

    H3 cells display aggregated values, not raw feature attributes. Their popups reference special attribute names — "felt:cluster_size" for the feature count, and "felt:sum:column", "felt:mean:column", "felt:min:column", "felt:max:column" for aggregates. If no popup is provided, Felt auto-generates sensible stats from the aggregation type. See .

    Getting started

    The Felt REST API allows you to programmatically interact with the Felt platform, enabling you to integrate Felt's powerful mapping capabilities into your own workflows and pipelines.

    You are able to create and manipulate Maps, Layers, Annotations, Sources, Projects and more.

    The REST API is available on select . Reach out to to learn more or set up a trial.

    All Felt API endpoints are hosted at the following base URL:

    All calls to the Felt API must be authenticated. The easiest way to authenticate your API calls is by creating an API token and providing it as a Bearer token in the request header.

    You can create an API token in the :

    Learn more about API tokens here:

    The easiest way to interact with the Felt API is by using our

    Refreshing live data layers

    It's common to have data update on a regular basis, such as every week or every month. Instead of having to re-upload and style the new data, it can be very convenient to simply refresh a layer using a new data source.

    Just like , refreshing a layer with a new file is a two-step process:

    Perform a POST request to receive an S3 presigned URL which you can later upload your files to:

    Similar to , refreshing an existing URL layer is just a matter of making a single POST

    Working with selection

    The Felt SDK provides functionality for reading the current selection state and selecting features on the map programmatically. This is useful for building interactive experiences that respond to data analysis or user interactions.

    Features are individual data points within layers. You can select features programmatically using the method. Only one feature can be selected at a time - selecting a new feature will replace the current selection.

    The method accepts options to control the selection behavior:

    • showPopup (boolean, default: true) - Whether to display the feature information popup

    Examples

    Explore examples of what you can build with the Felt SDK. These examples showcase different approaches to creating interactive map experiences - from extensions that run directly within Felt to embedded maps in custom applications.

    Extensions run directly within Felt maps, giving you immediate access to all SDK functionality. Here are some examples built using AI assistance:

    Visualize transportation patterns by drawing lines to destination counties on click. Features travel mode options and filtering capabilities to analyze commuting data across different regions. View the map .

    Compare neighborhoods side-by-side with automated analysis of land use patterns. This tool helps users understand demographic and geographic differences between areas. View the map .

    Bring geographic data to life with animations showing the flow of the Mississippi River Basin from headwaters to the Gulf of Mexico, demonstrating how to create compelling temporal visualizations. View the map .

    The aggregation method that will be used on points within each cell. Supported values are count (default), sum, min, max, and mean .

    binMode

    fixed (default), low, medium, high, or auto. fixed keeps the cell resolution constant at all zooms; the other modes pick a resolution from the current zoom, where low produces larger hexagons and high smaller ones (auto behaves like medium).

    baseBinLevel

    Required. If binMode is fixed, this is the H3 cell resolution that the map will use. H3 cells vary from resolution 0 (largest) to resolution 15 (smallest). In the zoom-adaptive modes, this is the reference resolution used for calculating class breaks — you will get best results choosing a resolution that matches the fixed resolution you would choose for the most commonly-viewed zoom of your map.

    numericAttribute

    The numeric column to aggregate. Required unless aggregation is count , in which case the column choice is irrelevant.

    Aggregation popups

    H3 cells are rendered as polygons, so size has no effect on them — control cell size with baseBinLevel (H3 resolution) and binMode (how that resolution adapts to zoom). The attributes block renames the source column, so "revenue" makes a popup entry read "Sum of Revenue ($)".

    the popup block
    request. The refresh re-fetches the layer's existing import URL — the request takes no body, so the URL itself cannot be changed during a refresh:

    A layer must have finished uploading successfully (status of completed) before it can be refreshed — see Monitoring progress

    Refreshing a layer with a file

    Refreshing a file layer is a single function call using the felt-python library.

    1. Request a refresh via the Felt API

    2. Upload your file(s) to Amazon S3

    Refreshing a layer with a URL

    regular file uploads
    a URL upload
    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>"
    layer_id = "<YOUR_LAYER_ID>"
    
    r = requests.post(
      f"https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/refresh",
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    presigned_upload = r.json()
    import os
    
    from felt_python import refresh_file_layer
    
    # Setting your API token as an env variable can save
    # you from repeating it in every function call
    os.environ["FELT_API_TOKEN"] = "<YOUR_API_TOKEN>"
    
    map_id = "<YOUR_MAP_ID>"
    layer_id = "<YOUR_LAYER_ID>"
    new_file_name = "<PATH_TO_NEW_FILE>"
    
    refresh_file_layer(
        map_id=map_id,
        layer_id=layer_id,
        file_name=new_file_name
    )

    fitViewport (boolean | { maxZoom: number }, default: true) - Whether to fit the viewport to the feature. Can be true, false, or an object with maxZoom to limit the zoom level used.

    You can get the current selection state using getSelection(). This returns an array of EntityNode objects, each representing a selected entity. The selection can include various types of entities at the same time, such as annotations and features:

    Remove current selections using clearSelection():

    To stay in sync with selection changes, use the onSelectionChange() method:

    1. Clean up listeners: Always store and call the unsubscribe function when you no longer need to listen for selection changes:

    1. Handle empty selection: Remember that the selection array might be empty if nothing is selected:

    By following these patterns, you can build robust interactions based on what users select in your Felt map.

    Selecting features

    selectFeature()
    selectFeature()

    Reading selection

    Clearing selection

    Reacting to selection changes

    Best practices

    {
      "config": {
        "steps": {"type": "quantiles", "count": 5},
        "aggregation": "sum",
        "binMode": "fixed",
        "baseBinLevel": 3,
        "numericAttribute": "capacity_mw"
      },
      "paint": {"color": "@riverine"},
      "type": "h3",
      "version": "2.3.1",
      "label": {},
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "h3",
      "config": {
        "aggregation": "count",
        "baseBinLevel": 4,
        "binMode": "medium",
        "steps": {"type": "continuous"}
      },
      "paint": {"color": "@galaxy", "opacity": 0.85, "strokeColor": "auto", "strokeWidth": 1},
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "h3",
      "config": {
        "numericAttribute": "revenue",
        "aggregation": "sum",
        "baseBinLevel": 5,
        "binMode": "medium",
        "steps": {"type": "jenks", "count": 5}
      },
      "paint": {"color": "@copper", "opacity": 0.85, "strokeColor": "auto", "strokeWidth": 1, "isClickable": true},
      "popup": {
        "titleAttribute": "felt:sum:revenue",
        "keyAttributes": ["felt:cluster_size", "felt:mean:revenue", "felt:min:revenue", "felt:max:revenue"]
      },
      "attributes": {"revenue": {"displayName": "Revenue ($)", "format": {"thousandSeparated": true, "mantissa": 0}}},
      "legend": {"displayName": "auto"}
    }
    # Your API token and map ID should look like this:
    # FELT_API_TOKEN="felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    FELT_API_TOKEN="<YOUR_API_TOKEN>"
    MAP_ID="<YOUR_MAP_ID>"
    LAYER_ID="<YOUR_LAYER_ID>"
    
    curl \
      -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps/${MAP_ID}/layers/${LAYER_ID}/refresh"
    import requests
    
    # Your API token and map ID should look like this:
    # api_token = "felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    api_token = "<YOUR_API_TOKEN>"
    map_id = "<YOUR_MAP_ID>"
    layer_id = "<YOUR_LAYER_ID>"
    
    r = requests.post(
      f"https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/refresh",
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    print(r.json())
    from felt_python import refresh_url_layer
    
    refresh_url_layer(map_id, layer_id)
    # This code is a continuation of the previous Python code block
    # and assumes you already have a "presigned_upload" variable
    
    file_name = "<YOUR_FILE_WITH_EXTENSION>"  # Example: regions.geojson
    
    url = presigned_upload["url"]
    presigned_attributes = presigned_upload["presigned_attributes"]
    # A 204 response indicates that the upload was successful
    with open(file_name, "rb") as file_obj:
        output = requests.post(
            url,
            # Order is important, file should come at the end
            files={**presigned_attributes, "file": file_obj},
        )
    # Nothing! Refreshing a file layer is a single step with the felt-python library
    await felt.selectFeature({
      id: "feature-123",
      layerId: "buildings-layer"
    });
    await felt.selectFeature({
      id: "feature-123",
      layerId: "buildings-layer",
      showPopup: false,           // Whether to show the feature popup (default: true)
      fitViewport: { maxZoom: 15 } // Fit viewport to feature with zoom limit
    });
    const selection = await felt.getSelection();
    
    console.log(`${selection.length} items selected`);
    
    selection.forEach(node => {
      switch(node.type) {
        case 'feature':
          console.log('Selected feature:', node.entity.id, 'from layer:', node.entity.layerId);
          break;
        case 'element':
          console.log('Selected element:', node.entity.name || node.entity.type);
          break;
      }
    });
    // Clear all selections
    await felt.clearSelection();
    
    // Clear specific types of selections
    await felt.clearSelection({ 
      features: true,   // Clear feature selections
      elements: false   // Keep element selections
    });
    const unsubscribe = felt.onSelectionChange({
      handler: ({ selection }) => {
        // selection is an array of EntityNode objects
        console.log("Selected entities:", selection);
        
        // Check what's selected
        selection.forEach(node => {
          console.log("Entity type:", node.type);
          console.log("Entity ID:", node.entity.id);
        });
      }
    });
    
    // Don't forget to clean up when you're done
    unsubscribe();
    const unsubscribe = felt.onSelectionChange({
      handler: ({ selection }) => {
        // Handle selection...
      }
    });
    
    // Later, when you're done:
    unsubscribe();
    const unsubscribe = felt.onSelectionChange({
      handler: ({ selection }) => {
        if (selection.length === 0) {
          console.log("Nothing is selected");
          return;
        }
        // Handle selection...
      }
    });
    felt-python
    SDK. You can install it with the following command:

    For map management beyond creation — reading details, deleting, moving between projects — see Navigating maps and workspaces.

    Creating a new map is as simple as making a POST request to the maps endpoint.

    # Your API token should look like this:
    # FELT_API_TOKEN="felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    FELT_API_TOKEN="<YOUR_API_TOKEN>"
    
    curl \
      -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps" \
      -d '{"title": "My newly created map"}'
    import requests
    
    # This looks like:
    # api_token = "felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    api_token = "<YOUR_API_TOKEN>"
    
    r = requests.post(
      "https://felt.com/api/v2/maps",
      json={"title": "My newly created map"},
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    map_id = r.json()["id"]
    
    print(r.json())
    import os
    
    from felt_python import create_map
    
    # Setting your API token as an env variable can save
    # you from repeating it in every function call
    os.environ["FELT_API_TOKEN"] = "<YOUR_API_TOKEN>"
    
    response = create_map(
        title="My newly created map",
        lat=40,
        lon=-3,
    )
    map_id = response["id"]

    You should see a response like this (trimmed for brevity):

    Notice the "id" property. Every map has a unique ID, which is also part of the map's URL. Let's take note of it for future API calls.

    Also part of the response is a "url" property, which is the URL to your newly-created map. Feel free to open it! For now, it should just show a blank map.

    This example uploads from a URL; for file uploads and monitoring processing, see Uploading files and URLs.

    Now that we've created a new map, let's add some data to it. We'll need the map_id included in the previous call's response.

    Felt supports many kinds of file and URL imports. In this case, we'll import all the recent earthquakes from the USGS' live GeoJSON feed:

    # Store the map ID from the previous call:
    # MAP_ID="CjU1CMJPTAGofjOK3ICf1D"
    MAP_ID="<YOUR_MAP_ID>"
    
    curl \
      -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps/${MAP_ID}/upload" \
      -d '{"import_url":"https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson", "name": "USGS Earthquakes"}'
    r = requests.post(
      f"https://felt.com/api/v2/maps/{map_id}/upload",
      json={
        "import_url":"https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson",
        "name": "USGS Earthquakes",
      },
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    layer_id = r.json()["layer_id"]
    
    print(r.json())
    from felt_python import upload_url
    
    url_upload = upload_url(
        map_id=map_id,
        layer_url="https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson",
        layer_name="USGS Earthquakes",
    )
    layer_id = url_upload["layer_id"]

    Like maps, layers also have unique identifiers. Let's take note of this one (the layer_id field in the response) so we can style it in the next call.

    You can see the uploaded result in your map:

    Since we imported a live data feed, the points on your layer may look different.

    For reading a layer's current style and more styling patterns, see Styling layers.

    Layers can be styled at upload time or afterwards. Let's change the style of our newly-created earthquakes layer so that points are bigger and in green color:

    # Store the layer ID from the previous call:
    # LAYER_ID="F1XyzAB2TQi9CDeFgHiJkL"
    LAYER_ID="<YOUR_LAYER_ID>"
    
    curl \
      -X POST \
      "https://felt.com/api/v2/maps/${MAP_ID}/layers/${LAYER_ID}/update_style" \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      --data '{"style": {"paint": {"color": "green", "opacity": 0.9, "size": 30, "strokeColor": "auto", "strokeWidth": 1}, "legend": {}, "type": "simple", "version": "2.3.1"}}'
    new_fsl = {
      "paint": {
        "color": "green",
        "opacity": 0.9,
        "size": 30,
        "strokeColor": "auto",
        "strokeWidth": 1
      },
      "legend": {},
      "type": "simple",
      "version": "2.3.1"
    }
    
    r = requests.post(
      f"https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/update_style",
      json={"style": new_fsl},
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    print(r.json())
    from felt_python import update_layer_style
    
    new_fsl = {
      "paint": {
        "color": "green",
        "opacity": 0.9,
        "size": 30,
        "strokeColor": "auto",
        "strokeWidth": 1
      },
      "legend": {},
      "type": "simple",
      "version": "2.3.1"
    }
    
    update_layer_style(
        map_id=map_id,
        layer_id=layer_id,
        style=new_fsl,
    )

    Go to your map to see how your new layer looks:

    Since we imported a live data feed, the points on your layer may look different.

    For refreshing file-based layers and the full refresh flow, see Refreshing live data layers.

    Similar to a URL upload, refreshing an existing URL layer is just a matter of making a single POST request:

    curl \
      -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps/${MAP_ID}/layers/${LAYER_ID}/refresh"
    r = requests.post(
      f"https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}/refresh",
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    print(r.json())
    from felt_python import refresh_url_layer
    
    refresh_url_layer(map_id, layer_id)

    Now go to your map and see if any new earthquakes have occurred!

    • Authentication — token behavior, rotation, and security.

    • Errors and rate limits — what failures look like and how to handle them.

    • Listening to updates using webhooks — react to map changes without polling.

    • API Reference — every endpoint, generated from the OpenAPI spec.

    https://felt.com/api/v2

    Endpoints

    Create an API token

    Install our Python library (optional)

    Enterprise plans
    our team
    Developers tab of the Workspace Settings page
    Authentication
    You can generate as many API tokens as you need. Make sure to copy them to a secure location!
    pip install felt-python
    {
      "id": "CjU1CMJPTAGofjOK3ICf1D",
      "type": "map",
      "title": "My newly created map",
      "url": "https://felt.com/map/My-newly-created-map-CjU1CMJPTAGofjOK3ICf1D",
      "public_access": "view_only",
      "layers": [],
      "created_at": "2024-05-25T15:51:34"
    }

    Example: Creating a new map

    Example: Uploading a layer from a URL

    Example: Styling a layer

    Layer styles are defined in the , a JSON-based specification that allows customizing a layer's style, legend, label and popups.

    Example: Refreshing a live data layer

    A layer must have finished uploading successfully before it can be refreshed

    Next steps

    Guide users through agricultural regions with an interactive narrative experience that combines storytelling with geographic exploration. View the map here.

    Embed Felt maps in your own applications and control them with the SDK. Here are some examples built with React and hosted on CodeSandbox:

    This interactive application leverages the Tool API to enable users to draw custom geometries that retrieve filtered GeoJSON data from an ESRI FeatureService. The application creates a dynamically styled GeoJSON layer to visualize solar potential data, helping users identify optimal locations for solar installations. View the app and code here.

    Create powerful business intelligence tools by combining Felt's layer statistics with popular charting libraries. This example demonstrates how to build interactive visualizations that leverage layer filters. View the app and code here.

    Enhance map usability with a custom legend that extracts and uses FSL styling information to generate SVG icons. The code demonstrates how to build a nested folder structure with visibility toggles using layer filters, providing a pattern for organizing complex data layers. View the app and code here.

    Build comprehensive multi-view dashboards by embedding multiple Felt maps on a single page. This example demonstrates how to create synchronized map views that communicate with each other, enabling users to simultaneously view different geographic contexts or zoom levels of the same data. View the app and code here.

    Create engaging interactive experiences with customizable map lenses that reveal different data layers or styling as users explore. This technique allows for compelling before/after comparisons or the ability to highlight specific data attributes within a defined area. View the app and code here.

    Provides a pattern for integrating third-party geospatial APIs with Felt maps. This example demonstrates how to make API requests based on annotation geometry and map interactions, process the returned data, and visualize isochrones as dynamic layers. View the app and code here.

    Extensions

    Commuter patterns

    Neighborhood comparison

    Animated data

    Story map

    here
    here
    here

    Embedded maps

    Rooftop solar potential

    Sales dashboard

    Custom legend with nested folders

    Inset maps

    Lens map

    Isochrones

    Uploading files and URLs

    Felt supports a myriad of formats, both as files and hosted URLs, up to a limit of 5GB. Check out the full list .

    Uploading a URL

    The easiest way of uploading data into a Felt map via the API is to import from a URL. Here's an example importing all the recent earthquakes from the USGS' live GeoJSON feed:

    # Your API token and map ID should look like this:
    # FELT_API_TOKEN="felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    # MAP_ID="CjU1CMJPTAGofjOK3ICf1D"
    
    import requests
    
    # Your API token should look like this:
    # api_token = "felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    
    import os
    
    from felt_python import upload_url
    
    # Setting your API token as an env variable can save
    # you from repeating it in every function call
    os.environ["FELT_API_TOKEN"] = "<YOUR_API_TOKEN>"
    
    map_id = "<YOUR_MAP_ID>"
    
    url_upload = upload_url(
        map_id=map_id,
        layer_url="https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson",
        layer_name="USGS Earthquakes",
    )
    layer_id = url_upload["layer_id"]

    Like maps, layers also have unique identifiers. Make sure to take note of them for subsequent calls, like styling a layer or removing it.

    Uploading a file

    Uploading a file is a single function call using the felt-python library.

    Files aren't uploaded to the Felt app — instead, they're uploaded directly to Amazon S3. Therefore, creating a layer from a file on your computer is a two-step process:

    1. Request an upload via the Felt API

    Perform a POST request to receive an S3 presigned URL which you can later upload your files to:

    r = 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"},
    )
    assert r.ok
    layer_id = r.json()["layer_id"]
    
    presigned_upload = r.json()
    from felt_python import upload_file
    
    file_name = "<YOUR_FILE_WITH_EXTENSION>" # Example: regions.geojson
    
    upload_file(
      map_id=map_id,
      file_name=file_name,
      layer_name="My new layer",
    )

    You can check the upload status of a layer by querying it. The response includes two useful fields:

    • progress — a number from 0 to 100, the percentage complete. Typed as a float in the API spec, so don't assume an integer.

    • status — one of uploading, processing, completed, or failed.

    Poll until status is completed (or failed). A layer must reach completed before it can be styled or .

    Simple visualizations

    Simple visualizations are those that show each feature in a vector dataset using the same style or the image as it is in raster ones.

    Simple visualizations must define "type": "simple" and a single value for each supported style and label properties.

    Example

    The Airports layer in Felt is an example of a simple visualization using a vector dataset

    and is defined by the following style:

    {
      "attributes": {
        "ele": {"displayName": "Elevation (meters)"},
        "faa": {"displayName": "FAA Code"},
        "iata": {"displayName": "IATA Code"},
        "icao": {"displayName": "ICAO Code"},
        "name": {"displayName": "Name"},
        "name_en": {"displayName": "Name (EN)"},
        "wikipedia": {"displayName": "Wikipedia entry"}
      },
      "config": {"labelAttribute": ["name_en", "name"]},
      "filters": [["name", "isnt", null], "and", ["name", "ne", ""]],
      "label": {
        "color": "hsl(40,30%,40%)",
        "fontSize": {"linear": [[12, 12], [20, 20]]},
        "fontStyle": "Normal",
        "fontWeight": 400,
        "haloColor": "hsl(40,20%,85%)",
        "haloWidth": 1.5,
        "justify": "auto",
        "letterSpacing": 0.1,
        "lineHeight": 1.2,
        "maxLineChars": 10,
        "maxZoom": 23,
        "minZoom": 10,
        "offset": [8, 0],
        "padding": 10,
        "placement": ["E", "W"]
      },
      "legend": {},
      "paint": {
        "color": "hsl(40,30%,80%)",
        "highlightColor": "#EA3891",
        "highlightStrokeColor": "#EA3891",
        "highlightStrokeWidth": {"linear": [[3, 0], [20, 2]]},
        "isSandwiched": false,
        "opacity": 1,
        "size": {"linear": [[3, 1], [20, 6]]},
        "strokeColor": "hsl(40,20%,55%)",
        "strokeWidth": {"linear": [[3, 0.5], [20, 2]]}
      },
      "version": "2.3.1"
    }

    The {"linear": [[zoom, value], …]} objects used for size, fontSize, and strokeWidth above are interpolators — values that change with zoom level. See and for the full syntax; plain numbers work anywhere an interpolator does.

    Raster layers can also use simple to display imagery as-is — see Raster visualizations.

    More patterns

    Icon markers (points). Set iconImage to draw points as icons; the icon takes the layer's color and size. See for the full catalog.

    Road-style casing (lines). A renders last-to-first, so the wider casing layer goes second (underneath) and the narrower fill goes first (on top).

    Layer filters

    The Felt SDK allows you to filter which features are visible in a layer using expressions that evaluate against feature properties. Filters can come from different sources and are combined to determine what's visible.

    Note that filters only work on layers that have been uploaded to and processed by Felt — layers created at runtime with cannot be filtered.

    By understanding how filters work and combine, you can create dynamic views of your data that respond to user interactions and application state.

    Layer filters can come from multiple sources, which are combined to create the final filter:

    1. Style filters: Set by the map creator in the Felt UI

    Getting started

    The Felt Style Language (FSL) is a JSON-based specification for styling data layers in Felt — comparable to the Mapbox Style Spec, but at the layer level. A single JSON object describes how a layer is drawn (paint), labeled (label), classified (config), and presented in popups and legends.

    The same style object works in three places:

    • In the Felt app — open a layer's overflow menu and choose Actions > Edit style language to view and edit the layer's FSL directly. (The neighbouring Actions > Edit styles opens the visual style editor, which has no JSON view.)

    Legends

    Adding a legend block to a visualization makes a legend entry appear for this visualization.

    Each legend entry is shown with the geometry type and color defined by the dataset and the visualization block.

    While simple visualizations will generate a single legend entry, categorical visualizations will generate a legend entry per category.

    The only field is displayName. For categorical visualizations it maps each category to its label; for numeric/heatmap visualizations it maps the index of each class ("0", "1", …) to its label. Set "displayName": "auto" to let Felt generate the labels for you — from the computed breaks for numeric classes, or from the category names for categorical visualizations ("auto"

    Felt Style Language
    FELT_API_TOKEN="<YOUR_API_TOKEN>"
    MAP_ID="<YOUR_MAP_ID>"
    curl \
    -X POST \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer ${FELT_API_TOKEN}" \
    "https://felt.com/api/v2/maps/${MAP_ID}/upload" \
    -d '{"import_url":"https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson", "name": "USGS Earthquakes"}'
    api_token = "<YOUR_API_TOKEN>"
    map_id = "<YOUR_MAP_ID>"
    r = requests.post(
    f"https://felt.com/api/v2/maps/{map_id}/upload",
    json={
    "import_url":"https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_hour.geojson",
    "name": "USGS Earthquakes",
    },
    headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    layer_id = r.json()["layer_id"]

    2. Upload your file(s) to Amazon S3

    Monitoring progress

    refreshed
    in our Help Center
    Icons
    paint array
    Zoom-based styling
    Interpolators
    Component filters: Set through interactive legend components
  • Ephemeral filters: Set temporarily through the SDK

  • You can inspect these different filter sources using getLayerFilters:

    Use setLayerFilters to apply ephemeral filters to a layer:

    This replaces any ephemeral filters currently set on the layer. You can also pass an optional note — a message shown on the layer legend while the filter is applied, along with a reset button that lets the user clear it:

    The following operators are available:

    • Comparison: lt (less than), gt (greater than), le (less than or equal), ge (greater than or equal), eq (equal), ne (not equal)

    • Text: cn (contains), nc (does not contain)

    • Boolean: and, or

    • Lookup: in (contained in list), ni (not contained in list)

    • Null checks: is / isnt (match against null)

    See the filters block for more details on filter operators.

    You can combine multiple conditions using boolean operators:

    Here's a common use case where we filter a layer to show only features that match a property of a selected feature:

    1. Clear filters: Set filters to null to remove them entirely:

    1. Check existing filters: Remember that your ephemeral filters combine with existing style and component filters:

    1. Type safety: Use TypeScript to ensure your filter expressions are valid:

    Understanding filter sources

    createLayersFromGeoJson

    Setting filters

    Filter operators

    Compound filters

    Practical example: Filtering by selected feature

    Best practices

    # This code is a continuation of the previous Python code block
    # and assumes you already have a "presigned_upload" variable
    
    file_name = "<YOUR_FILE_WITH_EXTENSION>" # Example: regions.geojson
    
    url = presigned_upload["url"]
    presigned_attributes = presigned_upload["presigned_attributes"]
    # A 204 response indicates that the upload was successful
    with open(file_name, "rb") as file_obj:
        output = requests.post(
            url,
            # Order is important, file should come at the end
            files={**presigned_attributes, "file": file_obj},
        )
    # Nothing! Uploading a file is a single step with the felt-python library
    curl \
      "https://felt.com/api/v2/maps/${MAP_ID}/layers/${LAYER_ID}" \
      -H "Authorization: Bearer ${FELT_API_TOKEN}"
    r = requests.get(
        f"https://felt.com/api/v2/maps/{map_id}/layers/{layer_id}",
        headers={"Authorization": f"Bearer {api_token}"},
    )
    assert r.ok
    print(r.json()["progress"])
    from felt_python import get_layer_details
    
    get_layer_details(map_id, layer_id)["progress"]
    {
      "version": "2.3.1",
      "type": "simple",
      "filters": ["status", "in", ["active"]],
      "paint": {
        "iconImage": "hospital",
        "iconFrame": "frame-circle",
        "color": "#E74C3C",
        "size": 4,
        "opacity": 0.9,
        "isClickable": true,
        "isHoverable": true
      },
      "legend": {}
    }
    {
      "version": "2.3.1",
      "type": "simple",
      "config": {"labelAttribute": ["name"]},
      "paint": [
        {"color": "#FFFFFF", "size": 4, "lineCap": "round", "lineJoin": "round", "isClickable": true},
        {"color": "#374151", "size": 8, "lineCap": "round", "lineJoin": "round"}
      ],
      "label": {
        "color": "auto",
        "haloColor": "auto",
        "haloWidth": 2,
        "placement": "Above",
        "minZoom": 12
      },
      "legend": {}
    }
    const filters = await felt.getLayerFilters("layer-1");
    console.log(filters.style);      // Base filters from the layer style
    console.log(filters.components); // Filters from legend components
    console.log(filters.ephemeral);  // Filters set through the SDK
    console.log(filters.combined);   // The final result of combining all filters
    felt.setLayerFilters({
      layerId: "layer-1",
      filters: ["POPULATION", "gt", 1000000]
    });
    felt.setLayerFilters({
      layerId: "layer-1",
      filters: ["POPULATION", "gt", 1000000],
      note: "Showing cities with over 1M residents",
    });
    felt.setLayerFilters({
      layerId: "layer-1",
      filters: [
        ["POPULATION", "gt", 1000000],
        "and",
        ["COUNTRY", "eq", "USA"]
      ]
    });
    // Listen for selection changes
    felt.onSelectionChange({
      handler: async ({ selection }) => {
        // Find the first selected feature
        const selectedFeature = selection.find(node => node.type === "feature");
        
        if (selectedFeature) {
          // Get the state code from the selected feature
          const stateCode = selectedFeature.entity.properties.STATE_CODE;
          
          // Filter the counties layer to show only counties in the selected state
          felt.setLayerFilters({
            layerId: "counties-layer",
            filters: ["STATE_CODE", "eq", stateCode]
          });
        } else {
          // Clear the filter when nothing is selected
          felt.setLayerFilters({
            layerId: "counties-layer",
            filters: null
          });
        }
      }
    });
    felt.setLayerFilters({
      layerId: "layer-1",
      filters: null
    });
    const filters = await felt.getLayerFilters("layer-1");
    
    // Check if there are any style filters before adding ephemeral ones
    if (filters.style) {
      console.log("This layer already has style filters");
    }
    import type { Filters } from "@feltmaps/js-sdk";
    
    const filter: Filters = ["POPULATION", "gt", 1000000];
    felt.setLayerFilters({
      layerId: "layer-1",
      filters: filter
    });
  • Via the REST API — read a layer's style field and update it with POST /update_style.

  • Via the JS SDK — apply session-only style changes with setLayerStyle.

  • Every style needs a version and a type. Here is a complete, minimal style that draws a point layer in green with a visible stroke:

    Paste this into Actions > Edit style language on any point layer and the points turn green immediately. From here, styling is incremental: change "type" to "categorical" or "numeric" to drive color or size from your data, add steps or categories to config, and swap literal colors for @palette shortcuts.

    Key
    Purpose

    version

    The FSL version the style is written against. Use "2.3.1" (current). Older versions are accepted and migrated automatically.

    type

    The visualization type: simple, categorical, numeric, heatmap, h3, or hillshade. See .

    config

    Learn how to define and configure the code blocks that compose the Felt Style Language

    Learn about visualization types, including simple, categorical, numeric (color by & size by), heatmaps, H3, and raster (imagery, numeric, categorical, and hillshade).

    Shared building blocks referenced throughout the language: smart "auto" colors and named palettes, the icon catalog, and the classification methods used to turn numbers into classes.

    Vary paint and label properties with the map's zoom level using interpolators.

    Details on how to customize legends on a per-layer basis.

    Definitions for errors raised when validating the Felt Style Language.

    A compact gallery with one worked example per visualization type.

    Where you use FSL

    {
      "version": "2.3.1",
      "type": "simple",
      "config": {},
      "paint": {
        "color": "#28A745",
        "size": 8,
        "strokeColor": "auto",
        "strokeWidth": 1
      },
      "legend": {},
      "label": {},
      "popup": {}
    }

    Your first style

    Anatomy of a style

    Explore the language

    Style definition blocks

    Types of visualizations

    Colors, icons & classification

    Zoom-based styling

    Legends

    Errors

    Examples

    Style definition blocks
    Types of visualizations
    Colors & palettes
    Icons
    Classification methods
    Zoom-based styling
    Legends
    Errors
    Examples
    requires
    steps
    or
    categories
    to be set in
    config
    ). An empty
    legend: {}
    still produces a legend entry using the dataset's geometry and color.

    For continuous (non-stepped) color-by and heatmap legends keyed by index, "0" labels the lowest value and the highest index labels the highest value. Continuous size legends are the historical exception: their indices run inverted, with "0" labeling the maximum, "1" the midpoint, and "2" the minimum.

    The Biodiversity Hotspots layer in Felt has a simple visualization with a legend defined as follows:

    The Plant Hardiness Zones layer in Felt has a categorical visualization with a legend defined as follows:

    The visual display of numeric legends varies based on the style method (stepped or continuous) and the geometry type (point, line, polygon).

    The displayName can be modified in the legend block similar to simple and categorical style types.

    Heatmap legends are defined as follows:

    Notice that the displayName mapping goes from 0 (left value) to 1 (right value)

    The legend block

    "legend": {}
    "legend": {
      "displayName": {
        "13": "13: 60 to 70 °F",
        "12": "12: 50 to 60 °F",
        "11": "11: 40 to 50 °F",
        "10": "10: 30 to 40 °F",
        "9": "9: 20 to 30 °F",
        "8": "8: 10 to 20 °F",
        "7": "7: 0 to 10 °F",
        "6": "6: -10 to 0 °F",
        "5": "5: -20 to -10 °F",
        "4": "4: -30 to -20 °F",
        "3": "3: -40 to -30 °F",
        "2": "2: -50 to -40 °F",
        "1": "1: -60 to -50 °F"
      }
    }
    "legend": {
      "displayName": {
        "0": "5.14 to 19.46",
        "1": "19.46 to 26.43",
        "2": "26.43 to 34.06",
        "3": "34.06 to 45.06",
        "4": "45.06 to 100"
      }
    }
    "legend": {
      "displayName": {
        "0": "2.34M", 
        "1": "714.65K", 
        "2": "33K"
      }
    }
    "legend": {
      "displayName": {
        "0": "Low", 
        "1": "High"
     }
    }

    Simple legend

    Categorical legend

    Numeric legends

    Stepped

    Continuous

    Heatmap legends

    Listening to updates using webhooks

    A great way of building data-driven apps using Felt is by triggering a workflow whenever something changes on a map, like someone drawing a polygon around an area of interest or updating the details on a pin.

    Instead of polling by listing annotations, comments or data layers on a fixed interval, set up a webhook and Felt will send your endpoint a notification any time a map is updated. This allows you to build integrations on top, such as sending a Slack message or recalculating statistics for a newly-drawn area.

    Each webhook is attached to a single map. Whenever the map changes — annotations drawn or edited, layers updated, comments added or resolved — Felt sends a POST request with a JSON body to your webhook URL:

    A few things to know about the delivery model:

    • Event types. map:update

    Icons

    Point layers can be drawn as icons instead of plain circles. Set iconImage in the paint block to a built-in icon slug (or an emoji), and the icon takes on the layer's color and size.

    Icons work in , , and point visualizations. In categorical and numeric styles, iconImage (and the other paint properties) may be an array so each category or class gets its own marker.

    Property

    Classification methods

    , , and (numeric and tinted hillshade) visualizations all turn a range of values into discrete classes (or a smooth gradient) using the steps field in the config block. The classification method decides where the breaks between classes fall.

    Method
    What it does
    Best for

    Authentication

    All calls to the Felt API authenticate with a personal access token sent as a Bearer token in the request header:

    Tokens start with the felt_pat_ prefix. Since a token grants access to your account, store it securely — treat it like a password. Prefer environment variables or a secrets manager over hardcoding tokens in source code.

    You can create an API token in the :

    Be sure to take note of the token before closing the dialog; you won't have a second chance to view it. Only a hash of your token is stored on Felt's servers.

    Projects

    APIs to organize maps

    Projects help you organize maps and manage team permissions.

    With these APIs, you can manage the projects in your workspace.

    Data configuration: which attribute drives the visualization, class breaks, categories, aggregation. See The config block.

    paint

    How geometries and pixels are drawn: colors, sizes, strokes, opacity, icons. See The paint block.

    label

    Feature labels: fonts, halos, placement, zoom range. See The label block.

    popup

    What clicking a feature shows. See The popup block.

    attributes

    Display names and number formatting for attributes. See The attributes block.

    filters

    Which features are visible. See The filters block.

    legend

    Legend labels. See Legends.

    Types of visualizations

    Smooth gradient, no discrete classes

    Proportional symbols, smooth color ramps

    jenks

    Natural breaks — minimizes variance within each class

    Most cases; a good starting point

    quantiles

    Equal number of features in each class

    Balanced representation, evenly distributed data

    equal-intervals

    Equal-sized value bins

    When the value ranges themselves matter

    stddev

    Classes in 1σ steps with the middle class centered on the mean

    Data with a near-normal distribution

    geo-intervals

    Break points in a geometric progression between min and max

    Multiplicative, strongly skewed data (values must be non-negative)

    All shortcut methods except continuous require a count. Raster algebra visualizations support only continuous and equal-intervals.

    There are two ways to define steps.

    Shortcut (recommended when you don't know the data's distribution). Name a method and a class count and let Felt compute the break points from the data:

    For a smooth gradient, use the continuous shortcut:

    Explicit break points (when you know the values you want). Provide the break points directly:

    • Classed: N break points produce N − 1 classes. An explicit color or size array must therefore have exactly N − 1 entries. (A palette shortcut such as @galaxy is expanded for you.)

    • Continuous: provide 2 or more colors and Felt interpolates between them across the full value range. For proportional symbols, give size: [min, max] and sizes scale smoothly between those two values.

    See Numeric visualizations for full color and size examples, and Colors & palettes for palette choices.

    Methods

    Numeric
    H3
    raster

    continuous

    Specifying steps

    How breaks map to colors and sizes

    For choropleths and other classed thematic maps, 5–7 classes usually reads best. For right-skewed data (common with population or income), prefer quantiles or jenks over equal-intervals. When you have the data's min/max on hand, use them to inform the method and breaks.

    Workspace-scoped. Each token belongs to the workspace it was created in and can only access that workspace's resources. Requests against another workspace's resources fail with 401.
  • They act as you. Requests made with your token have your account's permissions in that workspace.

  • No expiry. Tokens remain valid until revoked. To rotate a token, create a new one in workspace settings, switch your integration over, and revoke the old one.

  • Failed authentication returns 401 with a JSON body explaining the problem — see Errors and rate limits.

  • A successful response returns your user details, confirming the token works:

    From here, head to Getting started to create your first map via the API.

    Creating a token

    How tokens behave

    Developers tab of the Workspace Settings page
    Generate as many API tokens as you need
    Give your API token a unique name
    Make sure to copy your token to a secure location

    Making an authenticated request

    {
      "config": {
        "numericAttribute": "population_density",
        "steps": {"type": "jenks", "count": 5}
      }
    }
    {
      "config": {
        "numericAttribute": "temperature",
        "steps": {"type": "continuous"}
      }
    }
    {
      "config": {
        "numericAttribute": "magnitude",
        "steps": [0, 3, 5, 7, 9]
      }
    }
    # This looks like:
    # FELT_API_TOKEN="felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    FELT_API_TOKEN="<YOUR_API_TOKEN>"
    
    curl \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/user"
    import requests
    
    # This looks like:
    # api_token = "felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    api_token = "<YOUR_API_TOKEN>"
    
    r = requests.get(
      "https://felt.com/api/v2/user",
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    print(r.json())
    Authorization: Bearer <API Token>
    {
      "id": "AbC123dEfG456hIjK789lM",
      "type": "user",
      "name": "Your Name",
      "email": "you@example.com"
    }
    is currently the only event type. The payload tells you
    which
    map changed and
    when
    , but not what changed — use the
    , layers, or comments endpoints to fetch the current state when you receive an event.
  • Deliveries are coalesced. A rapid burst of edits to the same map may result in a single notification rather than one per edit. Treat each delivery as "this map changed, re-read it", not as a per-edit event stream.

  • Retries. If your endpoint does not respond with a 2xx status, delivery is retried up to 10 times with exponential backoff. This means delivery is at least once: your handler should be idempotent. Redirects are not followed.

  • Creation is UI-only. Webhooks are created in workspace settings (see below); there are no REST endpoints for managing them.

  • Every webhook has a signing key, shown in the workspace settings UI when you create it. Felt signs each delivery with a felt-signature HTTP header containing the Base64-encoded HMAC-SHA256 of the raw JSON body, computed with that signing key.

    Verify the signature before acting on a payload — it proves the request came from Felt and not from a third party who discovered your URL:

    import base64
    import hashlib
    import hmac
    
    def verify_felt_signature(signing_key: str, raw_body: bytes, signature_header: str) -> bool:
        expected = base64.b64encode(
            hmac.new(signing_key.encode(), raw_body, hashlib.sha256).digest()
        ).decode()
        return hmac.compare_digest(expected, signature_header)
    import { createHmac, timingSafeEqual } from "node:crypto";
    
    function verifyFeltSignature(signingKey, rawBody, signatureHeader) {
      const expected = createHmac("sha256", signingKey).update(rawBody).digest("base64");
      return timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));
    }

    Compute the HMAC over the raw request body exactly as received — re-serializing the parsed JSON can change key order or whitespace and produce a different signature.

    Two things are needed in order to make use of webhooks:

    1. A Felt map which will serve as the basis for the webhook. Updates will be sent whenever something on this map changes.

    2. A webhook URL where the updates will be sent in the form of POST requests.

    Workspace admins and editors can set up webhooks in the Developers tab of the Workspace Settings page.

    Simply click on Create a new webhook, select a map to listen to changes and paste in a webhook URL where the updates will be sent to.

    In order to use webhooks effectively, a receiving service must be set up to trigger actions based on the updates sent by the Felt API. Here are some examples of how to set up a webhook using Felt and an external service.

    {
      "attributes": {
        "type": "map:update",
        "map_id": "Jzjr8gMKSrCOxZ1OSMT49CB",
        "updated_at": "2024-04-29T12:16:46"
      }
    }

    How webhooks work

    Verifying webhook signatures

    Requirements

    Generating a new webhook

    Using your new webhook

    Setting up an example webhook using Pipedream

    is an easy way to collect webhook requests and even run custom code as a result.

    1. Create a free Pipedream account

    2. On the left-hand sidebar, navigate to Sources, then click on New source

    Setting up an example webhook using an AWS Lambda

    Serverless functions like AWS Lambda or Google Cloud Functions are an excellent way of triggering code after a map update by setting them to run after a specific HTTP call.

    1. In the AWS console, navigate to Lambda and click on Create function

    annotations
    Type
    Description

    iconImage

    string | string[]

    An icon slug from the catalog below, or an emoji in the form "emoji::name:".

    iconFrame

    string

    "none", "frame-circle", or "frame-square". Built-in icons only (not emojis).

    iconRotation

    number | string

    Rotation in degrees, or the name of a column to rotate by.

    When iconImage is set, color fills the icon and size scales it (the same size you would use for a circle radius).

    A single icon marker, framed in a circle:

    To give each category its own icon, make iconImage an array — see the icon-per-category example in Categorical visualizations.

    • Shapes: dot, square, diamond, triangle, x, plus, circle-line, circle-slash, circle-triangle, circle-x, circle-plus, star, heart, hexagon, octagon

    • Arrows & directions: arrow-up, chevron-up, double-chevron-up, direction-up (combine with iconRotation to point them anywhere)

    • Transportation: pedestrian, bicycle, wheelchair, airport, car, bus, train, truck, ferry, sailboat, electric-service

    • Activities & places: person, restroom, house, work, letter, hotel, factory, hospital, religious-facility, school, government

    • Infrastructure: zap, battery-full, battery-half, battery-low, boom, radar, wind-turbine, solar-panel, antenna, telephone-pole, oil-well

    • Nature: tree, flower, leaf, fire, mountain, snowy-mountain, volcano, island, wave, hot-springs, water

    • Weather: sun, moon, cloud, partial-sun, rain, lightning, snowflake, wind, snow, fog, sleet

    • Signs: warning, parking, info, circle-exclamation

    To use an emoji as a marker, write it as "emoji::name:" — note the double colon after emoji and the trailing colon. For example: "emoji::fire:", "emoji::tree:". iconFrame does not apply to emojis. Prefer built-in icons unless an emoji is specifically requested.

    Icon paint properties

    simple
    categorical
    numeric
    {
      "version": "2.3.1",
      "type": "simple",
      "paint": {
        "iconImage": "hospital",
        "iconFrame": "frame-circle",
        "color": "#E74C3C",
        "size": 4,
        "opacity": 0.9,
        "isClickable": true
      },
      "legend": {}
    }
    {
      "version": "2.3.1",
      "type": "simple",
      "paint": {
        "iconImage": "emoji::fire:",
        "size": 6
      },
      "legend": {}
    }

    Examples

    Available icons

    Use only the icon slugs listed here. Invented names will not render.

    Emojis

    Layer Exports

    APIs to export layer data

    With these APIs, you can export data to CSV, GeoJSON, and other formats.

    Numeric visualizations (color & size)

    Numeric visualizations use a numeric attribute to either vary colors or sizes between ranges of values and are defined in FSL with "type": "numeric".

    Ranges are calculated across discrete steps using a classification method, or on a continuous scale between an attribute’s min and max values. See for the full list (jenks, quantiles, equal-intervals, stddev, geo-intervals, continuous) and how to express steps.

    Color numeric values in your data using the color property.

    Stepped color

    This map shows the percent of renter occupied housing units by US county. Each county is colored according to the step of ranges it falls into using a sequential color palette where light colors are assigned to low values and darker colors for high values.

    Working with layers

    The Felt SDK allows you to add GeoJSON data to your maps from various sources:

    • Remote URLs

    • Local files

    • Programmatically generated GeoJSON data

    GeoJSON layers created via the SDK are temporary and session-specific - they're not permanently added to the map and won't be visible to other users.

    Style definition blocks

    A style in its most basic form contains a version definition but it can be extended to define how we want geometry and labels to show on the map, how the legend should look like, what information is shown in popups and the formatting used when displaying feature properties.

    The table below describes which properties can be used in the style definition.

    Field name
    Description

    The attributes block

    The attributes block contains information on how attributes will be shown both on the popup and the table. Each attribute definition can contain the following properties:

    Field name
    Description

    Sources

    APIs to connect your data

    Sources connect your databases to Felt.

    With these APIs, you can configure data source connections, credentials, and sync settings to create live maps.

    ,
    gas-service
    ,
    blood-clinic
    ,
    badge
    ,
    traffic-light
    ,
    traffic-cone
    ,
    road-sign-caution
    ,
    university
    ,
    bank
    ,
    landmark
    ,
    museum
    ,
    clothing
    ,
    shopping
    ,
    store
    ,
    bar
    ,
    pub
    ,
    cafe
    ,
    food
    ,
    park
    ,
    amusement-park
    ,
    camping-tent
    ,
    cabin
    ,
    picnic
    ,
    water-refill
    ,
    trailhead
    ,
    guidepost
    ,
    viewpoint
    ,
    camera
    ,
    us-football
    ,
    football
    ,
    tennis
    ,
    binoculars
    ,
    swimming
    ,
    oil-barrel
    ,
    railroad-track
    ,
    bridge
    ,
    lighthouse
    ,
    lock-closed
    ,
    lock-open
    ,
    wifi
    ,
    trash
    ,
    recycle
    ,
    lake
    ,
    ocean
    ,
    animal
    ,
    bird
    ,
    duck
    ,
    dog
    ,
    fish
    ,
    beach
    ,
    wetland
    ,
    hurricane

    iconHideOnZoom

    number

    Zoom level below which icons are drawn as plain points instead. Optional.

    in the top-right corner.
  • Select HTTP / Webhook, then New Requests (Payload Only), and give your newly-created source a name.

  • Copy the endpoint URL. It will look like https://XXX.m.pipedream.net

  • In Felt, navigate to the Developers tab of your workspace settings and click on Create new webhook

  • Paste the endpoint URL from Pipedream into the Webhook URL text field, select your map in the dropdown and click Create.

  • To test your webhook:

    1. Navigate to the Felt map that's linked to the webhook

    2. Make any change: add a pin, draw with the marker, change the color of a polygon, update sharing permissions...

    3. Back in Pipedream, verify that new events appear for the new source. Note that Pipedream wraps the request in its own envelope — the body field shown by Pipedream is the payload Felt sent:

    1. You may also configure a script to run using the above input.

    Choose a name and runtime and, under Advanced Settings, make sure to check Enable function URL
  • Set Auth type to NONE and click on Create function

  • In the next screen, copy the Function URL. It should look like https://{LAMBDA_ID}.lambda-url.{REGION}.on.aws

  • Continue configuring your Lambda function as usual by editing the code that will run on map updates

  • In Felt:

    1. Navigate to the Developers tab of your workspace settings and click on Create new webhook

    2. Paste the function URL from AWS into the Webhook URL text field, select your map in the dropdown and click Create.

    Since the function URL uses Auth type: NONE, anyone who discovers the URL can invoke it — make sure your function verifies the felt-signature header before doing any work.

    Pipedream's RequestBin
    When creating a GeoJSON layer, you can specify different styles for each geometry type (Point, Line, Polygon) that might be found in the source. Each geometry type will create its own layer. It's important to note that GeoJSON layers added via the SDK have limited capabilities compared to regular Felt layers - they cannot be filtered, nor can statistics be fetched for them.

    Use the createLayersFromGeoJson method to add GeoJSON layers to your map. This method accepts different source types depending on where your GeoJSON data comes from.

    To create a layer from a GeoJSON file at a remote URL:

    To create a layer from a GeoJSON file on the user's device:

    To create a layer from GeoJSON data that you've generated or processed in your application. This approach is useful when you need to dynamically generate GeoJSON data based on user interactions or other app states:

    When creating GeoJSON layers, you can specify different styles for each geometry type that might be found in your data. The SDK will create separate layers for each geometry type:

    Each style should be a valid FSL (Felt Style Language) style. If you don't specify styles, Felt will apply default styles based on the geometry type.

    To remove a GeoJSON layer:

    Note that this only works for layers created via the SDK's createLayersFromGeoJson method, not for layers added through the Felt UI.

    For GeoJSON layers created from URLs, you can set automatic refreshing:

    At Creation Time: By setting the refreshInterval parameter when creating the layer. The refreshInterval parameter is optional and specifies how frequently (in milliseconds) the layer should be automatically refreshed from the URL. Valid values range from 250ms to 5 minutes (300,000ms). If set to null or omitted, the layer won't refresh automatically.

    Manual refresh: Replace the source property of any layer you have created, using the updateLayer method to update the source data:

    Creating GeoJSON layers

    From a URL

    From a local file

    From GeoJSON data

    Styling by geometry type

    Deleting layers

    Refreshing GeoJSON layers

    {
      "body": {
        "attributes": {
          "type": "map:update",
          "updated_at": "2024-04-29T12:16:46",
          "map_id": "Jzjr8gMKSrCOxZ1OSMT49CB"
        }
      }
    }
    const layerResult = await felt.createLayersFromGeoJson({
      source: {
        type: "geoJsonUrl",
        url: "https://example.com/data/neighborhoods.geojson",
        // Optional: Auto-refresh every 30 seconds
        refreshInterval: 30000
      },
      name: "Neighborhoods",
      caption: "Neighborhood boundaries for the city", // Optional
      description: "This layer shows the official neighborhood boundaries" // Optional
    });
    
    if (layerResult) {
      console.log("Created layer group:", layerResult.layerGroup);
      console.log("Created layers:", layerResult.layers);
    }
    // Assuming you have a File object from a file input
    const fileInput = document.getElementById('geojson-upload');
    const file = fileInput.files[0];
    
    const layerResult = await felt.createLayersFromGeoJson({
      source: {
        type: "geoJsonFile",
        file: file
      },
      name: "User Uploaded Data"
    });
    
    if (layerResult) {
      // Store the layer ID for later reference
      const layerId = layerResult.layers[0].id;
    }
    const geojsonData = {
      type: "FeatureCollection",
      features: [
        {
          type: "Feature",
          geometry: {
            type: "Point",
            coordinates: [-122.4194, 37.7749]
          },
          properties: {
            name: "San Francisco",
            population: 874961
          }
        },
        // Additional features...
      ]
    };
    
    const layerResult = await felt.createLayersFromGeoJson({
      source: {
        type: "geoJsonData",
        data: geojsonData
      },
      name: "Dynamic Points"
    });
    const layerResult = await felt.createLayersFromGeoJson({
      name: "Styled Features",
      source: {
        type: "geoJsonUrl",
        url: "https://example.com/data/mixed-features.geojson"
      },
      geometryStyles: {
        Point: {
          paint: { 
            color: "red", 
            size: 8 
          }
        },
        Line: {
          paint: { 
            color: "blue", 
            size: 4 
          },
          config: { 
            labelAttribute: ["name"] 
          },
          label: { 
            minZoom: 0 
          }
        },
        Polygon: {
          paint: { 
            color: "green", 
            strokeColor: "darkgreen",
            fillOpacity: 0.5
          }
        }
      }
    });
    await felt.deleteLayer("layer-1");
    const layerResult = await felt.createLayersFromGeoJson({
      source: {
        type: "geoJsonUrl",
        url: "https://example.com/data/realtime-sensors.geojson",
        refreshInterval: 60000  // Refresh every minute
      },
      name: "Live Sensor Data"
    });
    await felt.updateLayer({
      id: layer.id,
      source: {
        type: "geoJsonData",
        data: updatedFeatureCollection,
      },
    });
    Map link: Percent renter occupied housing by county

    The style for this map is defined

    • with the visualization type: numeric

    • numericAttribute: "Renter occupied (%)" and the computed steps using Jenks Natural Breaks over 5 classes

    • the sequential @galaxy palette, which Felt expands to one color per class — light colors for low values, dark for high

    Continuous Color

    The map below shows average accumulated precipitation in the State of California between the years 1900 - 1960 and is colored along a continuous range between the min and max of the precipitation values.

    Map link: Average annual precipitation

    In this case, the numeric style is applied using a continuous method.

    • In the config block, numericAttribute: PRECIP uses the {"type": "continuous"} steps shortcut, so values scale across the attribute's full min–max range

    • The color property uses the sequential @purpYl palette, whose colors are interpolated to give each precipitation value a unique color

    Numeric color also works on raster datasets, using band instead of numericAttribute — see Raster visualizations.

    Size numeric values in your point or line data using the size property.

    Stepped size

    The map below shows earthquakes over the past year sized with 5 manually defined steps.

    In this case, the numeric style is applied using a classed method.

    • In the config block, the numericAttribute: mag has manually-defined steps for 5 classes

    • The size property has an array of five sizes, one for each defined class

    Map link: Earthquakes Stepped Size

    Continuous size

    The map below shows tonnes of corn that have been exported from Ukraine since August 2022 under the UN’s Black Sea Grain Initiative. The symbol size for each country is proportionate to its value in the data.

    Map link: Black Sea Grain Initiative

    To do this the min and max steps from the numericAttribute: tonnes are interpolated to be proportionately sized between a min and max point size — size:[5,48]

    • Let Felt compute breaks when you don't have the data in front of you: "steps": {"type": "jenks", "count": 5}. Provide explicit breaks ([0, 3, 5, 7, 9]) when you know the values you want. See Classification methods.

    • Classed arrays carry one value per class. With N break points you get N − 1 classes, so explicit color/size arrays need N − 1 entries.

    • Continuous size is written as [min, max] (e.g. [3, 30]) and scales smoothly; proportional-symbol sizes typically range 3–30 px for points. On lines, size is width in pixels (typically 1–20 px), not a radius.

    • Continuous size legends use inverted indices for historical reasons: "0" labels the maximum value, "1" the midpoint, and "2" the minimum (as in the example above). Continuous color legends run the intuitive way: "0" is the minimum. See .

    • Icons can vary by value too — set iconImage and let size (or color) carry the numeric variable:

    Vary color or size, not both at once — pick the single visual variable that best carries your message. Color reads as a choropleth; size reads as proportional symbols ("bigger = more"). Polygons support color only.

    Color

    Classification methods
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {
        "numericAttribute": "Renter occupied (%)",
        "steps": {"type": "jenks", "count": 5}
      },
      "paint": {
        "color": "@galaxy",
        "opacity": 0.9,
        "strokeColor": "auto",
        "strokeWidth": 0.5,
        "isSandwiched": true
      },
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {
        "numericAttribute": "PRECIP",
        "steps": {"type": "continuous"}
      },
      "paint": {
        "color": "@purpYl",
        "opacity": 0.9,
        "strokeColor": "auto",
        "strokeWidth": 0,
        "isClickable": false,
        "isSandwiched": true
      },
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {"numericAttribute": "mag", "steps": [4.5, 5.5, 6, 7, 7.5, 8.2]},
      "legend": {"displayName": "auto"},
      "paint": {
        "size": [5, 10, 12, 14, 16],
        "color": "hsl(0, 13%, 45%)",
        "opacity": 0.9,
        "strokeColor": "hsl(0, 13%, 88%)",
        "strokeWidth": 1.5
      }
    }
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {
        "steps": [33000, 2344684],
        "numericAttribute": "tonnes",
        "labelAttribute": ["category"]
      },
      "label": {
        "minZoom": 1,
        "color": "#5a5a5a",
        "fontSize": 14,
        "fontStyle": "Normal",
        "fontWeight": 500,
        "haloColor": "#d0d0d0",
        "haloWidth": 1.5,
        "offset": [8, 0]
      },
      "legend": {"displayName": {"0": "2.34M", "1": "714.65K", "2": "33K"}},
      "paint": {
        "size": [5, 48],
        "color": "hsl(22, 78%, 65%)",
        "opacity": 0.9,
        "strokeColor": "hsl(22, 78%, 88%)",
        "strokeWidth": 1.5
      }
    }
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {"numericAttribute": "beds", "steps": {"type": "jenks", "count": 4}},
      "paint": {
        "iconImage": "hospital",
        "iconFrame": "frame-circle",
        "color": "#E74C3C",
        "size": [3, 4, 5, 6],
        "opacity": 0.9,
        "isClickable": true
      },
      "legend": {"displayName": "auto"}
    }

    Any time there are fewer colors than values in a numeric style, they are interpolated in the ().

    Size

    Notes on steps, color, and size

    type

    Optional. One of , , , , , or (for raster) . Defaults to simple.

    config

    Optional. A block that contains some configuration options to be used across the style. .

    paint

    Optional. An object (or array of objects) that defines how the data will be drawn.

    label

    Optional. An object that defines how the labels will be drawn.

    legend

    Optional. Defines how this layer will be shown on the layer panel.

    popup

    Optional. Defines how the popup is shown and what’s included.

    attributes

    Optional. Defines how attributes are shown both in the popup and the table.

    filters

    Optional. A data filter definition that defines which data will be rendered.

    All of these keys are siblings at the top level of the object — none are nested inside another:

    version

    Mandatory. Defines which version this style adheres to. The current version is "2.3.1".

    The shape of a style definition

    {
      "version": "2.3.1",
      "type": "simple",
      "config": {},
      "paint": {},
      "label": {},
      "legend": {},
      "popup": {}
    }

    The block that controls how geometry and raster pixels are drawn is named paint. (Some earlier drafts of this guide referred to it as style.)

    format accepts any valid numbro format object — common keys include mantissa (decimal places), thousandSeparated, average (compact notation like 1.2M), output ("percent", "currency"), and prefix/postfix. The object is validated by numbro itself, so anything numbro accepts is valid.

    Felt adds one extra key on top of numbro: unit, for displaying measurements. Supported values: meter, kilometer, foot, mile, square_meter, hectare, square_kilometer, square_foot, acre, square_mile, and the adaptive auto-distance and auto-area.

    displayName

    Optional. How this attribute will be shown in different parts of the Felt UI.

    format

    Optional. A object that encodes how numeric fields should be shown.

    Example of an attributes block
    "attributes": {
      "faa": {
        "displayName": "FAA Code",
        "format": {
          "mantissa": 0,
          "thousandSeparated": true
        }
      },
      "wikipedia": {"displayName": "Wikipedia"}
    }
    "attributes": {
      "parcel_area": {
        "displayName": "Parcel area",
        "format": {"mantissa": 1, "unit": "auto-area"}
      }
    }

    The format object

    Drawing annotations

    References have been updated in the app and documentation, while REST API endpoint and JS SDK method naming remain unchanged.

    The Felt SDK provides two main approaches for creating annotations on your maps:

    1. Interactive Drawing: Configure and activate drawing tools for users to create annotations manually

    2. Programmatic Creation: Create and modify annotations directly through code

    Annotations created via the SDK are session-specific - they're not persisted to the map and won't be visible to other users.

    Interactive drawing with tools

    The methods on the ToolsController enable you to programmatically activate drawing tools for your users, as well as setting various options for the tools, such as color, line width, etc.

    Use the method to activate a particular tool.

    Use the method to configure the options for a specific tool.

    Use the and to be notified of changes to the above, or read them instantaneously with the and methods.

    As the user creates annotations with the tools, you can be notified of them being created and updated using the and listeners. See for more details.

    Tool name
    Annotation Type
    Description

    If you want to create annotations programmatically instead of letting your users draw them interactively on the map, use the methods in the .

    To create annotations, use the method.

    To update annotations, use the method.

    To delete annotations, use the method.

    When annotations are created programmatically, they also trigger notifications about the corresponding changes to annotations, via onElementCreate, onElementChange and onElementDelete.

    Extract the geometric representation of annotations using the method.

    The geometry is returned in GeoJSON geometry format, which can be quite different to the way the annotation is specified in Felt. For example, Circle annotations in Felt have their geometry converted into a polygon, representing the area covered by the circle.

    Note: Text, Note, and Image annotations do not return geometry as they are considered screen annotations rather than true "geospatial" annotations.

    Every change that is made to the annotations on a map results in a call to either , or .

    There are two different ways for listening to annotations being created, and the one you use depends on how the annotation is being created, and at what point you want to know about an annotation's creation.

    When the user is creating annotations with tools, they are often created in a number of steps, such as drawing a marker stroke or creating a polygon with many vertices.

    When you want to know when the user has finished creating the annotation (e.g. the polygon was closed or the marker stroke ended) then you should use the listener.

    When annotations are created programmatically, they do not trigger the event.

    Annotations created using Tools or will trigger the event, with an extra property stating whether the annotation is still being created.

    Here is an example showing the power of the Felt SDK, where in just a few lines of code you can allow your users to draw annotations and have them sent to your own backend systems for persistence or analysis.

    Assuming you have embedded your Felt map as described in , and in your own UI you have added a polygon-tool button and a reset-tool button, all you need is the following:

    Heatmaps

    Heatmaps are used to visualize the density of points on a map.

    Heatmaps work on point layers only, and show concentration rather than individual feature values — if you need to read a specific attribute, use a numeric visualization instead. The config block must be empty ({}), and heatmaps support no popups or labels.

    Heatmap visualizations are defined using "type": "heatmap" and allow the following properties to be set:

    Field name
    Type
    Default
    Typical range
    Description

    Tune size for the zoom you expect to view at — larger at low zoom, smaller at high zoom.

    This is an example of a heatmap visualization

    defined with the following visualization

    Zoom-based styling

    Zoom-based styling is useful to change how features and labels are shown at different zoom levels.

    Most of the properties used on the paint and label blocks can be defined using interpolators to enable zoom-based styling — the property tables on those pages mark which ones accept an Interpolator.

    We support multiple types of interpolators: Step functions, linear, exponential and cubic bezier to enable your map looking like you want at each zoom level. See the Interpolators page.

    An example of a layer changing feature colors depending on the zoom level can be found below

    "paint": {
      "color": {"linear": [[14, "red"], [20, "blue"]]}
    }

    On zoom levels lower than 14, features of this layer will be rendered in red color. On zoom levels higher than 20, features of this layer will be rendered in blue color.

    In zooms between 14 and 20, color will be linearly interpolated between red and blue.

    Comments

    APIs for programatic collaboration

    Comments bring conversations to mapping.

    With these APIs, you can export, resolve, and delete map comments and collaboration threads.

    The config block

    The config block contains configuration options for a given visualization.

    These are the fields that each config block can contain:

    Field name
    Description

    Controlling maps

    The Felt SDK has a number of methods for interacting with maps, depending on how you set up your HTML.

    All Felt maps are embedded in iframes, and the SDK can do this for you or can connect to an existing Felt iframe.

    Felt map IDs are unique identifiers for Felt maps. They are used to embed maps in iframes, and to connect to existing iframes.

    To get the ID of a Felt map, click the Map settings button in the main toolbar, and then you can see the Map ID in the Developers section.

    Alternatively, you can look at the URL of the map. For example, the map at https://felt.com/map/Map-title-xPV9BqMuYQxmUraVWy9C89BNA has the ID xPV9BqMuYQxmUraVWy9C89BNA.

    Throughout the documentation, we'll use the placeholder FELT_MAP_ID to refer to a Felt map ID.

    Layer Library

    APIs to publish layers

    With these APIs, you can publish your layers to your workspace library.

    simple
    categorical
    numeric
    heatmap
    h3
    hillshade
    Learn more
    Learn more.
    Learn more.
    Learn more.
    Learn more.
    Learn more.
    Learn more.
    numbro
    Features at zoom level 14
    Features at zoom level 17
    Features at zoom level 20
    Legends
    hcl color space

    route

    Line

    Creates a line that follows the routing logic depending on the mode of transport selected. For instance, walking, driving and cycling routes follow applicable roads and pathways to reach the waypoints the user provides. Flying routes follow great circle paths.

    polygon

    Polygon

    Creates an enclosed area with straight edges

    circle

    Circle

    A circle is defined by its center and radius.

    marker

    Marker

    Freeform drawing with a pen-like rendering. Different sizes can be set for the pen. The geometry produced is in world-space, so as you zoom the map, the pen strokes remain in place.

    highlighter

    Highlighter

    Represents an area of interest, created by drawing with a thick pen. By default, drawing an enclosed shape fills the interior.

    text

    Text

    A label placed on the map with no background color.

    note

    Note

    A label placed on the map with a rectangular background color and either white or black text.

    pin

    Place

    Creates a single point on a map, with a symbol and optional label

    line

    Line

    Tool types

    Example

    Programmatic annotation creation

    Example

    Retrieving annotation geometry

    Listening for changes

    Listening for annotation creation

    Sample application: sending annotations drawn by users to your backend

    Note: Annotations were previously referred to as Elements.

    setTool
    setToolSettings
    onToolChange
    onToolSettingsChange
    getTool
    getToolSettings
    onElementCreate
    onElementChange
    ElementsController
    createElement
    updateElement
    deleteElement
    getElementGeometry
    onElementCreate
    onElementDelete
    onElementChange
    onElementCreateEnd
    onElementCreateEnd
    createElement
    onElementCreate
    Getting started
    Listening for annotation creation

    Creates a sequence of straight lines through the points that the user clicks

    number

    0.5

    0.1–3.0

    How quickly density saturates. Higher = more contrast.

    opacity

    number

    0.9

    0–1

    Transparency.

    color

    string

    "@geyser"

    —

    A heatmap palette name, from less density to more.

    size

    number

    10

    1–30 px

    Radius of influence in pixels. Larger = smoother, smaller = more detailed.

    intensity

    Create an HTML page with a container element:

    Embed a Felt map in your container element and use the SDK to control it by calling Felt.embed, passing the container element as the first argument:

    Felt.embed also takes a third argument with options controlling the embed's UI, initial viewport, and authentication — see Embed options.

    In some cases, you may want to add a "template" iframe to your page. This can be useful if you want to style your iframe in a specific way, or if you already have one map embedded and want to mount and control a different map.

    In this case, you can call Felt.embed with the iframe element as the first argument:

    There may be cases where you already have a Felt map embedded in an iframe, and you want to control it using the SDK. This can be useful if your HTML is server-rendered with the Felt map already embedded.

    In this case, you can call Felt.connect with the iframe's window as the first argument:

    Note that in this case, you don't need to pass the Felt map ID to Felt.connect, because we are connecting to a map that has already been embedded.

    Felt map IDs

    Using Felt.embed to create an iframe

    Using Felt.embed to mount into an existing iframe

    Using Felt.connect to connect to an existing embedded Felt map

    // Configure the line tool
    felt.setToolSettings({
      tool: "line",
      strokeWidth: 8,
      color: "#448C2A"
    });
    
    // Activate the line tool
    felt.setTool("line");
    
    // Later, deactivate the tool
    felt.setTool(null);
    
    // Create a polygon
    const polygonElement = await felt.createElement({
      type: "Polygon",
      coordinates: [
        [
          [-122.42, 37.78],
          [-122.41, 37.78],
          [-122.41, 37.77],
          [-122.42, 37.77],
          [-122.42, 37.78]
        ]
      ],
      color: "#FF5733",
      fillOpacity: 0.5
    });
    
    
    // Update its properties
    await felt.updateElement({
      id: polygonElement.id,
      
      // note that we pass the type here, too in order to get correct
      // TypeScript type-checking and autocompletion.
      type: "Polygon",
      
      color: "#ABC123",
      fillOpacity: 0.5,
      strokeWidth: 2
    });
    
    // Finally delete the element
    await felt.deleteElement(polygonElement.id)
    // Get an element's geometry in GeoJSON format
    const geometry = await felt.getElementGeometry("element-1");
    console.log(geometry?.type, geometry?.coordinates);
    // Set up a listener for changes to a polygon
    const unsubscribeChange = felt.onElementChange({
      options: { id: polygonElement.id },
      handler: ({element}) => {
        console.log("Polygon was updated:", element);
      }
    });
    
    // Set up a listener for deletion
    const unsubscribeDelete = felt.onElementDelete({
      options: { id: polygonElement.id },
      handler: () => {
        console.log("Polygon was deleted");
      }
    });
    
    // Later, clean up listeners
    unsubscribeChange();
    unsubscribeDelete();
    // Listen for any element creation
    const unsubscribe = felt.onElementCreate({
      handler: ({ element, isBeingCreated }) => {
        console.log(`New element created with ID: ${element?.id}`);
    
        // Check if the element is still being drawn
        if (isBeingCreated) {
          console.log("User is still creating this element");
        }
      }
    });
    
    // Or listen for when element creation is completed with a tool
    const unsubscribeEnd = felt.onElementCreateEnd({
      handler: ({element}) => {
        console.log(`Element ${element.id} creation finished`);
      }
    });
    
    // Later, clean up listeners
    unsubscribe();
    unsubscribeEnd();
    // Set your initial tool settings in a style that suits your application
    felt.setToolSettings({
      tool: "polygon",
      strokeWidth: 2,
      color: "#FF5733",
      fillOpacity: 0.3,
    });
      
    // Activate the tool when the user clicks a button in your UI
    document.getElementById("polygon-tool").addEventListener("click", () => {
      felt.setTool("polygon");
    });
    
    // Disable the tool when the user clicks a button in your UI
    document.getElementById("reset-tool").addEventListener("click", () => {
      felt.setTool(null);
    });
    
    // Listen for completed polygons
    felt.onElementCreateEnd({
      handler: async ({element}) => {
        // get the polygon geometry that the user just drew
        const geometry = await felt.getElementGeometry(element.id);
        
        // send the polygon to your own backend system
        sendToServer(geometry);
      }
    });
    {
      "version": "2.3.1",
      "type": "heatmap",
      "config": {},
      "legend": {"displayName": {"0": "Low", "1": "High"}},
      "paint": {"color": "@purpYlPink", "size": 10, "intensity": 0.2}
    }
    <html>
      <body>
        <h1>My Felt app</h1>
        <div id="container"></div>
      </body>
    </html>
    import { Felt } from "@feltmaps/js-sdk";
    
    const felt = await Felt.embed(
      document.querySelector("#container"),
      "FELT_MAP_ID",
    );
    
    // Now use the SDK
    const layers = await felt.getLayers();
    const elements = await felt.getElements();
    
    // You also have a reference to the iframe itself:
    felt.iframe.style.width = "50%";
    <html>
      <body>
        <h1>My Felt app</h1>
        <iframe id="my-iframe"></iframe>
      </body>
    </html>
    import { Felt } from "@feltmaps/js-sdk";
    
    const felt = await Felt.embed(
      document.querySelector("#my-iframe"),
      "FELT_MAP_ID",
    );
    <html>
      <body>
        <h1>My Felt app</h1>
        <iframe src="https://felt.com/map/Map-title-xPV9BqMuYQxmUraVWy9C89BNA" id="my-iframe"></iframe>
      </body>
    </html>
    import { Felt } from "@feltmaps/js-sdk";
    
    const felt = await Felt.connect(
      document.querySelector("#my-iframe").contentWindow
    );

    Optional. Used in raster numeric visualizations. The raster band (1-indexed) to read data from — a number, or an array of band numbers for multiband styling.

    baseBinLevel

    Used in visualizations. The (0–15). Country-scale ≈ 3–4, city-scale ≈ 6–7. Sets the cell size when binMode is "fixed"; in the zoom-adaptive modes it serves as the reference resolution that steps values are scaled against.

    binMode

    Used in visualizations. "fixed" (default; uses baseBinLevel at all zooms) or the zoom-adaptive modes "low", "medium"/"auto", and "high" — low means larger hexagons, high means smaller ones.

    categoricalAttribute

    Mandatory for vector categorical visualizations. The attribute that contains the categorical values that will be used. (Raster categorical layers classify raw pixel values instead and omit this field.)

    categories

    Mandatory for a categorical visualization. Either an explicit array of category values, or a shortcut: {"type": "top", "count": N} for the N most common values, {"type": "bottom", "count": N} for the N least common, or {"type": "all"} (raster) for every unique pixel value.

    labelAttribute

    Optional. Defines which dataset attribute or attributes to use for labeling. If multiple values are provided, the first available one will be used.

    method

    Optional. Used in multiband raster numeric visualizations. Maps a spectral index (NDVI/NDMI/NDWI) to its band assignments. See .

    noData

    Optional. Used in raster visualizations. A value or array of values that won’t be shown (e.g. [-9999] for voids, [0] for no-data).

    numericAttribute

    Mandatory for a numeric visualization. The attribute that contains the numeric values used.

    otherOrder

    Optional. Used in categorical visualizations. It can be set to either "below" or "above" to make features that do not match any of the defined categories render below or above the other ones. The default position is "below".

    outOfRangeValues

    Optional. Used in raster numeric visualizations. "color" clamps out-of-range pixels to the nearest class color; "hide" makes them transparent.

    rasterResampling

    Optional. Used in raster numeric (and tinted hillshade) visualizations — not valid for categorical rasters, which always resample nearest. "nearest" preserves exact pixel values; "linear" smoothly interpolates (use for continuous imagery/elevation). Set it explicitly rather than relying on a default.

    showOther

    Optional. Used in categorical visualizations. If set to true it shows all features that do not match any defined category and adds an extra entry as the last item in the legend.

    steps

    Used by numeric, H3, and tinted-hillshade visualizations. Either an explicit array of break points (at least two values), or a shortcut such as {"type": "jenks", "count": 5} or {"type": "continuous"}.

    config is always an object. The examples below show the config block in isolation.

    aggregation

    Optional, for H3 visualizations. How points are aggregated within each cell: "count" (default), "sum", "mean", "min", or "max". All values except "count" also require numericAttribute.

    band

    Categorical config — explicit categories
    "config": {
      "labelAttribute": ["Wikipedia", "faa"],
      "categoricalAttribute": "faa",
      "categories": ["faa-code-1", "faa-code-2", "faa-code-3"],
      "showOther": true,
      "otherOrder": "above"
    }
    Categorical config — top-N shortcut
    "config": {
      "categoricalAttribute": "surface",
      "categories": {"type": "top", "count": 5},
      "showOther": true
    }
    Vector numeric config — automatic classification
    "config": {
      "numericAttribute": "percentage",
      "steps": {"type": "jenks", "count": 5}
    }
    Raster numeric config — single band
    "config": {
      "band": 1,
      "steps": {"type": "continuous"},
      "noData": [-9999],
      "rasterResampling": "nearest"
    }
    H3 config — aggregate points into hexes
    "config": {
      "aggregation": "sum",
      "numericAttribute": "capacity_mw",
      "baseBinLevel": 4,
      "binMode": "medium",
      "steps": {"type": "quantiles", "count": 5}
    }

    Examples

    Errors and rate limits

    Almost every error returned by the Felt API uses the same JSON envelope: an errors array where each entry has a title, a human-readable detail, usually a stable code, and — where applicable — a source telling you which header, parameter, or body field caused the problem.

    {
      "errors": [
        {
          "title": "Not found",
          "detail": "Map not found",
          "code": "not_found",
          "source": { "parameter": "map_id" }
        }
      ]
    }

    Treat code as best-effort rather than guaranteed: a few responses — notably field-validation failures and plan-limit errors — carry only title and detail. Branch on the HTTP status first, and use code to refine when it is present.

    Status
    Code
    Meaning
    What to do

    When handling responses in code, print the error body rather than only asserting success — detail almost always tells you exactly what's wrong:

    Two independent limits apply:

    1. Per-IP request throttle — currently 300 requests per minute per IP address. Exceeding it returns 429 with the too_many_requests code above. Spread bulk work out or batch it (for example, upsert many annotations in one POST /elements call instead of one call per feature).

    2. Plan usage limits — depending on your plan, API usage may also be subject to an overall usage limit. Every API response includes an x-api-limit-exceeded header (true or false

    When you receive a 429, retry with exponential backoff and jitter rather than immediately — and check x-api-limit-exceeded to distinguish the per-IP throttle (false) from a plan usage limit (true).

    List endpoints (GET /projects, GET /library, GET /maps/{map_id}/elements, and so on) currently return all results in a single response — there are no pagination parameters. For very large maps, prefer scoping your reads (for example, listing a single element group) over repeatedly fetching full collections.

    The current API version is v2, served under https://felt.com/api/v2. The machine-readable OpenAPI spec for the exact version in production is always available at:

    Interpolators

    Interpolators

    Interpolators are functions that use the current zoom level to get you a value. The following interpolators are currently supported:

    Step

    { "step": [output0, Stops[]] }: Computes discrete results by evaluating a piecewise-constant function defined by stops on a given input. Returns the output value of the stop with a stop input value just less than the input one. If the input value is less than the input of the first stop, output0 is returned.

    Stops are defined as pairs of [zoom, value] where zoom is the minimum zoom level where value is returned and value can be number | string | boolean. Note that stops need to be defined by increasing zoom level.

    The following image shows the behavior of this definition:

    { "linear": Stops[] }: Linearly interpolates between stop values less than or equal and greater than the input value

    The following image shows the behaviour of this definitions

    { "linear": [number, number] }: Expands to { "linear": [[minZoom, number], [maxZoom, number]] }

    Color linear interpolation is done in the HCL color-space

    { "exp": [number, Stops[]] }: Exponentially interpolates between output stop values less than or equal and greater than the input value. The base parameter controls the rate at which output increases where higher values increase the output value towards the end of the range, lower values increase the output value towards the start of the range, and a base 1 interpolates linearly.

    The used value is computed as follows : (Math.pow(base, progress) - 1) / (Math.pow(base, difference) - 1)

    The following images shows the behaviour of this definition

    { "cubicbezier": [number, number, number, number, Stops[]] }: Interpolates using the bezier curve defined by the curve control points.

    The following images shows the behaviour of this definition

    The popup block

    The popup block contains information on how the popup is displayed and which attributes to show.

    These are the fields that each popup block can contain:

    Field name
    Description

    type

    Optional. "attributes" (default), "iframe", or "html".

    An iframe popup embeds external content. Use the template syntax {{column_name}} (or {{['Column Name']}} for names with spaces) to inject feature values into the URL or HTML.

    An html popup renders a rich HTML template that is authored and stored with the layer in the Felt app — the FSL block only sets "type": "html" plus the common fields above; the template itself is not part of the style.

    hexes show aggregated values rather than raw feature attributes, so their popups reference special attribute names:

    • "felt:cluster_size" — number of features in the hex

    • "felt:sum:column", "felt:mean:column", "felt:min:column", "felt:max:column" — aggregates of column

    The filters block

    The filters block contains information on how the layer is being filtered before displaying. In order for a feature to be shown on the map it must evaluate the filter expression to true.

    Filters are written using a JSON infix notation that looks like one of [identifier, operator, operand], true or false .

    • Valid identifiers are either a feature property or a nested expression.

    H3
    H3 cell resolution
    H3
    Raster visualizations
    classification

    Linear

    Exponential

    Cubic Bezier

    Graph showing a Step interpolator function
    Graph showing a Linear interpolator function

    titleAttribute

    Optional. The attribute (or attributes) used to title the popup if available.

    imageAttribute

    Optional. The attribute that will be used to populate the popup image if available.

    popupLayout

    Optional. One of "table" or "list". The way the popup shows its contents. Defaults to "table".

    popupLocation

    Optional. Where the popup appears: "onMap", "leftSidebar", "rightSidebar", or "modal".

    headerLayout

    Optional. "standard", "compact", or "none".

    keyAttributes

    Optional. A list of attributes to show in the popup following the order defined here. If it’s not defined, only attributes with a value will show. If it’s defined, all listed attributes show even when the selected feature doesn’t include them.

    url

    Iframe popups only. The URL to embed; supports the {{column_name}} template syntax.

    width

    iframe and html popups only. The popup width in pixels.

    height

    iframe and html popups only. The popup height in pixels.

    Iframe and HTML popups

    H3 aggregation attributes

    H3
    Valid operators are:
    • "lt" – Less than

    • "gt" – Greater than

    • "le" – Less than or equal to

    • "ge" – Greater than or equal to

    • "eq" – Equal to

    • "ne" – Not equal to

    • "and" – And, cast to boolean

    • "or" – Or, cast to boolean

    • "cn" – Contains the operand, cast to string

    • "nc" – Does not contain the operand, cast to string

    • "in" – Contained in the operand list

    • "ni" – Not contained in the operand list

    • "is" – Used to match against null values

    • "isnt" – Used to match against null values

  • Operands are:

    • A numerical value, a string value, a boolean value

    • An array of numerical, string, or boolean values, a shorthand expanded to these patterns:

      • Input 1: [id, "in", [element1, …, elementN]]

      • Expansion 1: id is equal ("eq") to one or more of the elements

      • Input 2: [id, "ni", [element1, …, elementN]]

      • Expansion 2: id is not equal ("ne") to any of the elements

      • Not defined for operators other than "in" and "ni"

    • A nested expression

  • In cases of type mismatch cast the identifier value to the operand’s type

    • Type casting applies element-wise to lists with "in" and "ni" operators

    • Case & diacritics: eq, ne, gt, ge, lt, le, cn, and nc compare strings case-insensitively and diacritic-insensitively. ["status", "eq", "active"] matches "Active" and "ACTIVE".

    • in / ni are case-sensitive, unlike the operators above, and do per-element type coercion (["id", "in", [5]] matches a string "5"). in with an empty array always returns false; ni with an empty array always returns true.

    • Null handling: use is / isnt only for null/existence checks (with null as the value) — not for value equality. Most other operators yield null (and filter the feature out) when the column is missing or null.

    • Type coercion: the left-hand value is cast to match the right-hand type, so ["score", "eq", 100] matches whether the column stores 100 or "100".

    There is no single "between" operator — combine two comparisons:

    Check that a value exists and is non-empty:

    Three or more conditions must be written as nested pairs, not a flat list:

    Behavior notes

    Common patterns

    { "step": ["hsl(50,5%,72%)", [[9, "hsl(10,75%,75%)"]]] }
    // If zoom level is less than 9, "hsl(50,5%,72%)" will be returned
    // If zoom level is equal or higher than 9, "hsl(10,75%,75%)" will be returned
    
    { "step": [0, [[0, 0], [100, 100]]]} // Blue
    { "step": [0, [[0, 0], [50, 50], [100, 100]]]} // Red
    { "step": [0, [[0, 0], [25, 25], [50, 50], [75, 75], [100, 100]]]} // Yellow
    
    {
      "linear": [
        [8, 10],
        [14, 15],
        [20, 21]
      ]
    }
    // If zoom level is less than 8, 10 is returned
    // If zoom level is greater or equal than 8 but less than 14, a value linearly interpolated
    // between 10 and 15 is returned
    // If zoom level is greater or equal than 14 but less than 20, a value linearly interpolated // between 15 and 21 is returned
    // If zoom level is greater or equal than 20, 21 is returned
    
    { "linear": [[0, 0], [100, 100]]} // Blue
    { "linear": [[0, 0], [50, 50], [100, 100]]} // Red
    { "linear": [[0, 0], [25, 25], [50, 50], [75, 75], [100, 100]]} // Yellow
    
    { "linear": [8, 10] }
    // If minZoom is defined as 3 and maxZoom is defined as 20:
    // If zoom level is less than 3, 8 is returned
    // If zoom level is between 3 and 20, a value linearly interpolated between 8 and 10 is
    // returned
    // If zoom level is greater or equal than 20, 10 is returned
    
    {
      "exp": [
        0.25,
        [
          [0, 25],
          [10, 100]
        ]
      ]
    }
    // If zoom level is less than 0, 25 is returned
    // If zoom level z is between 0 and 10, an interpolation factor is computed between 0 and 10
    // and then it's used to interpolate between 25 and 100
    // If zoom level is equal or higher than 10, 100 will be returned
    
    { "exp": [0.25, [[0, 0], [100, 100]]]} // Blue
    { "exp": [0.25, [[0, 0], [50, 50], [100, 100]]]} // Red
    { "exp": [0.25, [[0, 0], [25, 25], [50, 50], [75, 75], [100, 100]]]} // Yellow
    { "exp": [0.5, [[0, 0], [100, 100]]]} // Blue
    { "exp": [0.5, [[0, 0], [50, 50], [100, 100]]]} // Red
    { "exp": [0.5, [[0, 0], [25, 25], [50, 50], [75, 75], [100, 100]]]} // Yellow
    { "exp": [0.75, [[0, 0], [100, 100]]]} // Blue
    { "exp": [0.75, [[0, 0], [50, 50], [100, 100]]]} // Red
    { "exp": [0.75, [[0, 0], [25, 25], [50, 50], [75, 75], [100, 100]]]} // Yellow
    { "exp": [1, [[0, 0], [100, 100]]]} // Blue
    { "exp": [1, [[0, 0], [50, 50], [100, 100]]]} // Red
    { "exp": [1, [[0, 0], [25, 25], [50, 50], [75, 75], [100, 100]]]} // Yellow
    { "exp": [1.25, [[0, 0], [100, 100]]]} // Blue
    { "exp": [1.25, [[0, 0], [50, 50], [100, 100]]]} // Red
    { "exp": [1.25, [[0, 0], [25, 25], [50, 50], [75, 75], [100, 100]]]} // Yellow
    { "exp": [2, [[0, 0], [100, 100]]]} // Blue
    { "exp": [2, [[0, 0], [50, 50], [100, 100]]]} // Red
    { "exp": [2, [[0, 0], [25, 25], [50, 50], [75, 75], [100, 100]]]} // Yellow
    { "cubicbezier": [0.25, 0, 0.75, 1.5, [[0, 0], [100, 100]]]} // Blue
    { "cubicbezier": [0.25, 0, 0.75, 1.5, [[0, 0], [50, 50], [100, 100]]]} // Red
    { "cubicbezier": [0.25, 0, 0.75, 1.5, [[0, 0], [25, 25], [50, 50], [75, 75], [100, 100]]]} // Yellow
    Example of a popup block
    "popup": {
      "titleAttribute": "name",
      "keyAttributes": ["osm_id", "highway", "ref", "place"],
      "popupLayout": "list",
      "popupLocation": "onMap",
      "headerLayout": "standard"
    }
    Iframe popup
    "popup": {
      "type": "iframe",
      "url": "https://example.com/details/{{id}}",
      "popupLocation": "modal",
      "width": 600,
      "height": 800
    }
    "popup": {
      "titleAttribute": "felt:sum:revenue",
      "keyAttributes": ["felt:cluster_size", "felt:mean:revenue", "felt:max:revenue"]
    }
    Example of a filter block that filters out features with a value less than 50000 on the acres property
    "filters": ["acres", "lt", 50000]
    Example of a more complex filter block
    "filters": [["acres", "ge", 50000], "and", ["acres", "le", 70000]]
    "filters": [["temperature", "ge", 0], "and", ["temperature", "le", 100]]
    "filters": [["name", "isnt", null], "and", ["name", "ne", ""]]
    // WRONG: [a, "and", b, "and", c]
    // RIGHT:
    "filters": [["a", "eq", 1], "and", [["b", "eq", 2], "or", ["c", "eq", 3]]]

    forbidden, over_storage_limit, over_processing_limit, unauthorized

    Your workspace has hit a plan limit — data hosting or monthly data processing — or the action requires a plan your workspace isn't on.

    Read detail: it names the limit. Reach out to to raise it.

    404

    not_found

    The resource doesn't exist. The source.parameter field names the offending ID.

    Verify the ID. Remember that map IDs come from the map URL, while layer IDs come from API responses.

    422

    invalid

    The request body or parameters failed validation. source.pointer identifies the invalid field.

    Fix the field named in detail / source and retry.

    429

    too_many_requests

    You hit a rate limit (see below).

    Back off and retry later.

    ); if your workspace exceeds its limit, requests return
    429
    . Reach out to
    if you have questions about your plan's API access.

    401

    unauthorized, invalid_access_token

    Missing, malformed, revoked, or wrong-workspace token. Requests with a valid token for a resource in a different workspace also return 401. Permission failures also return 401, not 403 — for example, editing or deleting a map your account can only view.

    Check the Authorization: Bearer header and that the token was created in the same workspace as the resource. If the token is fine, ask a workspace admin for the required role on the resource. See Authentication.

    r = requests.post(url, headers=headers, json=body)
    if not r.ok:
        print(r.status_code, r.json()["errors"])
        r.raise_for_status()
    GET https://felt.com/api/v2/openapi.json

    Status codes

    Rate limits

    Pagination

    Versioning

    403

    our team

    UI components

    Action triggers and custom panels

    The Felt SDK enables you to extend Felt maps with custom UI components that integrate seamlessly with the native interface. These extensions allow you to add interactive controls and custom workflows directly within the map experience.

    UI extension points

    Felt provides two primary ways to add custom UI to your maps:

    Action Triggers appear as buttons in the left sidebar and provide quick access to custom actions. Think of them as shortcuts that users can click to trigger specific functionality in your application.

    Custom Panels appear in the right sidebar and offer a full canvas for complex UI. These panels can contain forms, controls, and interactive elements that work together to create sophisticated user experiences.

    Action triggers

    Action triggers are simple button controls that execute custom functions when clicked. They're perfect for actions that don't require additional user input - like applying filters, running calculations, or enabling an interaction mode.

    await felt.createActionTrigger({
      actionTrigger: {
        label: "Check solar potential",
        onTrigger: async () => {
          // Enable polygon tool to allow a user to select a region
          await felt.setTool("polygon");
          // ...
        },
      }
    });

    Custom panels

    Custom panels provide a structured way to build complex UI within Felt. Each panel consists of three main sections that serve different purposes:

    Panel structure

    Header - Contains the panel title, and an optional close button.

    Body - Houses the main interactive elements like forms, selectors, and content areas. This is where users spend most of their time interacting with your custom functionality.

    Footer - Typically contains primary action buttons like "Save", "Cancel", or "Apply". This creates a consistent pattern users expect from dialog-style interfaces. The footer sticks to the bottom of the panel, with a divider separating it from the body.

    Create a panel by first generating an ID, then specifying its contents. You can control where panels appear using the initialPlacement parameter. When onClickClose is specified, a close button will be rendered in the header.

    Custom panels support a variety of interactive and display elements that can be combined to create rich user experiences:

    display formatted content and support full Markdown rendering, allowing you to include headings, lists, links, and formatting within your panels.

    elements allow users to enter custom values like names, descriptions, or numeric parameters.

    Control elements allow users to choose from predefined options:

    Available control elements include , , , and . Each element supports similar properties:

    trigger actions and come in different styles to communicate their importance and effect. Buttons can have different variants (filled, outlined, and transparent) and tints (primary, accent, danger and default):

    Primary filled buttons highlight the most important action in a context. Use sparingly - typically one per panel section.

    Group related buttons together to create clear action hierarchies:

    automatically handle spacing and alignment, ensuring your panels look polished and consistent.

    helps organize elements within panels to create complex layouts. It uses a grid property that follows the same syntax as the CSS shorthand grid property, and includes verticalAlignment and horizontalDistribution properties for precise control over layout positioning.

    allow you to embed external content by providing a URL to charts, dashboards, or other web applications directly within your panels.

    Divider elements provide visual separation between sections of content in your panels.

    A panel is identified by its ID, which must be created using . Custom IDs are not supported to prevent conflicts with other panels. Use for most panel scenarios. This declarative method lets you specify what the panel should contain, and it handles both creating new panels and updating existing ones with the same API call.

    Use for granular control when you want to modify individual elements. Elements need IDs to be targeted for updates. You can also use to add elements and to remove elements by their IDs.

    Events reference

    Every listener on the Felt controller follows the same pattern: you pass a handler (and sometimes an options object scoping the listener to a specific entity), and the call returns an unsubscribe function.

    const unsubscribe = felt.onLayerChange({
      options: { id: "layer-1" },
      handler: ({ layer }) => console.log(layer.bounds),
    });
    
    // ...later, when you no longer need the listener
    unsubscribe();

    Always call the unsubscribe function when your UI unmounts or the listener is no longer needed.

    Viewport and map state

    Listener
    Scoping options
    Handler receives
    Listener
    Scoping options
    Handler receives
    Listener
    Scoping options
    Handler receives
    Listener
    Scoping options
    Handler receives
    Listener
    Scoping options
    Handler receives

    For payload type details, follow each method's entry in the .

    Integrating with React

    To work with Felt embeds in React, we have a starter template that you can use as a starting point.

    This is available on GitHub in the felt/js-sdk-starter-react repository.

    In that repo, you will find a feltUtils.ts file that demonstrates some ways to make using the Felt SDK in React easier. The SDK itself is framework-agnostic and ships no React bindings — the hooks below are small wrappers you copy into your own project.

    Embedding with useFeltEmbed

    function MyComponent() {
      // get the felt controller (or null if it's not loaded yet) and a ref to the map container
      // into which we can embed the map
      const { felt, mapRef } = useFeltEmbed("FELT_MAP_ID", {
        uiControls: {
          cooperativeGestures: false,
          fullScreenButton: false,
          showLegend: false,
        },
      });
    
      return (
        <div>
          {/* the map container — remember to give it a height in your CSS */}
          <div ref={mapRef} />
    
          {/* a component that uses the Felt controller */}
          <MyFeltApp felt={felt} />
        </div>
      );
    }
    useFeltEmbed implementation

    A few things worth knowing about this hook:

    • The hasLoadedRef guard exists because React's Strict Mode runs effects twice in development — without it you would embed two iframes.

    • The hook embeds once for the component's lifetime: changing mapId

    Getting live data

    A common use case for building apps on Felt is to be notified when entities are updated. The main example of this is when you want to change the visibility of say a layer, and have your own UI reflect that change.

    Rather than keeping track of the visibility of entities yourself, you can use the Felt SDK to listen for changes to the visibility of entities.

    Here is an example of how you might do this for layers assuming you already have a reference to a Layer object, e.g. from calling felt.getLayers():

    Errors

    Style validation errors surface as a banner in the in-app style editor, and as 422 responses with the message in the error detail when styling via the REST API. The JS SDK rejects the setLayerStyle promise with the validation message.

    Unexpected value or type

    Problem: One of the values set in the style has an unsupported value or an invalid type.

    Solution: Change the value to be valid.

    Error messages:

    • Attribute 'displayName' on a legend item of type simple must be a string.

    • Attribute attribute_name is not a number.

    • Attribute attribute_name is not a string.

    • Attribute 'lineCap' is not a supported value. Supported values are butt, round, square.

    • Attribute 'lineJoin' is not a supported value. Supported values are bevel, round, miter.

    • Visualization dashArray has to be an array with even length.

    • Attribute 'offset' must be either an array of numbers or a number.

    • Attribute 'placement' contains a not supported value. Supported values are N, NE, E, SE, S, SW, W, NW, Center.

    • Attribute 'placement' contains a not supported value. Supported values are Above, Center, Below.

    • All values in 'labelAttribute' must be a string.

    • Visualization 'type' definition must be one of simple, categorical, numeric, heatmap, hillshade, h3.

    • Attribute 'showOther' must be one of above, below. (Despite the wording, this message refers to the otherOrder field — showOther itself is a boolean, while otherOrder must be "above" or "below".)

    Problem: The style defines a categorical visualization, but the maps are not showing the layer

    Error messages:

    • Categories required. A categories array must be defined in the config block when defining a categorical visualization. Read more about categorical visualizations .

    • Not enough or too many attribute_name values. When defining a categorical visualization, all style and label properties must be an array with either a single value that will apply to all categories or an array with as many values as categories defined in the config block. Read more about categorical visualizations .

    Sample application

    This is a sample application showing how to use the Felt SDK to build an app with the following features:

    • listing the map's layers

    • toggling layer visibility

    • moving the viewport to center it on predefined city locations

    The commented code in its entirety is shown below.

    Categorical visualization not working

    here
    here
    our team
    after mount won't re-embed. If you need to switch maps, remount the component (for example with a
    key={mapId}
    prop).
    export function useLiveLayer(felt: FeltController, initialLayer: Layer) {
      // start with the layer we were given
      const [currentLayer, setLayer] = React.useState<Layer | null>(initialLayer);
    
      // listen for changes to the layer and update our state accordingly
      // (onLayerChange returns its unsubscribe function, so returning it
      // from the effect cleans up the listener on unmount)
      React.useEffect(() => {
        return felt.onLayerChange({
          options: { id: initialLayer.id },
          handler: ({ layer }) => setLayer(layer),
        });
      }, [felt, initialLayer.id]);
    
      // return the live layer
      return currentLayer;
    }
    import {
      Felt,
      FeltController,
      FeltEmbedOptions,
      Layer,
    } from "@feltmaps/js-sdk";
    import React from "react";
    
    export function useFeltEmbed(mapId: string, embedOptions: FeltEmbedOptions) {
      const [felt, setFelt] = React.useState<FeltController | null>(null);
      const hasLoadedRef = React.useRef(false);
      const mapRef = React.useRef<HTMLDivElement>(null);
    
      React.useEffect(() => {
        async function loadFelt() {
          if (hasLoadedRef.current) return;
          if (!mapRef.current) return;
    
          hasLoadedRef.current = true;
          const felt = await Felt.embed(mapRef.current, mapId, embedOptions);
          setFelt(felt);
        }
    
        loadFelt();
      }, []);
    
      return {
        felt,
        mapRef,
      };
    }

    onViewportMove

    —

    ViewportState — fires continuously during movement, including during animations and inertia.

    onViewportMoveEnd

    —

    ViewportState — fires once when dragging, zooming, animations, and inertia have finished.

    onMapIdle

    —

    Nothing. Fires when the map is fully idle: no transitions, no interaction, all tiles loaded, fades complete.

    onBasemapChange

    —

    Basemap — the new basemap.

    onElementCreate

    —

    { element: Element | null, isBeingCreated: boolean } — fires repeatedly while the user draws (isBeingCreated: true), then a final time with isBeingCreated: false.

    onElementCreateEnd

    —

    onLayerChange

    { id }

    { layer: Layer | null }

    onLayerGroupChange

    { id }

    onPointerClick

    —

    MapInteractionEvent — { coordinate, point, features, rasterValues }. features and rasterValues are arrays (empty when nothing is under the pointer).

    onPointerMove

    —

    onToolChange

    —

    ToolType | null — the newly selected tool, or null when no tool is active.

    onToolSettingsChange

    —

    Annotations (elements)

    Layers and legends

    Pointer and selection

    Tools

    API reference
    const panelId = await felt.createPanelId();
    await felt.createOrUpdatePanel({
      panel: {
        id: panelId,
        title: "Add report",
        body: [
          { type: "Select", placeholder: "Choose a neighborhood", options: [{ label: "Downtown", value: "downtown" }] },
          { type: "Select", placeholder: "Choose a severity", options: [{ label: "Low", value: "low" }, { label: "High", value: "high" }] },
          { type: "TextInput", placeholder: "Email", onBlur: storeEmail },
        ],
        footer: [
          {
            type: "ButtonRow",
            align: "end",
            items: [
              { type: "Button", label: "Back", variant: "transparent", tint: "default", onClick: handleBack },
              { type: "Button", label: "Done", variant: "filled", tint: "primary", onClick: handleDone }
            ]
          }
        ],
        onClickClose: async () => {
          // Clean up
          await felt.deletePanel(panelId);
        }
      },
      initialPlacement: { at: "start" } // Optional: control panel positioning
    });
    {
      type: "Text",
      content: "**Welcome!** This is a *formatted* text element with [links](https://felt.com).",
    }
    {
      type: "TextInput",
      placeholder: "First name",
      value: "",
      onChange: (args) => {
        console.log("New value:", args.value);
      },
    }
    // Select dropdown
    {
      type: "Select", // or "CheckboxGroup" | "RadioGroup" | "ToggleGroup"
      label: "Year",
      options: [
        { value: "2025", label: "2025" },
        { value: "2024", label: "2024" },
      ],
      value: "",
      onChange: (args) => {
        console.log("Selected:", args.value);
      }
    }
    {
      type: "Button",
      label: "Submit",
      variant: "filled", // "transparent" | "outlined"
      tint: "primary", // "default" | "accent" | "danger"
      onClick: async () => {
        // Handle button click
      }
    }
    {
      type: "ButtonRow",
      align: "end",
      items: [
        { type: "Button", label: "Clear", variant: "transparent", tint: "default", onClick: handleClear },
        { type: "Button", label: "Send report", variant: "filled", tint: "primary", onClick: handleSend }
      ]
    }
    {
      type: "Grid",
      grid: "auto-flow / 2fr 1fr", // CSS grid shorthand
      verticalAlignment: "start",
      horizontalDistribution: "stretch",
      items: [
        { type: "Text", content: "![image](https://example.com/image1.png)" },
        { type: "Text", content: "![image](https://example.com/image2.png) \n ![image](https://example.com/image3.png)" },
      ]
    }
    {
      type: "Iframe",
      url: "https://example.com/dashboard",
      height: 400,
    }
    {
      type: "Divider",
    }
    const panelId = await felt.createPanelId();
    const greetingElement = { id: "greeting", type: "Text", content: "Hello" };
    
    // Initial state
    await felt.createOrUpdatePanel({
      panel: {
        id: panelId,
        title: "My Panel",
        body: [greetingElement]
      }
    });
    
    // Update using destructuring
    await felt.createOrUpdatePanel({
      panel: {
        id: panelId,
        title: "My Panel",
        body: [{ ...greetingElement, content: "Hello World" }]
      }
    });
    const panelId = await felt.createPanelId();
    
    // Create panel with multiple elements
    await felt.createOrUpdatePanel({
      panel: {
        id: panelId,
        title: "Data Panel",
        body: [
          { id: "status-text", type: "Text", content: "Ready" },
          { 
            id: "layer-select", 
            type: "Select", 
            label: "Choose Layer",
            options: [
              { value: "layer1", label: "Population" },
              { value: "layer2", label: "Income" }
            ]
          }
        ]
      }
    });
    
    // Update only the text element
    await felt.updatePanelElements({
      panelId,
      elements: [{
        element: {
          id: "status-text",
          type: "Text",
          content: "Processing data..."
        }
      }]
    });
    
    // Add a new element to the panel
    await felt.createPanelElements({
      panelId,
      elements: [{
        element: { 
          id: "progress-text", 
          type: "Text", 
          content: "Progress: 50%" 
        },
        container: "body",
        placement: { at: "end" }
      }]
    });
    
    // Remove an element from the panel
    await felt.deletePanelElements({
      panelId,
      elements: ["progress-text"]
    });

    Getting started with panels

    Panel elements

    Text elements

    TextInput elements

    Control elements

    Button elements

    Button rows

    Grid elements

    iframe elements

    Divider elements

    Panel state management

    Creating and updating panels

    Targeted panel element updates

    Text elements
    TextInput
    Select
    CheckboxGroup
    RadioGroup
    ToggleGroup
    Button elements
    Button rows
    The grid element
    iframe elements
    createPanelId
    createOrUpdatePanel
    updatePanelElements
    createPanelElements
    deletePanelElements
    The sample Felt SDK Application

    { element: Element } — fires once, when creation is finished.

    onElementChange

    { id }

    { element: Element | null, isBeingCreated: boolean } — element is null if it was removed.

    onElementDelete

    { id }

    Nothing.

    onElementGroupChange

    { id }

    { elementGroup: ElementGroup | null }

    { layerGroup: LayerGroup | null }

    onLegendItemChange

    { id, layerId }

    { legendItem: LegendItem | null }

    onLayerFiltersChange

    { layerId }

    LayerFilters — the bare filters object ({ style, components, ephemeral, combined }), with no wrapper. See Layer filters.

    onLayerBoundariesChange

    { layerId }

    LayerBoundaries | null

    MapInteractionEvent

    onSelectionChange

    —

    { selection: EntityNode[] } — see Working with selection.

    ToolSettingsChangeEvent — a discriminated union: check the tool field to narrow to that tool's settings.

    <!doctype html>
    <html lang="en">
      <head>
        <title>Felt JS SDK</title>
        <style>
          body {
            margin: 0;
            padding: 0;
            font-family: sans-serif;
            font-size: 13px;
          }
    
          .container {
            display: grid;
            grid-template-columns: 1fr 240px;
            height: 100vh;
          }
    
          iframe {
            display: block;
          }
    
          #sidebar {
            padding: 1rem;
            user-select: none;
          }
    
          #markers {
            margin-bottom: 1rem;
            padding-bottom: 1rem;
            border-bottom: 1px solid #ccc;
          }
    
          .marker {
            cursor: pointer;
            padding: 0.25rem 0;
          }
    
          .layer-toggles_toggle {
            padding: 0.25rem 0;
            margin-left: -4px;
            display: flex;
            align-items: center;
            gap: 0.25rem;
          }
    
          h3 {
            margin: 0;
            margin-bottom: 0.5rem;
          }
        </style>
      </head>
      <body>
        <div class="container">
          <div id="mapContainer"></div>
          <div id="sidebar">
            <div id="markers">
              <h3>Cities</h3>
            </div>
            <div id="layers">
              <h3>Layers</h3>
            </div>
          </div>
        </div>
    
        <script type="module">
          // Load the Felt SDK from the jsDelivr CDN
          import { Felt } from "https://esm.run/@feltmaps/js-sdk";
    
          // Get the map and sidebar elements
          const container = document.getElementById("mapContainer");
          const markerContainer = document.getElementById("markers");
          const layerContainer = document.getElementById("layers");
    
          // Embed the map — replace this ID with your own map's ID
          const felt = await Felt.embed(container, "u49BWs5EtSI29CpwuwB9CzRiC", {
            uiControls: {
              showLegend: false,
              cooperativeGestures: false,
              fullScreenButton: false,
            },
          });
    
          // Add some cities to the sidebar
          const locations = [
            { name: "Oakland", lat: 37.8044, lng: -122.271 },
            { name: "New York", lat: 40.7128, lng: -74.006 },
            { name: "Los Angeles", lat: 34.0522, lng: -118.2437 },
            { name: "Chicago", lat: 41.8781, lng: -87.6298 },
            { name: "Houston", lat: 29.7604, lng: -95.3698 },
            { name: "Phoenix", lat: 33.4484, lng: -112.074 },
          ];
    
          locations.forEach((location) => {
            // create a DOM element with the city name
            const marker = document.createElement("div");
            marker.classList.add("marker");
            marker.innerText = location.name;
    
            // center the viewport on the city when the marker is clicked
            marker.addEventListener("click", () => {
              felt.setViewport({
                center: {
                  latitude: location.lat,
                  longitude: location.lng,
                },
                zoom: 10,
              });
            });
    
            // add the marker to the sidebar
            markerContainer.appendChild(marker);
          });
    
          // get all the layers
          felt.getLayers().then((layers) => {
            layers.forEach((layer) => {
              // create a DOM element to represent the layer
              const layerElement = document.createElement("div");
              layerElement.classList.add("layer-toggles_toggle");
              layerElement.innerHTML = `
                <input type="checkbox" id="${layer.id}" ${
                  layer.visible ? "checked" : ""
                }>
                <label for="${layer.id}">${layer.name}</label>
              `;
    
              // toggle the layer's visibility when the checkbox changes
              const checkbox = layerElement.querySelector("input");
              checkbox.addEventListener("change", () => {
                felt.setLayerVisibility(
                  checkbox.checked ? { show: [layer.id] } : { hide: [layer.id] },
                );
              });
    
              // let the map be the source of truth: keep the checkbox in
              // sync if the layer's visibility changes for any other reason
              felt.onLayerChange({
                options: { id: layer.id },
                handler: ({ layer }) => {
                  if (layer) checkbox.checked = layer.visible;
                },
              });
    
              // add the layer element to the container
              layerContainer.appendChild(layerElement);
            });
          });
        </script>
      </body>
    </html>

    Working with annotations

    References have been updated in the app and documentation, while REST API endpoint and JS SDK method naming remain unchanged.

    Annotations sit on top of all data layers on a map. They are usually drawn in the Felt app, but can also be created and updated via the API.

    Combining annotations with is a great way to create interactive data apps in Felt.

    Listing all annotations on a map

    Annotations are returned as a GeoJSON Feature Collection.

    # Your API token and map ID should look like this:
    # FELT_API_TOKEN="felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    # MAP_ID="CjU1CMJPTAGofjOK3ICf1D"
    
    import requests
    
    # Your API token and map ID should look like this:
    # api_token = "felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
    
    import os
    
    from felt_python import list_elements
    
    # Setting your API token as an env variable can save
    # you from repeating it in every function call
    os.environ["FELT_API_TOKEN"] = "<YOUR_API_TOKEN>"
    
    map_id = "<YOUR_MAP_ID>"
    
    list_elements(map_id)

    Listing all annotation groups

    Returns a list of GeoJSON Feature Collections, one for each annotation group.

    curl \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps/${MAP_ID}/element_groups"
    r = requests.get(
      f"https://felt.com/api/v2/maps/{map_id}/element_groups",
      headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    print(r.json())
    from felt_python import list_element_groups
    
    list_element_groups(map_id)

    Create or update annotations

    Each annotation is represented by a feature in the POSTed GeoJSON Feature Collection.

    For each feature, including an existing annotation ID (felt:id) will result in the annotation being updated on the map. If the ID is omitted or does not match an existing annotation, a new annotation is created.

    Styling is controlled with felt:-prefixed properties on each feature — for example felt:color, felt:opacity, felt:strokeWidth, felt:strokeStyle, felt:size, and felt:text for text annotations. Properties without the felt: prefix are stored as the annotation's data attributes. Request bodies are limited to 1 MB, and very complex geometries may be simplified on import.

    Delete an annotation by its ID. Annotation IDs are returned as the felt:id property when .

    Embed options

    Felt.embed() takes an optional third argument that controls how the embedded map looks and behaves:

    const felt = await Felt.embed(container, FELT_MAP_ID, {
      uiControls: {
        showLegend: false,
        cooperativeGestures: false,
      },
      initialViewport: {
        center: { latitude: 40.7128, longitude: -74.006 },
        zoom: 10,
      },
    });

    UI controls

    All uiControls options are booleans:

    Option
    Default
    Description

    You can change these after the map has loaded with :

    initialViewport overrides the map's saved viewport with a center and zoom for this embed:

    Public and unlisted maps embed with no extra configuration. To embed a private map for visitors who aren't logged into Felt, generate a short-lived embed token server-side with the REST API and pass it as the token option:

    1. Your server calls , using your . The visitor's user_email is a required query parameter, not a body field, and that address should belong to a member of your workspace. The response contains a token valid for 15 minutes.

    2. Your page passes that token to Felt.embed:

    Never call the embed token endpoint from the browser — that would expose your API token. Generate embed tokens on your server and hand only the short-lived token to the client.

    Hiding and showing

    The Felt SDK provides methods to control the visibility of various entities like layers, layer groups, annotation groups, and legend items. These methods are designed to efficiently handle bulk operations.

    Understanding visibility requests

    All visibility methods use a consistent structure that allows both showing and hiding entities in a single call:

    {
      show?: string[],  // IDs of entities to show
      hide?: string[]   // IDs of entities to hide
    }

    Layers

    Control visibility of layers using setLayerVisibility:

    felt.setLayerVisibility({
      show: ["layer-1", "layer-2"],
      hide: ["layer-3"]
    });

    Layer groups

    Control visibility of layer groups using setLayerGroupVisibility:

    felt.setLayerGroupVisibility({
      show: ["group-1", "group-2"],
      hide: ["group-3"]
    });

    Annotation groups

    Similarly, control annotation group visibility with setElementGroupVisibility:

    felt.setElementGroupVisibility({
      show: ["points-group"],
      hide: ["lines-group", "polygons-group"]
    });

    Legend items

    Legend items require both a layer ID and an item ID to identify them. Use setLegendItemVisibility:

    felt.setLegendItemVisibility({
      show: [
        { layerId: "layer-1", id: "item-1" },
        { layerId: "layer-1", id: "item-2" }
      ],
      hide: [
        { layerId: "layer-1", id: "item-3" }
      ]
    });

    Common use cases

    Focusing on a single layer

    To focus on a single layer by hiding all others, first get all layers and then use their IDs:

    When implementing a toggle, you can use empty arrays for the operation you don't need:

    1. Batch operations: Use a single call with multiple IDs rather than making multiple calls:

    1. Omit unused properties: When you only need to show or hide, omit the unused property rather than including it with an empty array:

    Categorical visualizations

    Categorical visualizations use a categorical attribute and the categories within it to apply styling to discrete categories of the attribute. (On raster datasets, categories are raw pixel values instead — see .)

    Categorical visualizations are defined using "type": "categorical" and, for every supported style and label property used, either a single value that will apply to all categories or an array of different values for each category.

    You can list the categories explicitly, or use a shortcut when you don't know the exact values: {"type": "top", "count": N} keeps the N most common values (vector), and {"type": "all"} covers every unique pixel value (raster). When showOther: true is combined with an explicit categories array, paint/label arrays need

    Getting started

    The Felt SDK allows you to control your Felt maps and build powerful, interactive custom applications. You can control many aspects of the Felt UI and map contents, as well as receive notifications of events happening in the map such as clicks, selections, and more.

    This feature is available to customers on the . Reach out to .

    See our page to explore what you can build with the SDK.

    There are two main ways to use the Felt SDK:

    1. Extensions

    2. Embedded maps

    FELT_API_TOKEN="<YOUR_API_TOKEN>"
    MAP_ID="<YOUR_MAP_ID>"
    curl \
    -H "Authorization: Bearer ${FELT_API_TOKEN}" \
    "https://felt.com/api/v2/maps/${MAP_ID}/elements"
    api_token = "<YOUR_API_TOKEN>"
    map_id = "<YOUR_MAP_ID>"
    r = requests.get(
    f"https://felt.com/api/v2/maps/{map_id}/elements",
    headers={"Authorization": f"Bearer {api_token}"}
    )
    assert r.ok
    print(r.json())

    Delete an annotation

    Note: Annotations were previously referred to as Elements.

    listing annotations
    webhooks

    showLegend

    true

    Whether the legend is shown.

    cooperativeGestures

    true

    Adjusted gesture behavior for embeds: on mobile, one-finger drag scrolls the page while two fingers pan the map; on desktop, scroll-to-zoom requires holding Ctrl/Cmd. Disable for app-like embeds where the map is the main content.

    fullScreenButton

    true

    Shows a button that opens the map in a new tab or window.

    geolocation

    false

    Shows a geolocation button that plots and tracks the visitor's position.

    zoomControls

    true

    Shows the zoom controls (bottom right). Hiding them does not prevent zooming.

    scaleBar

    true

    Shows the scale bar.

    Initial viewport

    Embedding private maps

    updateUiControls
    POST /api/v2/maps/{map_id}/embed_token?user_email=…
    API token

    Toggling visibility

    Best practices

    curl \
      -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps/${MAP_ID}/elements" \
      -d '{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"coordinates":[[[15.478752514432728,15.576176978045694],[15.478752514432728,4.005934587045303],[29.892174099255755,4.005934587045303],[29.892174099255755,15.576176978045694],[15.478752514432728,15.576176978045694]]],"type":"Polygon"}}]}'
    new_elements = {
      "type": "FeatureCollection",
      "features": [
        {
          "type": "Feature",
          # Include "felt:id" in properties to update an existing annotation.
          # "felt:" properties control styling; anything else is stored as data.
          "properties": {"felt:color": "#2674BA"},
          "geometry": {
            "coordinates": [
              [
                [
                  15.478752514432728,
                  15.576176978045694
                ],
                [
                  15.478752514432728,
                  4.005934587045303
                ],
                [
                  29.892174099255755,
                  4.005934587045303
                ],
                [
                  29.892174099255755,
                  15.576176978045694
                ],
                [
                  15.478752514432728,
                  15.576176978045694
                ]
              ]
            ],
            "type": "Polygon"
          }
        }
      ]
    }
    
    r = requests.post(
      f"https://felt.com/api/v2/maps/{map_id}/elements",
      headers={"Authorization": f"Bearer {api_token}"},
      json=new_elements
    )
    assert r.ok
    print(r.json())
    from felt_python import upsert_elements
    
    new_elements = {
      "type": "FeatureCollection",
      "features": [
        {
          "type": "Feature",
          "properties": {},
          "geometry": {
            "coordinates": [
              [
                [
                  15.478752514432728,
                  15.576176978045694
                ],
                [
                  15.478752514432728,
                  4.005934587045303
                ],
                [
                  29.892174099255755,
                  4.005934587045303
                ],
                [
                  29.892174099255755,
                  15.576176978045694
                ],
                [
                  15.478752514432728,
                  15.576176978045694
                ]
              ]
            ],
            "type": "Polygon"
          }
        }
      ]
    }
    
    upsert_elements(map_id, new_elements)
    curl \
      -X DELETE \
      -H "Authorization: Bearer ${FELT_API_TOKEN}" \
      "https://felt.com/api/v2/maps/${MAP_ID}/elements/${ELEMENT_ID}"
    element_id = "<YOUR_ELEMENT_ID>"
    
    r = requests.delete(
      f"https://felt.com/api/v2/maps/{map_id}/elements/{element_id}",
      headers={"Authorization": f"Bearer {api_token}"},
    )
    assert r.ok
    from felt_python import delete_element
    
    element_id = "<YOUR_ELEMENT_ID>"
    
    delete_element(map_id, element_id)
    felt.updateUiControls({ showLegend: false });
    initialViewport: {
      center: { latitude: 40.7128, longitude: -74.006 },
      zoom: 10,
    }
    const felt = await Felt.embed(container, FELT_MAP_ID, {
      token: embedTokenFromYourServer,
    });
    const layers = await felt.getLayers();
    const targetLayerId = "important-layer";
    
    felt.setLayerVisibility({
      show: [targetLayerId],
      hide: layers
        .map(layer => layer?.id)
        .filter(id => id && id !== targetLayerId)
    });
    function toggleLayer(layerId: string, visible: boolean) {
      felt.setLayerVisibility({
        show: visible ? [layerId] : [],
        hide: visible ? [] : [layerId]
      });
    }
    // Better approach
    felt.setLayerVisibility({
      show: ["layer-1", "layer-2"],
      hide: ["layer-3", "layer-4"]
    });
    
    // Less efficient approach
    felt.setLayerVisibility({ show: ["layer-1"] });
    felt.setLayerVisibility({ show: ["layer-2"] });
    felt.setLayerVisibility({ hide: ["layer-3"] });
    felt.setLayerVisibility({ hide: ["layer-4"] });
    // Do this
    felt.setLayerVisibility({
      show: ["layer-1"]
    });
    N + 1
    values — the extra one styles the "Other" bucket. For colors, prefer a
    shortcut over a hand-built array.

    The Global Power Plants layer in Felt is an example of a categorical layer on a vector dataset

    and is defined by the following style

    Notice that we are saying that the primary_fuel data attribute will be used to categorize elements and that the possible values of that attribute that we are interested in are "Solar", "Hydro", "Wind", "Gas", "Coal", "Oil" and "Nuclear" (colors are assigned in the same order). Also notice that we are defining either a single value that will apply to all categories (i.e. size) or a value for each category (i.e. color)

    Palette shortcut + "top N". When you don't know the exact category values, let Felt pick the most common ones and color them from a categorical palette:

    A different icon per category. iconImage and the paint arrays follow the same N (or N + 1 with showOther) pattern as color:

    Styling "Other" separately. With showOther: true, the trailing array element targets the "Other" bucket — here it is made smaller and more transparent than the named categories:

    Raster visualizations
    {
      "version": "2.3.1",
      "type": "categorical",
      "config": {
        "categoricalAttribute": "primary_fuel",
        "categories": ["Solar", "Hydro", "Wind", "Gas", "Coal", "Oil", "Nuclear"],
        "showOther": false
      },
      "legend": {"displayName": {}},
      "attributes": {
        "capacity_mw": {"displayName": "Capacity (MW)"},
        "name": {"displayName": "Name"},
        "primary_fuel": {"displayName": "Primary Fuel"}
      },
      "paint": {
        "color": [
          "#E5C550",
          "#7AB6C2",
          "#AB71A4",
          "#CC615C",
          "#AD7B68",
          "#EB9360",
          "#DEA145"
        ],
        "isSandwiched": false,
        "opacity": 1,
        "size": [{"linear": [[3, 1.5], [20, 8]]}]
      }
    }
    {
      "version": "2.3.1",
      "type": "categorical",
      "config": {
        "categoricalAttribute": "fuel_type",
        "categories": {"type": "top", "count": 10},
        "showOther": true
      },
      "paint": {
        "color": "@catPalette4",
        "size": 4,
        "strokeColor": "auto",
        "strokeWidth": 1,
        "opacity": 0.9,
        "isClickable": true
      },
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "categorical",
      "config": {
        "categoricalAttribute": "facility_type",
        "categories": ["hospital", "school", "fire_station"],
        "showOther": true
      },
      "paint": {
        "iconImage": ["hospital", "school", "fire", "dot"],
        "iconFrame": "frame-circle",
        "color": ["#E74C3C", "#3498DB", "#E67E22", "#95A5A6"],
        "size": 4,
        "opacity": 0.9,
        "isClickable": true
      },
      "legend": {
        "displayName": {
          "hospital": "Hospitals",
          "school": "Schools",
          "fire_station": "Fire Stations"
        }
      }
    }
    {
      "version": "2.3.1",
      "type": "categorical",
      "config": {
        "categoricalAttribute": "status",
        "categories": ["active", "pending", "closed"],
        "showOther": true
      },
      "paint": {
        "color": ["#22C55E", "#F59E0B", "#EF4444", "#9CA3AF"],
        "size": [8, 8, 8, 4],
        "opacity": [0.9, 0.9, 0.9, 0.5],
        "strokeColor": "auto",
        "strokeWidth": 1
      },
      "legend": {"displayName": "auto"}
    }

    Example

    More patterns

    Lines support color variation per category but not per-category icons. For categorical polygons, color is the only visual variable — keep to 5–7 categories so large filled areas stay distinguishable. Lines can still use a for casing under each colored category.

    @palette
    Write code directly within Felt using our Extensions feature. Extensions run directly within the Felt environment, giving you immediate access to all SDK functionality without embedding or connection steps.

    When creating an extension, you automatically have access to a FeltController object named felt with no setup required. This controller provides all the methods you need to interact with your Felt map, including getViewport, createElement, setLayerStyle, and many more.

    Embed Felt maps in your own applications and control them remotely.

    • A Felt map to embed. Open any map you have access to and grab its ID from the URL: in felt.com/map/Readable-Title-xPV9BqMuYQxmUraVWy9C89BNA, the ID is the trailing part, xPV9BqMuYQxmUraVWy9C89BNA.

    • The map's sharing settings must allow the visitor to view it. Public and unlisted maps work out of the box; for private maps see Embed options.

    Install the SDK using your preferred package manager:

    Alternatively, load it straight from a CDN in a <script type="module"> — no build step required:

    Create an HTML page with a container element. Give the container an explicit height — an iframe inside a zero-height container renders as an invisible sliver, which is the most common first-run problem:

    Embed a Felt map in your container element and use the SDK to read from it:

    You should see your map load inside the container, with the Felt legend and zoom controls visible. Open the browser console and you should see the layer count logged. If the container stays empty, check that the map ID is correct and that the map's sharing settings allow viewing.

    Throughout these docs, code examples assume a controller variable named felt, whether it came from Felt.embed or from the extension environment.

    • General concepts — the mental model: controllers, promises, listeners, and what persists.

    • Controlling maps — viewports, and connecting to existing iframes.

    • Embed options — UI controls, initial viewport, private maps.

    • Integrating with React — React hooks for the SDK, and the React starter repo for a quick start.

    Extensions

    Enterprise plan
    set up a trial
    examples
    // In a Felt extension, the controller is automatically available
    const layers = await felt.getLayers();
    
    // Listen for map events
    felt.onSelectionChange({
      handler: ({ selection }) => console.log("Selection changed:", selection),
    });
    npm install @feltmaps/js-sdk
    import { Felt } from "https://esm.run/@feltmaps/js-sdk";
    <html>
      <head>
        <style>
          #container { height: 500px; }
        </style>
      </head>
      <body>
        <div id="container"></div>
        <script type="module" src="main.js"></script>
      </body>
    </html>
    // main.js
    import { Felt } from "@feltmaps/js-sdk";
    
    const felt = await Felt.embed(
      document.querySelector("#container"),
      "FELT_MAP_ID", // Replace with your map's ID
    );
    
    const layers = await felt.getLayers();
    console.log(`This map has ${layers.length} layers`);

    Embedded maps

    What you'll need

    Installation

    Embed your first map

    Next steps

    Building custom charts

    The Felt SDK provides powerful methods to analyze your geospatial data and transform it into informative visualizations. You can calculate statistics on entire datasets or focus on specific areas using boundaries and filters, allowing you to create custom charts that reveal insights about your spatial data.

    Statistics are available for layers that have been uploaded to and processed by Felt — layers created at runtime with createLayersFromGeoJson cannot be queried for statistics.

    Data analysis methods

    The SDK offers three complementary approaches to analyze your map data:

    1. Aggregates: single statistics

    Calculate individual values (count, sum, average, etc.) across your dataset or a filtered subset. If no aggregation method is provided, the count is returned.

    // Count all residential buildings
    const residentialCount = await felt.getAggregates({
        layerId: "buildings",
        filters: ["type", "eq", "residential"]
    });
    // returns { count: 427 }
    
    // Calculate average home value in a specific neighborhood
    const avgHomeValue = await felt.getAggregates({
        layerId: "buildings",
        boundary: [-122.43, 47.60, -122.33, 47.62], // neighborhood boundary
        aggregation: {
            method: "avg",
            attribute: "assessed_value"
        }
    });
    // returns { avg: 652850.32 }

    2. Categories: group by values

    Group features by unique attribute values and calculate statistics for each group.

    // Basic grouping: Count of buildings by type
    const buildingsByType = await felt.getCategoryData({
        layerId: "buildings",
        attribute: "type"
    });
    /* returns:
    [
      { value: "residential", count: 427 },
      { value: "commercial", count: 82 },
      { value: "mixed-use", count: 38 },
      { value: "industrial", count: 15 }
    ]
    */

    3. Histograms: group by numeric ranges

    Create bins for numeric data and calculate statistics for each range.

    // Basic histogram: Building heights in 5 natural break bins
    const buildingHeights = await felt.getHistogramData({
        layerId: "buildings",
        attribute: "height",
        steps: { type: "jenks", count: 5 }
    });
    /* returns:
    [
      { min: 0, max: 20, count: 175 },
      { min: 20, max: 50, count: 203 },
      { min: 50, max: 100, count: 142 },
      { min: 100, max: 200, count: 36 },
      { min: 200, max: 500, count: 6 }
    ]
    */

    Working with filters

    You can apply filters in two powerful ways:

    1. At the top level - Affects both which data is included and how values are calculated

    2. In the values configuration - Only affects the calculated values while keeping all categories/bins

    This two-level filtering is especially useful for creating comparative visualizations while maintaining consistent groupings.

    Comparing building types by floor area (Categories)

    Comparing building heights across time periods (Histograms)

    Comparing neighborhood density (Aggregates)

    Here's how you might integrate these analysis methods with an interactive chart:

    This example demonstrates how a user clicking on a pie chart slice could apply a filter to the map, highlighting only the buildings of that type. It also shows how you could fetch additional statistics based on the user's selection to enrich the visualization experience.

    Raster visualizations

    Raster layers are styled with one of five type values. They share a common set of config options and never support popups or labels.

    General concepts

    This guide covers the mental model and the common patterns used throughout the Felt SDK. Understanding these once makes every other page predictable.

    Everything you do with the SDK goes through a controller object — named felt in all the examples in these docs. How you get it depends on where your code runs:

    • Embeds — your code runs in your page, and the map lives in an iframe. Felt.embed(container, mapId, options) creates the iframe and returns a controller for it. You can also use Felt.connect(iframe.contentWindow) to attach a controller to a Felt iframe you've already placed on the page. See and .

    paint array

    Advanced filtering examples

    Interactive visualization example

    Extensions — your code runs inside the Felt app, and receives a ready-made controller: no embedding required. See the extensions documentation.

    The controller communicates with the map via message passing, which is why every read is asynchronous (see promises below). The same controller API is available in both contexts.

    A crucial rule for building on the SDK: changes made via the SDK are visible only to the current session — they are not saved to the map. This applies to:

    • Annotations created with createElement

    • Layers created with createLayersFromGeoJson

    • Style changes made with setLayerStyle

    • Filters set with setLayerFilters

    This makes the SDK safe for building per-visitor experiences on shared maps: ten visitors can each see their own filters and drawings without affecting each other or the underlying map. To make persistent changes to a map, use the REST API.

    All methods in the Felt SDK are asynchronous and return Promises — writes as well as reads. This means you'll need to use await or .then() when calling them:

    The SDK follows a consistent pattern for getting entities. For each entity type, there are usually two getters:

    1. A singular getter for retrieving one entity by ID:

    1. A plural getter that accepts constraints for retrieving multiple entities:

    The plural getters also allow you to pass no constraints, in which case they'll return all entities of that type:

    Singular getters return null when the entity doesn't exist, and plural getters can contain null entries — always check before using the result:

    When you need multiple entities, use the plural methods with constraints rather than making multiple individual calls:

    Each entity type has a corresponding change listener method following the pattern on{EntityType}Change:

    There are also various other setters and getters in the Felt SDK that follow this convention as much as possible. For example, selection:

    And layer filters — note that this particular listener receives the filters value directly, with no wrapper object:

    For the full list of listeners and their payloads, see the Events reference.

    All change listeners return an unsubscribe function that should be called when you no longer need the listener:

    This is particularly important in frameworks like React where you should clean up listeners when components unmount:

    Change listeners always take a single object parameter containing both options and handler. This structure makes it easier to add new options in the future without breaking existing code:

    When dealing with mixed collections of entities (like in selection events), each entity is wrapped in an EntityNode object that includes type information:

    The Felt controller

    Controlling maps
    Embed options

    Session-only vs persisted changes

    Use of promises

    Getting entities

    Getters can return null

    Batch your reads

    Change listeners

    Cleanup functions

    Handler and options structure

    Entity nodes

    // Advanced: Show all building types, but only sum floor area of recent buildings
    const recentBuildingAreaByType = await felt.getCategoryData({
        layerId: "buildings",
        attribute: "type",
        values: {
            filters: ["year_built", "ge", 2000],
            aggregation: {
                method: "sum",
                attribute: "floor_area"
            }
        }
    });
    /* returns:
    [
      { value: "residential", sum: 1250000 },
      { value: "commercial", sum: 750000 },
      { value: "mixed-use", sum: 350000 },
      { value: "industrial", sum: 120000 }
    ]
    */
    // Compare old vs new buildings using the same height ranges
    const oldBuildingHeights = await felt.getHistogramData({
        layerId: "buildings",
        attribute: "height",
        steps: [0, 20, 50, 100, 200, 500],
        values: {
            filters: ["year_built", "lt", 1950]
        }
    });
    /* returns:
    [
      { min: 0, max: 20, count: 96 },
      { min: 20, max: 50, count: 104 },
      { min: 50, max: 100, count: 37 },
      { min: 100, max: 200, count: 12 },
      { min: 200, max: 500, count: 1 }
    ]
    */
    
    const newBuildingHeights = await felt.getHistogramData({
        layerId: "buildings",
        attribute: "height",
        steps: [0, 20, 50, 100, 200, 500], // Same ranges as above
        values: {
            filters: ["year_built", "ge", 1950]
        }
    });
    /* returns:
    [
      { min: 0, max: 20, count: 79 },
      { min: 20, max: 50, count: 99 },
      { min: 50, max: 100, count: 105 },
      { min: 100, max: 200, count: 24 },
      { min: 200, max: 500, count: 5 }
    ]
    */
    // Find average residential density across different neighborhoods
    const downtownDensity = await felt.getAggregates({
        layerId: "buildings",
        boundary: [-122.335, 47.600, -122.330, 47.610], // downtown boundary
        filters: ["type", "eq", "residential"],
        aggregation: {
            method: "avg",
            attribute: "units_per_acre"
        }
    });
    // returns { avg: 124.7 }
    
    const suburbanDensity = await felt.getAggregates({
        layerId: "buildings",
        boundary: [-122.200, 47.650, -122.150, 47.700], // suburban boundary
        filters: ["type", "eq", "residential"],
        aggregation: {
            method: "avg", 
            attribute: "units_per_acre"
        }
    });
    // returns { avg: 8.2 }
    // Create a pie chart showing building type distribution
    async function createBuildingTypePieChart() {
        // Get data for the chart
        const data = await felt.getCategoryData({
            layerId: "buildings",
            attribute: "type"
        });
        
        // Render pie chart (using a hypothetical chart library)
        const chart = renderPieChart(data, {
            valuePath: "count",
            labelPath: "value",
            onSliceClick: handleSliceClick
        });
        
        return chart;
    }
    
    // Handle user interaction with the chart
    async function handleSliceClick(slice) {
        const buildingType = slice.label;
        
        // Apply filter to highlight this building type on the map
        await felt.setLayerFilters({
            layerId: "buildings",
            filters: ["type", "eq", buildingType],
            note: `Showing ${buildingType} buildings only`
        });
        
        // Get additional statistics for this building type
        const stats = await felt.getAggregates({
            layerId: "buildings",
            filters: ["type", "eq", buildingType],
            aggregation: {
                method: "avg",
                attribute: "year_built"
            }
        });
        
        // Update the UI with these statistics
        updateStatsPanel(`Average ${buildingType} year built: ${Math.round(stats.avg)}`);
    }
    
    // Initialize the chart when the page loads
    createBuildingTypePieChart();
    import { Felt } from "@feltmaps/js-sdk";
    
    const felt = await Felt.embed(
      document.getElementById("container"),
      FELT_MAP_ID,
    );
    const layer = await felt.getLayer("layer-1");
    felt.getElements().then(elements => {
      console.log(elements);
    });
    const layer = await felt.getLayer("layer-1");
    const element = await felt.getElement("element-1");
    const layers = await felt.getLayers({ ids: ["layer-1", "layer-2"] });
    const legendItems = await felt.getLegendItems({ layerIds: ["layer-1", "layer-2"] });
    const layers = await felt.getLayers();
    const legendItems = await felt.getLegendItems();
    const layer = await felt.getLayer("layer-1");
    if (layer) {
      // Layer exists, safe to use
      console.log(layer.visible);
    } else {
      console.log("Layer not found");
    }
    // Better approach
    const layers = await felt.getLayers({ ids: ["layer-1", "layer-2"] });
    
    // Less efficient approach
    const layer1 = await felt.getLayer("layer-1");
    const layer2 = await felt.getLayer("layer-2");
    const unsubscribe = felt.onLayerChange({
      options: { id: "layer-1" },
      handler: ({ layer }) => {
        console.log("Layer updated:", layer);
      }
    });
    const selection = await felt.getSelection();
    const unsubscribe = felt.onSelectionChange({
      handler: ({ selection }) => {
        console.log("Selection updated:", selection);
      }
    });
    const filters = await felt.getLayerFilters("layer-1");
    await felt.setLayerFilters({
      layerId: "layer-1",
      filters: ["name", "eq", "Jane"],
    });
    const unsubscribe = felt.onLayerFiltersChange({
      options: { layerId: "layer-1" },
      handler: (filters) => console.log(filters.combined),
    });
    const unsubscribe = felt.onLayerChange({
      options: { id: "layer-1" },
      handler: ({ layer }) => {
        console.log("Layer changed:", layer);
      }
    });
    
    // Later, when you're done listening:
    unsubscribe();
    useEffect(() => {
      const unsubscribe = felt.onViewportMove({
        handler: (viewport) => {
          console.log("Viewport changed:", viewport);
        }
      });
    
      // Clean up when the component unmounts
      return () => unsubscribe();
    }, []);
    // Current API
    felt.onElementChange({
      options: { id: "element-1" },
      handler: ({ element }) => { /* ... */ }
    });
    
    // If we need to add new options later, no breaking changes:
    felt.onElementChange({
      options: { 
        id: "element-1",
        newOption: "value" // Can add new options without breaking existing code
      },
      handler: ({ element }) => { /* ... */ }
    });
    felt.onSelectionChange({
      handler: ({ selection }) => {
        selection.forEach(node => {
          console.log(node.type);    // e.g., "element", "layer", "feature", ...
          console.log(node.entity);  // The actual entity object
          
          if (node.type === "element") {
            // TypeScript knows this is an Element
            console.log(node.entity.attributes);
          }
        });
      }
    });

    simple

    Display the raster as-is (satellite, aerial, base tiles)

    numeric

    Classify one band (elevation, temperature, a hazard index)

    numeric

    Compute a spectral index (NDVI, NDMI, NDWI) from several bands

    categorical

    Discrete pixel classes (land cover, soil types)

    hillshade

    Relief shading from elevation, optionally tinted

    Option
    Notes

    band

    Which band to read (1-indexed). Numeric/hillshade.

    steps

    Classification — see . {"type": "continuous"} for smooth, or breaks like [0, 500, 1000].

    method

    In paint, color takes a raster palette or an explicit color array, plus opacity and isSandwiched (render below basemap water/roads).

    Renders the image with no classification — just opacity and resampling.

    Classify one band. Prefer continuous for smooth data (elevation, temperature); use breaks for discrete groups (hazard levels).

    A style is classed when steps has more than two break points — the color array then needs one entry per class (N break points produce N − 1 classes; extra colors are ignored). With exactly two steps ([min, max], as below), the style is continuous: the whole color array is interpolated smoothly across the range:

    Compute a derived index from multiple bands before classifying. The config.method names the index and maps its inputs to band numbers, and band lists every band used. Supported indices:

    • NDVI — (NIR − R) / (NIR + R), vegetation health. Requires NIR, R.

    • NDMI — (NIR − SWIR) / (NIR + SWIR), moisture. Requires NIR, SWIR.

    • NDWI — (G − NIR) / (G + NIR), water. Requires G, NIR.

    Band numbers are 1-indexed and sensor-specific (Landsat 8/9: R=4, G=3, NIR=5, SWIR=6 · Sentinel-2: R=4, G=3, NIR=8, SWIR=11).

    NDVI output ranges from −1 (water/bare) to 1 (dense vegetation); classify it with explicit breaks (e.g. [-1, -0.2, 0, 0.2, 0.4, 0.6, 1]) for labelled classes. Good starting points: NDVI → [-0.5, 0.5] with @cbRedYlGrn; NDWI → [-0.5, 0.25] and NDMI → [-0.5, 0.5] with @feltVibrant.

    Raster categories are raw pixel values (integers), so there is no categoricalAttribute. Use {"type": "all"} when you don't know the values, or an explicit array when you do, with one color per value. Don't set rasterResampling here — categorical rasters always use nearest resampling automatically (the property is rejected on this type), since linear interpolation would blend category codes into invalid values.

    For raster categorical, use the vector categorical palettes (@catPalette1…@catPalette7). A fully-transparent class can be expressed as "rgba(0, 0, 0, 0)".

    Simulates light and shadow on terrain. Plain hillshade is grayscale relief (config carries just band; paint carries source and intensity). Tinted hillshade overlays a hypsometric color ramp — add steps to config and color to paint; only do this when elevation coloring is wanted.

    Paint property
    Default
    Notes

    source

    315

    Light azimuth in degrees (0 = North, 90 = East). 315 (northwest) is standard.

    intensity

    0.5

    Tinted, classifying elevation like any numeric raster (use rasterResampling: "linear" and noData for voids):

    Mode

    type

    Use it for

    {
      "version": "2.3.1",
      "type": "simple",
      "config": {},
      "paint": {"opacity": 0.93, "isSandwiched": false}
    }
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {
        "band": 1,
        "steps": {"type": "continuous"},
        "noData": [-9999],
        "rasterResampling": "linear"
      },
      "paint": {"color": "@mplVirdis", "opacity": 1, "isSandwiched": false},
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {"band": 1, "steps": [-154.46, 7987.46]},
      "legend": {"displayName": {"0": "-154.46", "1": "7.99K"}},
      "paint": {
        "opacity": 1,
        "isSandwiched": false,
        "color": ["#454b9f", "#2d79a4", "#18a2a9", "#8cc187", "#e5d96c", "#eab459", "#ef8b45", "#e66250", "#db2d5e"]
      }
    }
    {
      "version": "2.3.1",
      "type": "numeric",
      "config": {
        "method": {"NDVI": {"NIR": 5, "R": 4}},
        "band": [5, 4],
        "steps": {"type": "continuous"},
        "noData": [0],
        "rasterResampling": "nearest",
        "outOfRangeValues": "hide"
      },
      "paint": {"color": "@cbRedYlGrn", "opacity": 1, "isSandwiched": false},
      "legend": {"displayName": "auto"}
    }
    {
      "version": "2.3.1",
      "type": "categorical",
      "config": {"categories": [1, 2, 3, 4, 5]},
      "paint": {
        "color": ["#228B22", "#4682B4", "#DAA520", "#8B4513", "#808080"],
        "opacity": 0.85,
        "isSandwiched": true
      },
      "legend": {
        "displayName": {"1": "Forest", "2": "Water", "3": "Cropland", "4": "Bare Soil", "5": "Urban"}
      }
    }
    {
      "version": "2.3.1",
      "type": "hillshade",
      "config": {"band": 1},
      "paint": {"source": 315, "intensity": 0.5, "isSandwiched": true},
      "legend": {}
    }
    {
      "version": "2.3.1",
      "type": "hillshade",
      "config": {
        "band": 1,
        "steps": {"type": "quantiles", "count": 6},
        "noData": [-9999],
        "rasterResampling": "linear"
      },
      "paint": {"color": "@terrain", "source": 315, "intensity": 0.5, "isSandwiched": true},
      "legend": {"displayName": "auto"}
    }

    Shared config options

    Image (simple)

    Numeric — single band

    Numeric — multiband (raster algebra)

    Categorical

    Hillshade

    Spectral-index formula and band mapping (multiband only).

    categories

    Categorical only — {"type": "all"} for every pixel value, or an explicit array.

    noData

    Value(s) to exclude, e.g. [-9999] for voids or [0] for no-data.

    rasterResampling

    Numeric and tinted hillshade only — categorical rasters reject it (they always resample nearest). "nearest" keeps exact pixel values; "linear" interpolates (use for continuous imagery/elevation).

    outOfRangeValues

    "color" clamps to the nearest class color; "hide" makes them transparent.

    Shadow intensity 0–1; higher = more dramatic relief.

    color

    —

    Raster palette or color array (tinted only), low → high elevation.

    Image
    Numeric — single band
    Numeric — multiband / raster algebra
    Categorical
    Hillshade
    Classification methods

    The paint block

    The paint block defines how feature geometries and raster pixels are rendered.

    Color properties (color, strokeColor) accept a literal color or a @palette shortcut, and strokeColor additionally accepts the smart keyword "auto" — see Colors & palettes. Point layers can be drawn as icons via iconImage — see Icons. For data-driven (categorical, numeric, h3) visualizations, paint properties may be arrays, one value per category/class.

    Properties common to all visualization types.

    Type
    Default
    Description

    The following properties are available for the simple type of visualization

    Type
    Applies to
    Description

    See for the default values of these attributes on each geometry type.

    categorical and numeric visualizations use the same color, opacity, size, strokeColor, strokeWidth, and line properties listed above (highlightColor/highlightStrokeColor are simple-only). The difference is that each property may be an array: a single value applies to every category/class, or one value per category/class. See the and pages for worked examples.

    When a point layer should be drawn as icons instead of circles, set iconImage in the paint block. The icon takes on the layer's color and size. See for the full catalog and examples.

    Type
    Description

    The paint property can be an array of paint objects for layered rendering. The layers render last-to-first (the last entry is the bottom layer, the first is on top). This is most often used for road-style casing: a wide dark outline beneath a narrower colored fill.

    Paint arrays work on all geometries but are most useful for line casing.

    Label rendering is configured separately, in the label block. See for the full property reference, defaults, and placement-by-geometry guidance.

    Name
    Points
    Polygons
    Lines

    boolean

    false

    Optional. A flag to tell if features should be hoverable

    isSandwiched

    boolean

    false

    Optional. A flag to tell if features affected by this visualization need to be rendered below the basemap road and water layers. Only applies to polygon features, point and line features are already rendered on top of the basemap

    maxZoom

    number

    24

    Optional. The maximum zoom level at which the visualization will be shown

    minZoom

    number

    0

    Optional. The minimum zoom level at which the visualization will be shown

    renderAsLines

    boolean

    false

    Optional. Decides if a polygon dataset should be rendered as lines thus making them render above the basemap. Note that using this requires that the style uses line properties instead of polygon ones.

    paintPropertyOverrides

    object

    Optional. An escape hatch: raw paint or layout properties applied to the generated layer. Keys that are not valid for the underlying MapLibre layer type are silently ignored. Also available on the label block. See for more.

    number[]

    Lines

    Optional. The dash line definition — an array of dash/gap lengths with an even number of entries, e.g. [2, 1]

    highlightColor

    string

    Points, lines and polygons

    Optional. The color to be used when a feature is selected

    highlightStrokeColor

    string

    Points, lines and polygons

    Optional. The stroke color to be used when a feature is selected

    highlightStrokeWidth

    number |

    Points and polygons

    Optional. The stroke width when a feature is selected

    lineCap

    "butt" | "round" | "square"|

    Lines

    Optional. The shape used to draw the end points of lines

    lineJoin

    "bevel" | "round"| "miter"|

    Lines

    Optional. The shape used to join two line segments when they meet

    opacity

    number |

    Points, lines and polygons

    Optional. The opacity to use from 0 to 1

    size

    number |

    Points and lines

    Optional. Point radius or line width in pixels

    strokeColor

    string | | auto

    Points and polygons

    Optional. Stroke color

    strokeWidth

    number |

    Points and polygons

    Optional. Stroke width in pixels

    iconRotation

    number | string

    Rotation in degrees, or a column name to rotate by.

    iconHideOnZoom

    number

    Zoom level below which icons render as plain points.

    "#EA3891"

    "#EA3891"

    "#EA3891"

    highlightStrokeColor

    "#EA3891"

    "#EA3891"

    "#EA3891"

    dashArray

    -

    -

    lineCap

    -

    -

    "round"

    lineJoin

    -

    -

    "round"

    opacity

    0.9

    0.8

    1

    isSandwiched

    -

    false

    -

    size

    4

    -

    2

    strokeColor

    "#F9F8Fb"

    "#777777"

    -

    strokeWidth

    1

    1

    -

    isClickable

    boolean

    true

    Optional. A flag to tell if features should be clickable

    color

    string | Interpolator

    Points, lines and polygons

    Optional. The color to be used

    iconImage

    string | string[]

    An icon slug, or an emoji as "emoji::name:". Array form assigns an icon per category/class.

    iconFrame

    "none" | "frame-circle" | "frame-square"

    {
      "version": "2.3.1",
      "type": "simple",
      "paint": [
        {"color": "#3B82F6", "size": 4, "opacity": 1.0, "lineCap": "round", "lineJoin": "round"},
        {"color": "#1E3A5F", "size": 8, "opacity": 1.0, "lineCap": "round", "lineJoin": "round"}
      ],
      "legend": {}
    }

    color

    "#EE4D5A"

    "#826DBA"

    "#4CC8A3"

    Simple visualizations

    Categorical and numeric visualizations

    Icon properties (points)

    Paint arrays (casing & layered rendering)

    Label block reference

    Default values

    default values
    categorical
    numeric
    Icons
    The label block

    isHoverable

    dashArray

    A frame drawn behind built-in icons (not emojis).

    highlightColor

    Colors & palettes

    Colors appear throughout the Felt Style Language — in paint (color, strokeColor), in label (color, haloColor), and in legends. There are three ways to express a color:

    1. A literal color — a hex, HSL, or RGB string.

    2. A smart color — the keyword "auto", which Felt resolves to a contrasting color at render time.

    3. A palette shortcut — a named, multi-color ramp like @galaxy, used by data-driven (categorical, numeric, heatmap, H3) visualizations.

    Any of these string formats are accepted wherever a single color is expected:

    rgba(...) is also supported and is handy for fully-transparent fills (for example, a transparent "Other"/background class in a categorical raster: "rgba(0, 0, 0, 0)").

    "auto" computes a contrasting color automatically, based on the current map theme and the colors around it. It keeps strokes and label halos legible without hard-coding a value that might clash on a dark basemap or against a particular fill.

    Prefer "auto" for:

    • strokeColor on points and polygons

    • color and haloColor on labels

    …unless a specific color has been requested.

    For any data-driven visualization, prefer a named palette over a hand-built color array. Palettes are referenced with an @ prefix (for example "color": "@galaxy") and Felt expands them to the right number of colors for your classes or categories.

    Used by categorical, numeric, heatmap, and H3 visualizations on points, lines, and polygons.

    Palette
    Description
    Palette
    Description
    Palette
    Description

    Sequential and diverging vector palettes also come in numbered variants that request a specific number of colors — for example @galaxy7, @galaxy8, @galaxy9. Variants exist for 7, 8, and 9 colors (@lightning also has a 6-color variant). The unnumbered name lets Felt pick the right count for you, which is usually what you want.

    Used by heatmap visualizations, ordered from least to most density.

    Palette
    Description

    Used by numeric, hillshade, and raster-algebra visualizations.

    Palette
    Description
    Palette
    Description
    Palette
    Description
    Palette
    Description

    For raster categorical layers, use the vector categorical palettes above (@catPalette1 … @catPalette7, @catPalettePT1, @catPalettePT2).

    Raster palettes also support numbered variants to request a specific number of steps — for example @feltGrays2, @feltGrays3, … @feltGrays9.

    When a palette or color array drives a data-driven visualization, the number of colors should line up with the number of classes or categories:

    • Categorical: one color per category. With showOther: true and an explicit categories array, provide N + 1 colors — the extra one styles the "Other" bucket.

    • Classed numeric: N break points produce N − 1 classes, so an explicit color array needs N − 1 entries.

    • Continuous: provide 2 or more colors and Felt interpolates smoothly between them in the

    A palette shortcut handles all of this for you — Felt expands @galaxy to exactly the colors it needs. Reach for explicit arrays only when you want precise control over each color.

    The label block

    These are the properties available to define label rendering. Point and line features are labeled directly; polygon labels are anchored at each polygon's centroid (or along lines with renderAsLines).

    Type
    Applies to
    Description
    MapLibre
    here
    Interpolator
    Interpolator
    Interpolator
    Interpolator
    Interpolator
    Interpolator
    Interpolator

    @purpYl

    Purple to yellow

    @pinkYl

    Pink to yellow

    @lightning

    Lightning gradient

    @copper

    Copper gradient

    @spruce

    Spruce green

    @riverine

    Water gradient

    @neptune

    Blue gradient

    @violet

    Violet gradient

    @purple

    Purple gradient

    @grnOr

    Green to orange

    @purGrn

    Purple to green

    @weath

    Weather gradient

    @lightningHeat

    Purple → teal → green → yellow

    @ylGrnHeat

    Dark teal → green → yellow

    @bluRdHeat

    Blue → gray → red (diverging feel)

    @tealRedHeat

    Teal → green → yellow → orange → pink

    @purpYlPink

    Purple → teal → yellow → orange → red/pink

    @feltPinks

    Pink gradient

    @cmOceanGreens

    Ocean greens gradient

    @pattFeltOcean

    Teal ocean gradient

    @cmOceanDeep

    Deep ocean gradient

    @mpaInferno

    Matplotlib inferno — note the spelling: mpa, not mpl

    @mplPlasma

    Matplotlib plasma

    @mplVirdis

    Matplotlib viridis, perceptually uniform — note the spelling: Virdis, not Viridis

    @cividis

    Cividis — colorblind-safe

    @feltYlRed

    Felt yellow to red

    @veg

    Vegetation gradient

    @nclBlOrRed

    NCL blue-orange-red diverging

    @cbRedYlGrn

    ColorBrewer red-yellow-green diverging

    @cbBrBG

    ColorBrewer brown-blue-green diverging

    @wikiTerrain

    Wikipedia terrain gradient

    .

    @galaxy

    Purple to yellow (popular default)

    @ylRed

    Yellow to red

    @ylGrn

    @bluRd

    Blue to red

    @tealOr

    Teal to orange (colorblind-safe)

    @bluBr

    @catPalette1 … @catPalette7

    Categorical color schemes

    @catPalettePT1

    Paul Tol categorical palette 1

    @catPalettePT2

    @geyser

    Green → beige → orange → red (default)

    @redOrHeat

    Yellow → orange → red → magenta

    @purpYlHeat

    @feltGrays

    Grayscale gradient

    @cbBlues

    ColorBrewer blues

    @cbPurples

    @feltWeath

    Felt weather gradient

    @feltHeat

    Felt heat gradient

    @feltVibrant

    @terrain

    Terrain elevation gradient

    @rTerrain

    R terrain gradient

    @feltHypso

    @nasaNDVI

    NASA NDVI vegetation index

    Literal colors

    Smart color: "auto"

    Palette shortcuts

    Only the palette names listed below are valid. Use sequential palettes for single-direction data (population, elevation), and diverging palettes for data with a meaningful midpoint (change from a baseline, temperature anomaly). Reserve literal hex/HSL colors for simple (uniform) styles or when a specific color is requested.

    Vector palettes

    Sequential (low → high)

    Diverging (two directions from a center)

    Categorical (distinct colors)

    Heatmap palettes

    Raster palettes

    Sequential

    Diverging

    Terrain

    Vegetation

    How colors map to classes

    HCL color space

    Yellow to green

    Blue to brown

    Paul Tol categorical palette 2

    Light yellow → coral → pink → purple

    ColorBrewer purples

    Felt vibrant gradient

    Felt hypsometric tints

    {
      "color": "#3B82F6",
      "strokeColor": "hsl(217, 80%, 40%)",
      "haloColor": "rgb(38, 113, 0)"
    }
    {
      "paint": {
        "color": "#8F7EBF",
        "strokeColor": "auto",
        "strokeWidth": 1
      },
      "label": {
        "color": "auto",
        "haloColor": "auto",
        "haloWidth": 1.5
      }
    }

    string | auto |

    Points and lines

    Optional. The label color

    fontFamily

    string

    Points and lines

    Optional. The font family to use

    fontSize

    number |

    Points and lines

    Optional. The font size in pixels

    fontStyle

    "normal" | "italic"

    Points and lines

    Optional. The font style (case-insensitive). Values other than italic render as normal

    fontWeight

    number

    Points and lines

    Optional. The font weight

    haloColor

    string |

    Points and lines

    Optional. The label halo color

    haloWidth

    number |

    Points and lines

    Optional. The label halo width in pixels

    justify

    "auto" | "left" | "right" | "center"

    Points and lines

    Optional. Text justification for multi-line labels

    letterSpacing

    number

    Points and lines

    Optional. Horizontal spacing behaviour between text characters

    lineHeight

    number

    Points and lines

    Optional. Sets the height of a line box

    maxLineChars

    number |

    Points and lines

    Optional. Defines the max number of characters before a line break

    maxZoom

    number

    Points and lines

    Optional. The maximum zoom level at which the label will be shown. Defaults to 24

    minZoom

    number

    Points and lines

    Optional. The minimum zoom level at which the label will be shown. Defaults to 24 (see note below)

    offset

    [number, number] | number

    Points and lines

    Optional. In the case of points, this value must be an array of two numeric offsets that will be applied on the positive X and Y axis defined by the label placement (i.e. an offset of [3,4] with a label placement of NE moves the label 3pixels to the right and 4 pixels above of the anchor point. An offset of [3,4] with a label placement of SW moves the label 3pixels to the left and 4 pixels below of the anchor point). In case of lines, this value is a single number that moves the label following the label position (i.e. an offset of 3 with a label position of Above will move the label 3 pixels above the line following the line normal. An offset of 3 with a label position of Below will mode the label 3 pixels under the line following the line normal)

    padding

    number

    Points and lines

    Optional. Adds invisible padding around the label that's used to compute label collisions

    placement

    string[] | "auto" | string

    Points and lines

    Optional. On points: an array of placements to try ("N", "NE", "E", "SE", "S", "SW", "W", "NW", "Center") or "auto"; if all placements collide with existing labels, the label is not shown. On lines: a single placement relative to the line — "Above", "Center"

    renderAsLines

    boolean

    Polygons

    Optional. Renders labels along lines instead of using the centroids

    repeatDistance

    number

    Lines

    Optional. The distance in pixels between label repetitions on a line

    textTransform

    "none" | "uppercase" | "lowercase"

    Points and lines

    Optional. Specifies how to capitalize the label

    isClickable

    boolean

    Points, Lines and Polygons

    Optional. A flag to tell if labels should be clickable

    isHoverable

    boolean

    Points, Lines and Polygons

    Optional. A flag to tell if labels should be hoverable

    In addition, lines support maxAngle (number, default 30), the maximum angle change in degrees between adjacent characters of text following a curved line. Sharper turns aren't placed. See when a label isn't rendered.

    See default values of these attributes on each label type.

    placement is shaped differently depending on the geometry being labeled:

    • Points: an array of compass directions to try, e.g. ["E"] (right of the point), ["E", "W"], or ["Center"]. Felt uses the first placement that doesn't collide.

    • Lines: a single string relative to the line — "Above", "Center", or "Below". Tune repeatDistance (pixels between repeated labels) and maxAngle for curved text.

    • Polygons: ["Center"] places the label at the polygon's centroid.

    A feature with a label value can still render no label. Three rules decide:

    • Collision. A label that overlaps one already placed is dropped rather than moved. padding sets how much space around the text counts as an overlap. Zooming in usually brings the label back.

    • Line length. Line labels are anchored every repeatDistance pixels and need enough of the run on screen to fit their glyphs. Short segments get nothing. A smaller fontSize or a lower repeatDistance makes room.

    • Curvature. maxAngle caps the angle change between adjacent characters, not the overall bend of the line. Sharper turns aren't placed, so tight meanders often go unlabeled at the default 30.

    If a feature never labels at any zoom, check its config.labelAttribute value. Null or empty draws nothing.

    If using a categorical or numeric visualization, the properties above may be arrays. If there's a single value in the array, that value is used in all categories. If there are as many values as categories, the corresponding value will be used for each category. You can see an example of a categorical viz here.

    Name
    Points
    Lines
    Centroids

    color

    "#333333"

    "#333333"

    "#333333"

    The label block defines how feature labels are rendered.

    color

    Placement by geometry

    When a label isn't rendered

    Prefer "color": "auto" and "haloColor": "auto" so labels stay legible across themes and basemaps. See .

    Default values

    The default minZoom and maxZoom are both 24 — an empty range, which is how labels are hidden by default. To show labels, set a real zoom range on the label block.

    or
    "Below"

    fontFamily

    "Atlas Grotesk LC"

    "Atlas Grotesk LC"

    "Atlas Grotesk LC"

    fontSize

    13

    13

    13

    fontStyle

    "Normal"

    "Normal"

    "Normal"

    fontWeight

    500

    400

    500

    haloColor

    "#fbfcfb"

    "#fbfcfb"

    "#fbfcfb"

    haloWidth

    1

    1

    1

    justify

    "auto"

    "auto"

    "auto"

    letterSpacing

    0

    0

    0

    lineHeight

    1.2

    1.2

    1.2

    maxLineChars

    10

    -

    10

    maxAngle

    -

    30

    -

    maxZoom

    24

    24

    24

    minZoom

    24

    24

    24

    offset

    [8, 8]

    0

    -

    padding

    2

    1

    0

    placement

    "auto"

    "Above"

    "Center"

    repeatDistance

    -

    250

    -

    textTransform

    "none"

    "none"

    "none"

    Interpolator
    Interpolator
    Interpolator
    Interpolator
    Interpolator
    Colors & palettes

    Get current user

    get

    Retrieve profile information and settings for the authenticated user.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Responses
    200

    User

    application/json
    emailstringOptional
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestringOptional
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/user
    GET /api/v2/user HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "email": "text",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "name": "text"
    }
    post

    Create a new layer from an existing data source connection (database, API, or file).

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    Body
    dataset_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    fromstring · enumRequiredPossible values:
    or
    fromstring · enumRequiredPossible values:
    querystringRequired
    source_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    or
    fromstring · enumRequiredPossible values:
    source_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    stac_asset_urlstringRequired
    Responses
    202

    AddSourceLayerAccepted

    application/json
    layer_groupstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/KFFhKAbvS4anD3wxtwNEpD
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC
    statusstring · enumOptionalPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/add_source_layer
    POST /api/v2/maps/{map_id}/add_source_layer HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 56
    
    {
      "dataset_id": "luCHyMruTQ6ozGk3gPJfEB",
      "from": "dataset"
    }
    {
      "links": {
        "layer_group": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/KFFhKAbvS4anD3wxtwNEpD",
        "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC"
      },
      "status": "accepted"
    }
    post

    Trigger a data refresh for a layer from its original data source to pull in the latest updates.

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

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

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

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map hosting the layer to refresh

    layer_idstringRequired

    The ID of the layer to refresh

    Responses
    200

    Refresh response

    application/json
    layer_group_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    layer_idstring · felt_idOptional

    The ID of the layer created by this upload. If multiple layers are included in the upload, this is the ID of the first layer in the layer group.

    Example: luCHyMruTQ6ozGk3gPJfEB
    presigned_attributesobject · nullableOptional

    If provided, the presigned attributes to attach to the post request

    typestring · enumOptionalPossible values:
    urlstring · nullableOptional

    If provided, the URL to post the file to

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layers/{layer_id}/refresh
    POST /api/v2/maps/{map_id}/layers/{layer_id}/refresh HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "layer_group_id": "luCHyMruTQ6ozGk3gPJfEB",
      "layer_id": "luCHyMruTQ6ozGk3gPJfEB",
      "presigned_attributes": {},
      "type": "upload_response",
      "url": "text"
    }
    post

    Upload a file or import data from a URL to create a new layer on the map.

    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 contain information you will use to upload the file to Amazon S3

    Check our docs to see what URLs are supported.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to upload the layer to.

    Body
    latstringRequired
    lngstringRequired
    or
    lat_lngstringRequired
    or
    full_addressstringRequired
    or
    countrystringOptional

    ex: USA

    localitystringOptional

    ex: Oakland

    postal_codestringOptional

    ex: 94612

    regionstringOptional

    ex: California

    street_addressstringRequired

    ex: 1904 Franklin St

    or
    countrystringOptional

    ex: USA

    localitystringRequired

    ex: Oakland

    regionstringOptional

    ex: California

    or
    wkt_wkb_literalstringRequired
    or
    us_census_tract_2020stringRequired
    or
    us_cbsa_2020stringRequired
    or
    us_state_2020stringRequired
    or
    us_county_2020stringRequired
    or
    us_zip_code_2022stringRequired
    or
    eu_lau_2021stringRequired
    or
    eu_nuts_1_2021stringRequired
    or
    eu_nuts_2_2021stringRequired
    or
    eu_nuts_3_2021stringRequired
    or
    aus_postal_area_2021stringRequired
    or
    admin_0stringRequired
    or
    admin_1stringRequired
    or
    timezonestringRequired
    or
    h3stringRequired
    import_urlstringOptional

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

    latnumberOptional

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

    lngnumberOptional

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

    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired

    The display name for the new layer.

    zoomnumberOptional

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

    Responses
    200

    Upload layer response

    application/json
    layer_group_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    layer_idstring · felt_idOptional

    The ID of the layer created by this upload. If multiple layers are included in the upload, this is the ID of the first layer in the layer group.

    Example: luCHyMruTQ6ozGk3gPJfEB
    presigned_attributesobject · nullableOptional

    If provided, the presigned attributes to attach to the post request

    typestring · enumOptionalPossible values:
    urlstring · nullableOptional

    If provided, the URL to post the file to

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/upload
    POST /api/v2/maps/{map_id}/upload HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    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"
    }
    post

    Creates a token, valid for 12 hours, for authenticating a visitor to view a private embedded map view without being logged into Felt. You must provide a user_email to associate the token with the end user that will be viewing the map. Each end user should be a member of your Felt workspace with a viewer, editor, or admin role assigned.

    Mint a fresh token for each page load. The 12 hours cover a full working session in one open tab — reconnects included — and when they run out the embed asks the visitor to refresh, at which point your page should mint again.

    • Generate a token by making a call to this API from your server

    • Securely pass the token to your frontend client

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    Query parameters
    user_emailstringRequired

    Each token must be associated with the email address of the user who will use it.

    Responses
    200

    EmbedToken

    application/json
    expires_atstring · date_timeOptionalExample: 2024-05-25T15:51:34
    tokenstringOptional
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/embed_token
    POST /api/v2/maps/{map_id}/embed_token?user_email=text HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "expires_at": "2024-05-25T15:51:34",
      "token": "text"
    }
    post

    Move a map to a different project or folder within the same workspace. Project IDs and Folder IDs can be found inside map settings.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    Body
    project_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    or
    folder_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    Responses
    200

    Map

    application/json
    basemapstringOptional
    created_atstring · date_timeRequiredExample: 2024-05-25T15:51:34
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestring · nullableOptional
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    folder_idstring · nullableOptional
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC
    project_idstringRequired
    public_accessstring · enumRequiredPossible values:
    default_table_layer_idstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    viewers_can_open_tablebooleanOptional

    Whether viewers can open the data table

    thumbnail_urlstring · nullableRequired

    A static thumbnail image of the map

    titlestringRequired
    typestring · enumRequiredPossible values:
    urlstringRequired
    can_duplicate_mapbooleanOptional

    Whether viewers can duplicate the map and data

    can_export_databooleanOptional

    Whether viewers can export map data

    can_see_map_presencebooleanOptional

    Whether viewers can see who else is viewing the map

    visited_atstring · date_time · nullableRequired
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/move
    POST /api/v2/maps/{map_id}/move HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 39
    
    {
      "project_id": "luCHyMruTQ6ozGk3gPJfEB"
    }
    {
      "basemap": "text",
      "created_at": "2024-05-25T15:51:34",
      "element_groups": [
        {
          "elements": {
            "features": [
              {
                "geometry": {
                  "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
                  "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
                },
                "properties": {},
                "type": "Feature"
              }
            ],
            "type": "FeatureCollection"
          },
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "name": "text"
        }
      ],
      "elements": {
        "features": [
          {
            "geometry": {
              "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
              "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
            },
            "properties": {},
            "type": "Feature"
          }
        ],
        "type": "FeatureCollection"
      },
      "folder_id": "text",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "layer_groups": [
        {
          "caption": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "layers": [
            {
              "attributes": [
                {
                  "name": "text",
                  "type": "INTEGER"
                }
              ],
              "caption": "text",
              "geometry_type": "Line",
              "hide_from_legend": true,
              "id": "luCHyMruTQ6ozGk3gPJfEB",
              "is_spreadsheet": true,
              "last_refreshed_at": "2026-01-01T00:00:00.000Z",
              "legend_display": "default",
              "legend_visibility": "hide",
              "links": {
                "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
                "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",
              "next_refresh_at": "2026-01-01T00:00:00.000Z",
              "ordering_key": 1,
              "paused_reason": "consecutive_failures",
              "progress": 1,
              "refresh_period": "15 min",
              "refresh_status": "active",
              "status": "uploading",
              "style": {},
              "tile_url": "text",
              "type": "layer"
            }
          ],
          "legend_visibility": "hide",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
          },
          "name": "text",
          "ordering_key": 1,
          "type": "layer_group",
          "visibility_interaction": "default"
        }
      ],
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ],
      "links": {
        "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC"
      },
      "project_id": "text",
      "public_access": "private",
      "table_settings": {
        "default_table_layer_id": "luCHyMruTQ6ozGk3gPJfEB",
        "viewers_can_open_table": true
      },
      "thumbnail_url": "text",
      "title": "text",
      "type": "map",
      "url": "text",
      "viewer_permissions": {
        "can_duplicate_map": true,
        "can_export_data": true,
        "can_see_map_presence": true
      },
      "visited_at": "text"
    }
    post

    Create a copy of a map with all its layers, elements, and configuration.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to duplicate

    Body
    destinationone ofOptional
    project_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    or
    folder_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    titlestringOptional

    Title for the duplicated map. If not provided, will default to '[Original Title] (copy)'

    Responses
    200

    Duplicated Map

    application/json
    basemapstringOptional
    created_atstring · date_timeRequiredExample: 2024-05-25T15:51:34
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestring · nullableOptional
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    folder_idstring · nullableOptional
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC
    project_idstringRequired
    public_accessstring · enumRequiredPossible values:
    default_table_layer_idstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    viewers_can_open_tablebooleanOptional

    Whether viewers can open the data table

    thumbnail_urlstring · nullableRequired

    A static thumbnail image of the map

    titlestringRequired
    typestring · enumRequiredPossible values:
    urlstringRequired
    can_duplicate_mapbooleanOptional

    Whether viewers can duplicate the map and data

    can_export_databooleanOptional

    Whether viewers can export map data

    can_see_map_presencebooleanOptional

    Whether viewers can see who else is viewing the map

    visited_atstring · date_time · nullableRequired
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/duplicate
    POST /api/v2/maps/{map_id}/duplicate HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 70
    
    {
      "destination": {
        "project_id": "luCHyMruTQ6ozGk3gPJfEB"
      },
      "title": "text"
    }
    {
      "basemap": "text",
      "created_at": "2024-05-25T15:51:34",
      "element_groups": [
        {
          "elements": {
            "features": [
              {
                "geometry": {
                  "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
                  "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
                },
                "properties": {},
                "type": "Feature"
              }
            ],
            "type": "FeatureCollection"
          },
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "name": "text"
        }
      ],
      "elements": {
        "features": [
          {
            "geometry": {
              "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
              "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
            },
            "properties": {},
            "type": "Feature"
          }
        ],
        "type": "FeatureCollection"
      },
      "folder_id": "text",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "layer_groups": [
        {
          "caption": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "layers": [
            {
              "attributes": [
                {
                  "name": "text",
                  "type": "INTEGER"
                }
              ],
              "caption": "text",
              "geometry_type": "Line",
              "hide_from_legend": true,
              "id": "luCHyMruTQ6ozGk3gPJfEB",
              "is_spreadsheet": true,
              "last_refreshed_at": "2026-01-01T00:00:00.000Z",
              "legend_display": "default",
              "legend_visibility": "hide",
              "links": {
                "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
                "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",
              "next_refresh_at": "2026-01-01T00:00:00.000Z",
              "ordering_key": 1,
              "paused_reason": "consecutive_failures",
              "progress": 1,
              "refresh_period": "15 min",
              "refresh_status": "active",
              "status": "uploading",
              "style": {},
              "tile_url": "text",
              "type": "layer"
            }
          ],
          "legend_visibility": "hide",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
          },
          "name": "text",
          "ordering_key": 1,
          "type": "layer_group",
          "visibility_interaction": "default"
        }
      ],
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ],
      "links": {
        "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC"
      },
      "project_id": "text",
      "public_access": "private",
      "table_settings": {
        "default_table_layer_id": "luCHyMruTQ6ozGk3gPJfEB",
        "viewers_can_open_table": true
      },
      "thumbnail_url": "text",
      "title": "text",
      "type": "map",
      "url": "text",
      "viewer_permissions": {
        "can_duplicate_map": true,
        "can_export_data": true,
        "can_see_map_presence": true
      },
      "visited_at": "text"
    }
    post

    Create a new map with optional customization options.

    Several aspects can be customized when creating a new map, including:

    • Title

    • Initial location (latitude, longitude and zoom level)

    • Sharing permissions (defaults to viewing and commenting for users with the map URL)

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Body
    basemapstringOptional

    The basemap to use for the new map. Defaults to "default". Valid values are "default", "light", "dark", "satellite", a valid raster tile URL with {x}, {y}, and {z} parameters, or a hex color string like #ff0000.

    descriptionstringOptional

    A description to display in the map legend

    latnumberOptional

    If no data has been uploaded to the map, the initial latitude to center the map display on.

    layer_urlsstring[]Optional

    An array of urls to use to create layers in the map. Only tile URLs for raster layers are supported at the moment.

    lonnumberOptional

    If no data has been uploaded to the map, the initial longitude to center the map display on.

    public_accessstring · enumOptional

    The level of access to grant to the map. Defaults to "view_only".

    Possible values:
    titlestringOptional

    The title to be used for the map. Defaults to "Untitled Map"

    workspace_idstringOptional

    The workspace to create the map in. Defaults to the latest used workspace

    zoomnumberOptional

    If no data has been uploaded to the map, the initial zoom level for the map to display.

    Responses
    200

    Map

    application/json
    basemapstringOptional
    created_atstring · date_timeRequiredExample: 2024-05-25T15:51:34
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestring · nullableOptional
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    folder_idstring · nullableOptional
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC
    project_idstringRequired
    public_accessstring · enumRequiredPossible values:
    default_table_layer_idstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    viewers_can_open_tablebooleanOptional

    Whether viewers can open the data table

    thumbnail_urlstring · nullableRequired

    A static thumbnail image of the map

    titlestringRequired
    typestring · enumRequiredPossible values:
    urlstringRequired
    can_duplicate_mapbooleanOptional

    Whether viewers can duplicate the map and data

    can_export_databooleanOptional

    Whether viewers can export map data

    can_see_map_presencebooleanOptional

    Whether viewers can see who else is viewing the map

    visited_atstring · date_time · nullableRequired
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps
    POST /api/v2/maps HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 149
    
    {
      "basemap": "text",
      "description": "text",
      "lat": 1,
      "layer_urls": [
        "text"
      ],
      "lon": 1,
      "public_access": "private",
      "title": "text",
      "workspace_id": "text",
      "zoom": 1
    }
    {
      "basemap": "text",
      "created_at": "2024-05-25T15:51:34",
      "element_groups": [
        {
          "elements": {
            "features": [
              {
                "geometry": {
                  "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
                  "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
                },
                "properties": {},
                "type": "Feature"
              }
            ],
            "type": "FeatureCollection"
          },
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "name": "text"
        }
      ],
      "elements": {
        "features": [
          {
            "geometry": {
              "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
              "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
            },
            "properties": {},
            "type": "Feature"
          }
        ],
        "type": "FeatureCollection"
      },
      "folder_id": "text",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "layer_groups": [
        {
          "caption": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "layers": [
            {
              "attributes": [
                {
                  "name": "text",
                  "type": "INTEGER"
                }
              ],
              "caption": "text",
              "geometry_type": "Line",
              "hide_from_legend": true,
              "id": "luCHyMruTQ6ozGk3gPJfEB",
              "is_spreadsheet": true,
              "last_refreshed_at": "2026-01-01T00:00:00.000Z",
              "legend_display": "default",
              "legend_visibility": "hide",
              "links": {
                "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
                "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",
              "next_refresh_at": "2026-01-01T00:00:00.000Z",
              "ordering_key": 1,
              "paused_reason": "consecutive_failures",
              "progress": 1,
              "refresh_period": "15 min",
              "refresh_status": "active",
              "status": "uploading",
              "style": {},
              "tile_url": "text",
              "type": "layer"
            }
          ],
          "legend_visibility": "hide",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
          },
          "name": "text",
          "ordering_key": 1,
          "type": "layer_group",
          "visibility_interaction": "default"
        }
      ],
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ],
      "links": {
        "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC"
      },
      "project_id": "text",
      "public_access": "private",
      "table_settings": {
        "default_table_layer_id": "luCHyMruTQ6ozGk3gPJfEB",
        "viewers_can_open_table": true
      },
      "thumbnail_url": "text",
      "title": "text",
      "type": "map",
      "url": "text",
      "viewer_permissions": {
        "can_duplicate_map": true,
        "can_export_data": true,
        "can_see_map_presence": true
      },
      "visited_at": "text"
    }
    post

    Update map properties including title, description, and access permissions.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to update

    Body
    basemapstringOptional

    The basemap to use for the map. Defaults to "default". Valid values are "default", "light", "dark", "satellite", a valid raster tile URL with {x}, {y}, and {z} parameters, or a hex color string like #ff0000.

    descriptionstringOptional

    A description to display in the map legend

    public_accessstring · enumOptional

    The level of access to grant to the map. Defaults to "view_only".

    Possible values:
    default_table_layer_idstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    viewers_can_open_tablebooleanOptional

    Whether viewers can open the data table

    titlestringOptional

    The new title for the map

    can_duplicate_mapbooleanOptional

    Whether viewers can duplicate the map and data

    can_export_databooleanOptional

    Whether viewers can export map data

    can_see_map_presencebooleanOptional

    Whether viewers can see who else is viewing the map

    Responses
    200

    Map

    application/json
    basemapstringOptional
    created_atstring · date_timeRequiredExample: 2024-05-25T15:51:34
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestring · nullableOptional
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    folder_idstring · nullableOptional
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC
    project_idstringRequired
    public_accessstring · enumRequiredPossible values:
    default_table_layer_idstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    viewers_can_open_tablebooleanOptional

    Whether viewers can open the data table

    thumbnail_urlstring · nullableRequired

    A static thumbnail image of the map

    titlestringRequired
    typestring · enumRequiredPossible values:
    urlstringRequired
    can_duplicate_mapbooleanOptional

    Whether viewers can duplicate the map and data

    can_export_databooleanOptional

    Whether viewers can export map data

    can_see_map_presencebooleanOptional

    Whether viewers can see who else is viewing the map

    visited_atstring · date_time · nullableRequired
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/update
    POST /api/v2/maps/{map_id}/update HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 278
    
    {
      "basemap": "text",
      "description": "text",
      "public_access": "private",
      "table_settings": {
        "default_table_layer_id": "luCHyMruTQ6ozGk3gPJfEB",
        "viewers_can_open_table": true
      },
      "title": "text",
      "viewer_permissions": {
        "can_duplicate_map": true,
        "can_export_data": true,
        "can_see_map_presence": true
      }
    }
    {
      "basemap": "text",
      "created_at": "2024-05-25T15:51:34",
      "element_groups": [
        {
          "elements": {
            "features": [
              {
                "geometry": {
                  "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
                  "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
                },
                "properties": {},
                "type": "Feature"
              }
            ],
            "type": "FeatureCollection"
          },
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "name": "text"
        }
      ],
      "elements": {
        "features": [
          {
            "geometry": {
              "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
              "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
            },
            "properties": {},
            "type": "Feature"
          }
        ],
        "type": "FeatureCollection"
      },
      "folder_id": "text",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "layer_groups": [
        {
          "caption": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "layers": [
            {
              "attributes": [
                {
                  "name": "text",
                  "type": "INTEGER"
                }
              ],
              "caption": "text",
              "geometry_type": "Line",
              "hide_from_legend": true,
              "id": "luCHyMruTQ6ozGk3gPJfEB",
              "is_spreadsheet": true,
              "last_refreshed_at": "2026-01-01T00:00:00.000Z",
              "legend_display": "default",
              "legend_visibility": "hide",
              "links": {
                "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
                "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",
              "next_refresh_at": "2026-01-01T00:00:00.000Z",
              "ordering_key": 1,
              "paused_reason": "consecutive_failures",
              "progress": 1,
              "refresh_period": "15 min",
              "refresh_status": "active",
              "status": "uploading",
              "style": {},
              "tile_url": "text",
              "type": "layer"
            }
          ],
          "legend_visibility": "hide",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
          },
          "name": "text",
          "ordering_key": 1,
          "type": "layer_group",
          "visibility_interaction": "default"
        }
      ],
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ],
      "links": {
        "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC"
      },
      "project_id": "text",
      "public_access": "private",
      "table_settings": {
        "default_table_layer_id": "luCHyMruTQ6ozGk3gPJfEB",
        "viewers_can_open_table": true
      },
      "thumbnail_url": "text",
      "title": "text",
      "type": "map",
      "url": "text",
      "viewer_permissions": {
        "can_duplicate_map": true,
        "can_export_data": true,
        "can_see_map_presence": true
      },
      "visited_at": "text"
    }

    Get map

    get

    Retrieve a map with its metadata including title, URL, thumbnail, and timestamps.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    Responses
    200

    Map

    application/json
    basemapstringOptional
    created_atstring · date_timeRequiredExample: 2024-05-25T15:51:34
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestring · nullableOptional
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    folder_idstring · nullableOptional
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC
    project_idstringRequired
    public_accessstring · enumRequiredPossible values:
    default_table_layer_idstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    viewers_can_open_tablebooleanOptional

    Whether viewers can open the data table

    thumbnail_urlstring · nullableRequired

    A static thumbnail image of the map

    titlestringRequired
    typestring · enumRequiredPossible values:
    urlstringRequired
    can_duplicate_mapbooleanOptional

    Whether viewers can duplicate the map and data

    can_export_databooleanOptional

    Whether viewers can export map data

    can_see_map_presencebooleanOptional

    Whether viewers can see who else is viewing the map

    visited_atstring · date_time · nullableRequired
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}
    GET /api/v2/maps/{map_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "basemap": "text",
      "created_at": "2024-05-25T15:51:34",
      "element_groups": [
        {
          "elements": {
            "features": [
              {
                "geometry": {
                  "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
                  "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
                },
                "properties": {},
                "type": "Feature"
              }
            ],
            "type": "FeatureCollection"
          },
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "name": "text"
        }
      ],
      "elements": {
        "features": [
          {
            "geometry": {
              "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
              "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
            },
            "properties": {},
            "type": "Feature"
          }
        ],
        "type": "FeatureCollection"
      },
      "folder_id": "text",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "layer_groups": [
        {
          "caption": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "layers": [
            {
              "attributes": [
                {
                  "name": "text",
                  "type": "INTEGER"
                }
              ],
              "caption": "text",
              "geometry_type": "Line",
              "hide_from_legend": true,
              "id": "luCHyMruTQ6ozGk3gPJfEB",
              "is_spreadsheet": true,
              "last_refreshed_at": "2026-01-01T00:00:00.000Z",
              "legend_display": "default",
              "legend_visibility": "hide",
              "links": {
                "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
                "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",
              "next_refresh_at": "2026-01-01T00:00:00.000Z",
              "ordering_key": 1,
              "paused_reason": "consecutive_failures",
              "progress": 1,
              "refresh_period": "15 min",
              "refresh_status": "active",
              "status": "uploading",
              "style": {},
              "tile_url": "text",
              "type": "layer"
            }
          ],
          "legend_visibility": "hide",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
          },
          "name": "text",
          "ordering_key": 1,
          "type": "layer_group",
          "visibility_interaction": "default"
        }
      ],
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ],
      "links": {
        "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC"
      },
      "project_id": "text",
      "public_access": "private",
      "table_settings": {
        "default_table_layer_id": "luCHyMruTQ6ozGk3gPJfEB",
        "viewers_can_open_table": true
      },
      "thumbnail_url": "text",
      "title": "text",
      "type": "map",
      "url": "text",
      "viewer_permissions": {
        "can_duplicate_map": true,
        "can_export_data": true,
        "can_see_map_presence": true
      },
      "visited_at": "text"
    }

    Delete map

    delete

    Permanently delete a map and all its associated data.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to delete

    Responses
    204

    No Content

    No content

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    delete/api/v2/maps/{map_id}
    DELETE /api/v2/maps/{map_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    

    No content

    post

    Render the map to a PNG, JPG or PDF image at a chosen size and view — what the app's "Export as image" produces, without a browser.

    The request waits up to 55 seconds and returns 200 with a completed export. Follow download_url to download the file before expires_at. Invalid requests return 4xx; rendering failures return 503, and a render that exceeds the request deadline returns 504. There is no polling endpoint.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to export

    Body

    Output settings, geographic view and legend options for a map image export.

    show_componentsbooleanOptional

    Include the map's layer components (charts, statistics) in the legend card. Defaults to true.

    Default: true
    show_descriptionbooleanOptional

    Include the map's description under the title. Defaults to true.

    Default: true
    show_titlebooleanOptional

    Head the legend card with the map's title. Defaults to true.

    Default: true
    visiblebooleanOptional

    Draw the legend card over the map. Ignored when the map has no legend. Defaults to true.

    Default: true
    formatstring · enumOptional

    Output format. JPG is much smaller for satellite imagery. Defaults to png.

    Default: pngExample: pngPossible values:
    height_pxinteger · min: 96 · max: 16384Required

    Height of the output image file, in pixels.

    Example: 1500
    jpg_qualitynumber · max: 1Optional

    JPG quality, 0–1. Only used when format is jpg. Defaults to 0.9.

    Default: 0.9Example: 0.9
    pixel_ratiointeger · enumOptional

    Output pixels per CSS pixel of the map canvas (the app's Resolution setting). The canvas is width_px / pixel_ratio × height_px / pixel_ratio, so raising this at a fixed output size covers less ground. Defaults to 2.

    Default: 2Example: 2Possible values:
    width_pxinteger · min: 96 · max: 16384Required

    Width of the output image file, in pixels.

    Example: 2000
    show_scale_barbooleanOptional

    Draw the scale bar. Attribution is always drawn. Defaults to true.

    Default: true
    viewone ofOptional

    Choose exactly one of bounds or viewport. Omit view to use the map's default view.

    boundsnumber[] · min: 4 · max: 4Required

    [west, south, east, north] in degrees. The image is zoomed so the whole box is visible; the box is centered and the shorter axis is padded. The response's rendered_bounds reports the resulting frame. Latitudes must be within -85.051129..85.051129. A box that cannot fit at the supported zoom levels is rejected.

    Example: [-122.52,37.7,-122.35,37.83]
    or
    latitudenumber · min: -85.051129 · max: 85.051129RequiredExample: 37.77
    longitudenumber · min: -180 · max: 180RequiredExample: -122.43
    zoomnumber · min: 1 · max: 23RequiredExample: 12.5
    Responses
    200

    Completed image export

    application/json
    download_urlstringRequired

    A URL for the finished image; it redirects to the file, so follow redirects. Expires at expires_at.

    Example: https://felt.com/map-image-exports/auFxn9BO4RrGGiKrGfaS7ZB/download
    expires_atstring · date-timeRequired

    When download_url stops working.

    Example: 2026-08-28T19:04:11Z
    filenamestringRequiredExample: My map.png
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    formatstring · enumOptional

    Output format. JPG is much smaller for satellite imagery. Defaults to png.

    Default: pngExample: pngPossible values:
    height_pxinteger · min: 96 · max: 16384Required

    Height of the output image file, in pixels.

    Example: 1500
    jpg_qualitynumber · max: 1Optional

    JPG quality, 0–1. Only used when format is jpg. Defaults to 0.9.

    Default: 0.9Example: 0.9
    pixel_ratiointeger · enumOptional

    Output pixels per CSS pixel of the map canvas (the app's Resolution setting). The canvas is width_px / pixel_ratio × height_px / pixel_ratio, so raising this at a fixed output size covers less ground. Defaults to 2.

    Default: 2Example: 2Possible values:
    width_pxinteger · min: 96 · max: 16384Required

    Width of the output image file, in pixels.

    Example: 2000
    rendered_boundsnumber[] · min: 4 · max: 4Required

    The [west, south, east, north] the image actually covers — the requested view.bounds fitted to the canvas's aspect ratio, or the viewport's frame. Adjust framing from this rather than by measuring pixels. An east west of west crosses the antimeridian.

    Example: [-129,41.25,-116.1,47.03]
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    503

    ServiceUnavailableError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    504

    Gateway timeout

    application/json
    codestringOptional
    detailstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/image_exports
    POST /api/v2/maps/{map_id}/image_exports HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 254
    
    {
      "legend": {
        "show_components": true,
        "show_description": true,
        "show_title": true,
        "visible": true
      },
      "output": {
        "format": "png",
        "height_px": 1500,
        "jpg_quality": 0.9,
        "pixel_ratio": 2,
        "width_px": 2000
      },
      "show_scale_bar": true,
      "view": {
        "bounds": [
          -122.52,
          37.7,
          -122.35,
          37.83
        ]
      }
    }
    {
      "download_url": "https://felt.com/map-image-exports/auFxn9BO4RrGGiKrGfaS7ZB/download",
      "expires_at": "2026-08-28T19:04:11Z",
      "filename": "My map.png",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "output": {
        "format": "png",
        "height_px": 1500,
        "jpg_quality": 0.9,
        "pixel_ratio": 2,
        "width_px": 2000
      },
      "rendered_bounds": [
        -129,
        41.25,
        -116.1,
        47.03
      ]
    }

    Get map layer group

    get

    Retrieve detailed information about a specific layer group including its layers and configuration.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    layer_group_idstringRequired
    Responses
    200

    Layer Group

    application/json
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/layer_groups/{layer_group_id}
    GET /api/v2/maps/{map_id}/layer_groups/{layer_group_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "caption": "text",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ],
      "legend_visibility": "hide",
      "links": {
        "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
      },
      "name": "text",
      "ordering_key": 1,
      "type": "layer_group",
      "visibility_interaction": "default"
    }
    post

    Update layer group properties including name, visibility, and organization settings.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    layer_group_idstringRequired
    Body
    captionstringOptionalExample: A very interesting group
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    legend_visibilitystring · enumOptional

    Controls how the layer group is displayed in the legend

    Possible values:
    namestringOptionalExample: My Layer Group
    ordering_keyintegerOptional
    subtitlestringOptionalDeprecated

    Deprecated: use caption instead.

    visibility_interactionstring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    Responses
    200

    LayerGroup

    application/json
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layer_groups/{layer_group_id}
    POST /api/v2/maps/{map_id}/layer_groups/{layer_group_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 171
    
    {
      "caption": "A very interesting group",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "legend_visibility": "hide",
      "name": "My Layer Group",
      "ordering_key": 1,
      "visibility_interaction": "default"
    }
    {
      "caption": "text",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ],
      "legend_visibility": "hide",
      "links": {
        "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
      },
      "name": "text",
      "ordering_key": 1,
      "type": "layer_group",
      "visibility_interaction": "default"
    }
    delete

    Permanently remove a layer group and all its contained layers from a map.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    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
    204

    No Content

    No content

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    delete/api/v2/maps/{map_id}/layer_groups/{layer_group_id}
    DELETE /api/v2/maps/{map_id}/layer_groups/{layer_group_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    

    No content

    get

    Retrieve all layers from a map, including uploaded files and connected data sources.

    Every layer you have created is listed, so a layer whose upload has not finished comes back with "status": "uploading" even though the map does not show it yet — an upload that never arrives can be cleaned up by deleting the layer. Pass include_uploading=false for just the layers the map shows.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    Query parameters
    include_uploadingbooleanOptional

    Set to false to leave out the layers whose upload has not finished, matching what the map shows.

    Default: true
    Responses
    200

    Layers list

    application/json
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/layers
    GET /api/v2/maps/{map_id}/layers HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    [
      {
        "attributes": [
          {
            "name": "text",
            "type": "INTEGER"
          }
        ],
        "caption": "text",
        "geometry_type": "Line",
        "hide_from_legend": true,
        "id": "luCHyMruTQ6ozGk3gPJfEB",
        "is_spreadsheet": true,
        "last_refreshed_at": "2026-01-01T00:00:00.000Z",
        "legend_display": "default",
        "legend_visibility": "hide",
        "links": {
          "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
          "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",
        "next_refresh_at": "2026-01-01T00:00:00.000Z",
        "ordering_key": 1,
        "paused_reason": "consecutive_failures",
        "progress": 1,
        "refresh_period": "15 min",
        "refresh_status": "active",
        "status": "uploading",
        "style": {},
        "tile_url": "text",
        "type": "layer"
      }
    ]
    post

    Update layer properties including styling, visibility, grouping, and other configuration options.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    Bodyobject · LayerUpdateParams[]
    captionstringOptionalExample: A very interesting dataset
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    layer_group_idstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    legend_displaystring · enumOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enumOptional

    Controls whether or not the layer is displayed in the legend.

    Possible values:
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringOptionalExample: My Layer
    ordering_keyintegerOptional
    refresh_periodstring · enumOptionalPossible values:
    subtitlestringOptionalDeprecated

    Deprecated: use caption instead.

    Responses
    200

    Layer list

    application/json
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layers
    POST /api/v2/maps/{map_id}/layers HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 427
    
    [
      {
        "caption": "A very interesting dataset",
        "id": "luCHyMruTQ6ozGk3gPJfEB",
        "layer_group_id": "luCHyMruTQ6ozGk3gPJfEB",
        "legend_display": "default",
        "legend_visibility": "hide",
        "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"
      }
    ]
    [
      {
        "attributes": [
          {
            "name": "text",
            "type": "INTEGER"
          }
        ],
        "caption": "text",
        "geometry_type": "Line",
        "hide_from_legend": true,
        "id": "luCHyMruTQ6ozGk3gPJfEB",
        "is_spreadsheet": true,
        "last_refreshed_at": "2026-01-01T00:00:00.000Z",
        "legend_display": "default",
        "legend_visibility": "hide",
        "links": {
          "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
          "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",
        "next_refresh_at": "2026-01-01T00:00:00.000Z",
        "ordering_key": 1,
        "paused_reason": "consecutive_failures",
        "progress": 1,
        "refresh_period": "15 min",
        "refresh_status": "active",
        "status": "uploading",
        "style": {},
        "tile_url": "text",
        "type": "layer"
      }
    ]
    get

    Retrieve all layer groups from a map to see how layers are organized.

    Every layer group you have created is listed, including one whose upload has not finished and which the map does not show yet. Pass include_uploading=false for just the layer groups the map shows.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    Query parameters
    include_uploadingbooleanOptional

    Set to false to leave out the layer groups whose upload has not finished, matching what the map shows.

    Default: true
    Responses
    200

    Layers Groups

    application/json
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/layer_groups
    GET /api/v2/maps/{map_id}/layer_groups HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    [
      {
        "caption": "text",
        "id": "luCHyMruTQ6ozGk3gPJfEB",
        "layers": [
          {
            "attributes": [
              {
                "name": "text",
                "type": "INTEGER"
              }
            ],
            "caption": "text",
            "geometry_type": "Line",
            "hide_from_legend": true,
            "id": "luCHyMruTQ6ozGk3gPJfEB",
            "is_spreadsheet": true,
            "last_refreshed_at": "2026-01-01T00:00:00.000Z",
            "legend_display": "default",
            "legend_visibility": "hide",
            "links": {
              "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
              "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",
            "next_refresh_at": "2026-01-01T00:00:00.000Z",
            "ordering_key": 1,
            "paused_reason": "consecutive_failures",
            "progress": 1,
            "refresh_period": "15 min",
            "refresh_status": "active",
            "status": "uploading",
            "style": {},
            "tile_url": "text",
            "type": "layer"
          }
        ],
        "legend_visibility": "hide",
        "links": {
          "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
        },
        "name": "text",
        "ordering_key": 1,
        "type": "layer_group",
        "visibility_interaction": "default"
      }
    ]
    post

    Update properties for multiple layer groups in a single request for efficient bulk operations.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    Bodyobject · LayerGroupParams[]
    captionstringOptionalExample: A very interesting group
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    legend_visibilitystring · enumOptional

    Controls how the layer group is displayed in the legend

    Possible values:
    namestringRequiredExample: My Layer Group
    ordering_keyintegerOptional
    subtitlestringOptionalDeprecated

    Deprecated: use caption instead.

    visibility_interactionstring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    Responses
    200

    LayerGroup list

    application/json
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layer_groups
    POST /api/v2/maps/{map_id}/layer_groups HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 173
    
    [
      {
        "caption": "A very interesting group",
        "id": "luCHyMruTQ6ozGk3gPJfEB",
        "legend_visibility": "hide",
        "name": "My Layer Group",
        "ordering_key": 1,
        "visibility_interaction": "default"
      }
    ]
    [
      {
        "caption": "text",
        "id": "luCHyMruTQ6ozGk3gPJfEB",
        "layers": [
          {
            "attributes": [
              {
                "name": "text",
                "type": "INTEGER"
              }
            ],
            "caption": "text",
            "geometry_type": "Line",
            "hide_from_legend": true,
            "id": "luCHyMruTQ6ozGk3gPJfEB",
            "is_spreadsheet": true,
            "last_refreshed_at": "2026-01-01T00:00:00.000Z",
            "legend_display": "default",
            "legend_visibility": "hide",
            "links": {
              "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
              "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",
            "next_refresh_at": "2026-01-01T00:00:00.000Z",
            "ordering_key": 1,
            "paused_reason": "consecutive_failures",
            "progress": 1,
            "refresh_period": "15 min",
            "refresh_status": "active",
            "status": "uploading",
            "style": {},
            "tile_url": "text",
            "type": "layer"
          }
        ],
        "legend_visibility": "hide",
        "links": {
          "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
        },
        "name": "text",
        "ordering_key": 1,
        "type": "layer_group",
        "visibility_interaction": "default"
      }
    ]
    post

    Update the visual styling properties of a layer including colors, symbols, and rendering options.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    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
    200

    Layer

    application/json
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layers/{layer_id}/update_style
    POST /api/v2/maps/{map_id}/layers/{layer_id}/update_style HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 12
    
    {
      "style": {}
    }
    {
      "attributes": [
        {
          "name": "text",
          "type": "INTEGER"
        }
      ],
      "caption": "text",
      "geometry_type": "Line",
      "hide_from_legend": true,
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "is_spreadsheet": true,
      "last_refreshed_at": "2026-01-01T00:00:00.000Z",
      "legend_display": "default",
      "legend_visibility": "hide",
      "links": {
        "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
        "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",
      "next_refresh_at": "2026-01-01T00:00:00.000Z",
      "ordering_key": 1,
      "paused_reason": "consecutive_failures",
      "progress": 1,
      "refresh_period": "15 min",
      "refresh_status": "active",
      "status": "uploading",
      "style": {},
      "tile_url": "text",
      "type": "layer"
    }

    Get map layer

    get

    Retrieve detailed information about a specific layer including data source, styling, and configuration.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired
    layer_idstringRequired
    Responses
    200

    Layer

    application/json
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/layers/{layer_id}
    GET /api/v2/maps/{map_id}/layers/{layer_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "attributes": [
        {
          "name": "text",
          "type": "INTEGER"
        }
      ],
      "caption": "text",
      "geometry_type": "Line",
      "hide_from_legend": true,
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "is_spreadsheet": true,
      "last_refreshed_at": "2026-01-01T00:00:00.000Z",
      "legend_display": "default",
      "legend_visibility": "hide",
      "links": {
        "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
        "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",
      "next_refresh_at": "2026-01-01T00:00:00.000Z",
      "ordering_key": 1,
      "paused_reason": "consecutive_failures",
      "progress": 1,
      "refresh_period": "15 min",
      "refresh_status": "active",
      "status": "uploading",
      "style": {},
      "tile_url": "text",
      "type": "layer"
    }

    Delete map layer

    delete

    Permanently remove a layer from a map.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to delete the layer from

    layer_idstringRequired

    The ID of the layer to delete

    Responses
    204

    No Content

    No content

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    delete/api/v2/maps/{map_id}/layers/{layer_id}
    DELETE /api/v2/maps/{map_id}/layers/{layer_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    

    No content

    post

    Copy layers or layer groups to other maps, preserving styling and configuration.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Bodyone of[]
    destination_map_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    source_layer_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    or
    destination_map_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    source_layer_group_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    Responses
    200

    Duplicate Layers Response

    application/json
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/duplicate_layers
    POST /api/v2/duplicate_layers HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 92
    
    [
      {
        "destination_map_id": "luCHyMruTQ6ozGk3gPJfEB",
        "source_layer_id": "luCHyMruTQ6ozGk3gPJfEB"
      }
    ]
    {
      "layer_groups": [
        {
          "caption": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "layers": [
            {
              "attributes": [
                {
                  "name": "text",
                  "type": "INTEGER"
                }
              ],
              "caption": "text",
              "geometry_type": "Line",
              "hide_from_legend": true,
              "id": "luCHyMruTQ6ozGk3gPJfEB",
              "is_spreadsheet": true,
              "last_refreshed_at": "2026-01-01T00:00:00.000Z",
              "legend_display": "default",
              "legend_visibility": "hide",
              "links": {
                "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
                "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",
              "next_refresh_at": "2026-01-01T00:00:00.000Z",
              "ordering_key": 1,
              "paused_reason": "consecutive_failures",
              "progress": 1,
              "refresh_period": "15 min",
              "refresh_status": "active",
              "status": "uploading",
              "style": {},
              "tile_url": "text",
              "type": "layer"
            }
          ],
          "legend_visibility": "hide",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
          },
          "name": "text",
          "ordering_key": 1,
          "type": "layer_group",
          "visibility_interaction": "default"
        }
      ],
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ]
    }

    Delete map element

    delete

    Permanently delete an element from a map.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to delete the element from.

    element_idstringRequired

    The ID of the element to delete.

    Responses
    204

    No Content

    No content

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    delete/api/v2/maps/{map_id}/elements/{element_id}
    DELETE /api/v2/maps/{map_id}/elements/{element_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    

    No content

    List map elements

    get

    Returns a GeoJSON FeatureCollection containing all the elements in a map that are not in an element group.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to list elements from.

    Responses
    200

    GeoJSON

    application/json
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/elements
    GET /api/v2/maps/{map_id}/elements HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "features": [
        {
          "geometry": {
            "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
            "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
          },
          "properties": {},
          "type": "Feature"
        }
      ],
      "type": "FeatureCollection"
    }
    post

    Create new elements or update existing ones on a map using GeoJSON data. Each element is represented by a feature in the POST'ed GeoJSON Feature Collection. For each feature, including an existing element id will result in the element being updated on the map. If no element id is provided (or a non-existent one), a new element will be created.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to create the elements in

    Body
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    Responses
    200

    GeoJSON

    application/json
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/elements
    POST /api/v2/maps/{map_id}/elements HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 165
    
    {
      "features": [
        {
          "geometry": {
            "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
            "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
          },
          "properties": {},
          "type": "Feature"
        }
      ],
      "type": "FeatureCollection"
    }
    {
      "features": [
        {
          "geometry": {
            "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
            "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
          },
          "properties": {},
          "type": "Feature"
        }
      ],
      "type": "FeatureCollection"
    }

    Get map element group

    get

    Retrieve all elements from a specific group as GeoJSON.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map.

    group_idstringRequired

    The ID of the element group.

    Responses
    200

    GeoJSON

    application/json
    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/element_groups/{group_id}
    GET /api/v2/maps/{map_id}/element_groups/{group_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "features": [
        {
          "geometry": {
            "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
            "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
          },
          "properties": {},
          "type": "Feature"
        }
      ],
      "type": "FeatureCollection"
    }
    get

    Returns a list of GeoJSON FeatureCollections, one for each element group in the map.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to list groups from.

    Responses
    200

    ElementGroupList

    application/json
    colorstringRequired

    The color of the element group symbol.

    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    The ID of the element group.

    namestring · nullableRequired

    The name of the element group.

    symbolstring · nullableRequired

    The symbol used to represent the element group.

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/element_groups
    GET /api/v2/maps/{map_id}/element_groups HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    [
      {
        "color": "text",
        "elements": {
          "features": [
            {
              "geometry": {
                "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
                "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
              },
              "properties": {},
              "type": "Feature"
            }
          ],
          "type": "FeatureCollection"
        },
        "id": "text",
        "name": "text",
        "symbol": "text"
      }
    ]
    post

    Create new element groups or update existing ones.

    For each Element Group, including an existing Element Group id will result in the Element Group being updated. If no id is provided, a new Element Group will be created.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to create the group in

    Bodyobject · ElementGroupParams[]
    colorstringOptionalDefault: #C93535
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequiredExample: My Element Group
    symbolstringOptionalDefault: dot
    Responses
    200

    Element group list

    application/json
    colorstringRequired

    The color of the element group symbol.

    felt:idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    felt:parentIdstring · felt_id · nullableOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    propertiesobjectOptional
    typestring · enumOptionalPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    The ID of the element group.

    namestring · nullableRequired

    The name of the element group.

    symbolstring · nullableRequired

    The symbol used to represent the element group.

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/element_groups
    POST /api/v2/maps/{map_id}/element_groups HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 92
    
    [
      {
        "color": "#C93535",
        "id": "luCHyMruTQ6ozGk3gPJfEB",
        "name": "My Element Group",
        "symbol": "dot"
      }
    ]
    [
      {
        "color": "text",
        "elements": {
          "features": [
            {
              "geometry": {
                "felt:id": "luCHyMruTQ6ozGk3gPJfEB",
                "felt:parentId": "luCHyMruTQ6ozGk3gPJfEB"
              },
              "properties": {},
              "type": "Feature"
            }
          ],
          "type": "FeatureCollection"
        },
        "id": "text",
        "name": "text",
        "symbol": "text"
      }
    ]
    get

    Retrieve all projects accessible to the authenticated user within the workspace.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Query parameters
    workspace_idstringOptional

    Only needed when using the API as part of a plugin

    Responses
    200

    Projects

    application/json
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    selfstringOptionalExample: https://felt.com/api/v2/projects/V0dnOMOuTd9B9BOsL9C0UjmqC
    max_inherited_permissionstring · enumRequired

    The maximum permission level workspace members inherit on team-visible projects.

    Example: view_onlyPossible values:
    namestringRequired
    typestring · enumRequiredPossible values:
    visibilitystring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/projects
    GET /api/v2/projects HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    [
      {
        "id": "luCHyMruTQ6ozGk3gPJfEB",
        "links": {
          "self": "https://felt.com/api/v2/projects/V0dnOMOuTd9B9BOsL9C0UjmqC"
        },
        "max_inherited_permission": "view_only",
        "name": "text",
        "type": "project_reference",
        "visibility": "workspace"
      }
    ]
    post

    Create a new project with specified name and visibility settings within the workspace.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Body
    max_inherited_permissionstring · enumOptional

    The maximum permission level workspace members inherit on team-visible projects. Only applicable when visibility is "workspace".

    Example: view_onlyPossible values:
    namestringRequired

    The name to be used for the Project

    visibilitystring · enumRequired

    Either viewable by all members of the workspace, or private to users who are invited.

    Possible values:
    Responses
    200

    Project

    application/json
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    created_atstring · date_timeRequiredExample: 2024-05-25T15:51:34
    folder_idstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC
    project_idstringRequired
    public_accessstring · enumRequiredPossible values:
    thumbnail_urlstring · nullableRequired

    A static thumbnail image of the map

    titlestringRequired
    typestring · enumRequiredPossible values:
    urlstringRequired
    visited_atstring · date_time · nullableRequired
    max_inherited_permissionstring · enumRequired

    The maximum permission level workspace members inherit on team-visible projects.

    Example: view_onlyPossible values:
    namestringRequired
    typestring · enumRequiredPossible values:
    visibilitystring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/projects
    POST /api/v2/projects HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 79
    
    {
      "max_inherited_permission": "view_only",
      "name": "text",
      "visibility": "workspace"
    }
    {
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "maps": [
        {
          "created_at": "2024-05-25T15:51:34",
          "folder_id": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC"
          },
          "project_id": "text",
          "public_access": "private",
          "thumbnail_url": "text",
          "title": "text",
          "type": "map_reference",
          "url": "text",
          "visited_at": "text"
        }
      ],
      "max_inherited_permission": "view_only",
      "name": "text",
      "type": "project",
      "visibility": "workspace"
    }

    Get project

    get

    Retrieve detailed information about a specific project including metadata, permissions, and references to the maps in the project.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    project_idstringRequired
    Responses
    200

    Project

    application/json
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    created_atstring · date_timeRequiredExample: 2024-05-25T15:51:34
    folder_idstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC
    project_idstringRequired
    public_accessstring · enumRequiredPossible values:
    thumbnail_urlstring · nullableRequired

    A static thumbnail image of the map

    titlestringRequired
    typestring · enumRequiredPossible values:
    urlstringRequired
    visited_atstring · date_time · nullableRequired
    max_inherited_permissionstring · enumRequired

    The maximum permission level workspace members inherit on team-visible projects.

    Example: view_onlyPossible values:
    namestringRequired
    typestring · enumRequiredPossible values:
    visibilitystring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/projects/{project_id}
    GET /api/v2/projects/{project_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "maps": [
        {
          "created_at": "2024-05-25T15:51:34",
          "folder_id": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC"
          },
          "project_id": "text",
          "public_access": "private",
          "thumbnail_url": "text",
          "title": "text",
          "type": "map_reference",
          "url": "text",
          "visited_at": "text"
        }
      ],
      "max_inherited_permission": "view_only",
      "name": "text",
      "type": "project",
      "visibility": "workspace"
    }

    Delete project

    delete

    Permanently delete a project and all its contained maps and folders.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    project_idstringRequired

    The ID of the Project to delete. Note: This will delete all Folders and Maps inside the project!

    Responses
    204

    No Content

    No content

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    delete/api/v2/projects/{project_id}
    DELETE /api/v2/projects/{project_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    

    No content

    post

    Update project properties including name and visibility settings.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    project_idstringRequired

    The ID of the project to update

    Body
    max_inherited_permissionstring · enumOptional

    The maximum permission level workspace members inherit on team-visible projects. Only applicable when visibility is "workspace".

    Example: view_onlyPossible values:
    namestringOptional

    The name to be used for the Project

    visibilitystring · enumOptional

    Either viewable by all members of the workspace, or private to users who are invited.

    Possible values:
    Responses
    200

    Project

    application/json
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    created_atstring · date_timeRequiredExample: 2024-05-25T15:51:34
    folder_idstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC
    project_idstringRequired
    public_accessstring · enumRequiredPossible values:
    thumbnail_urlstring · nullableRequired

    A static thumbnail image of the map

    titlestringRequired
    typestring · enumRequiredPossible values:
    urlstringRequired
    visited_atstring · date_time · nullableRequired
    max_inherited_permissionstring · enumRequired

    The maximum permission level workspace members inherit on team-visible projects.

    Example: view_onlyPossible values:
    namestringRequired
    typestring · enumRequiredPossible values:
    visibilitystring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/projects/{project_id}/update
    POST /api/v2/projects/{project_id}/update HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 79
    
    {
      "max_inherited_permission": "view_only",
      "name": "text",
      "visibility": "workspace"
    }
    {
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "maps": [
        {
          "created_at": "2024-05-25T15:51:34",
          "folder_id": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC"
          },
          "project_id": "text",
          "public_access": "private",
          "thumbnail_url": "text",
          "title": "text",
          "type": "map_reference",
          "url": "text",
          "visited_at": "text"
        }
      ],
      "max_inherited_permission": "view_only",
      "name": "text",
      "type": "project",
      "visibility": "workspace"
    }
    get

    Generate a direct download link for layer data export.

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

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map where the layer is located

    layer_idstringRequired

    The ID of the layer to export

    Responses
    200

    Export link

    application/json
    export_linkstringRequired
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    503

    ServiceUnavailableError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/layers/{layer_id}/get_export_link
    GET /api/v2/maps/{map_id}/layers/{layer_id}/get_export_link HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "export_link": "text"
    }
    get

    Check the processing status and download availability of a custom export request.

    If the export is successful, the response will include a download_url for accessing the exported data.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    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
    200

    Custom export request status

    application/json
    download_urlstring · nullableRequiredExample: https://us1.data-pipeline.felt.com/fcdfd96c-06fa-40b9-9ae9-ad034b5a66df/Felt-Export.zip
    export_idstringRequiredExample: FZWQjWZJSZWvW3yn9BeV9AyA
    itemsanyOptional
    statusstring · enumRequiredExample: completedPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/layers/{layer_id}/custom_exports/{export_id}
    GET /api/v2/maps/{map_id}/layers/{layer_id}/custom_exports/{export_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "download_url": "https://us1.data-pipeline.felt.com/fcdfd96c-06fa-40b9-9ae9-ad034b5a66df/Felt-Export.zip",
      "export_id": "FZWQjWZJSZWvW3yn9BeV9AyA",
      "filters": [],
      "status": "completed"
    }
    post

    Start a custom export with specific format and filter options for layer data.

    Export requests are asynchronous. A successful response will return a poll_endpoint to check the status of the export using the poll custom export endpoint.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map where the layer is located

    layer_idstringRequired

    The ID of the layer to export

    Body
    email_on_completionbooleanOptional

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

    itemsanyOptional
    output_formatstring · enumRequiredExample: csvPossible values:
    Responses
    200

    Custom export response

    application/json
    export_request_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    poll_endpointstringRequiredExample: http://felt.com/api/v2/maps/vAbZ5eKqRoGe4sCH8nHW8D/layers/7kF9Cfz45TUWIiuuWV8uZ7A/custom_exports/auFxn9BO4RrGGiKrGfaS7ZB
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    503

    ServiceUnavailableError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layers/{layer_id}/custom_export
    POST /api/v2/maps/{map_id}/layers/{layer_id}/custom_export HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    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"
    }
    post

    Update data source connection settings, access permissions, or configuration details.

    Connecting the Source and inspecting its datasets will happen asynchronously after the API response is returned. To determine when the inspection process has completed, poll the Show Source endpoint and check for sync_status: completed.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    source_idstringRequired

    The ID of the source to update

    Body
    connectionone ofOptional
    blob_storage_urlstringOptional

    ABS blob storage URL

    typestring · enumRequiredPossible values:
    or
    base64_encoded_service_accountstring · nullableOptional

    BigQuery credentials - Base 64 encoded Service account JSON

    datasetstring · nullableOptional

    BigQuery dataset

    projectstringOptional

    BigQuery project

    typestring · enumRequiredPossible values:
    or
    catalogstring · nullableOptional

    Databricks catalog

    http_pathstringOptional

    Databricks server HTTP path

    schemastring · nullableOptional

    Databricks schema

    server_hostnamestringOptional

    Databricks server hostname

    typestring · enumRequiredPossible values:
    or
    tokenstring · nullableOptional

    ESRI server token

    typestring · enumRequiredPossible values:
    urlstringOptional

    ESRI FeatureServer, MapServer, or ImageServer URL

    or
    gs_uristringOptional

    GCS URI

    typestring · enumRequiredPossible values:
    or
    databasestringOptional

    MSSQL database name

    hoststringOptional

    MSSQL host

    passwordstringOptional

    MSSQL password

    portinteger · nullableOptional

    MSSQL port

    typestring · enumRequiredPossible values:
    userstringOptional

    MSSQL user name

    or
    databasestringOptional

    Postgres database name

    hoststringOptional

    Postgres host

    passwordstringOptional

    Postgres password

    portinteger · nullableOptional

    Postgres port

    schemastringOptional

    Postgres schema

    typestring · enumRequiredPossible values:
    userstringOptional

    Postgres user name

    or
    databasestringOptional

    Redshift database name

    hoststringOptional

    Redshift host

    passwordstringOptional

    Redshift password

    portinteger · nullableOptional

    Redshift port

    typestring · enumRequiredPossible values:
    userstringOptional

    Redshift user name

    or
    s3_uristringOptional

    S3 URI

    typestring · enumRequiredPossible values:
    or
    account_idstringOptional

    Snowflake account ID

    databasestringOptional

    Snowflake database name

    passwordstringOptional

    Snowflake password

    rolestring · nullableOptional

    Snowflake role

    schemastring · nullableOptional

    Snowflake database schema

    typestring · enumRequiredPossible values:
    userstringOptional

    Snowflake user name

    warehousestring · nullableOptional

    Snowflake warehouse

    or
    tokenstring · nullableOptional

    STAC token

    typestring · enumRequiredPossible values:
    urlstringOptional

    STAC server / asset URL

    or
    typestring · enumRequiredPossible values:
    urlstringOptional

    WFS URL

    or
    typestring · enumRequiredPossible values:
    urlstringOptional

    WMS/WMTS URL

    namestringOptional
    permissionsone ofOptional
    typestring · enumRequiredPossible values:
    or
    typestring · enumRequiredPossible values:
    or
    project_idsstring · felt_id[]RequiredExample: luCHyMruTQ6ozGk3gPJfEB
    typestring · enumRequiredPossible values:
    Responses
    202

    Source reference

    application/json
    automatic_syncstring · enumOptionalPossible values:
    connection_typestring · enumOptionalPossible values:
    created_atinteger · nullableOptional
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    last_synced_atinteger · nullableOptional
    selfstringOptionalExample: https://felt.com/api/v2/sources/V0dnOMOuTd9B9BOsL9C0UjmqC
    namestringOptional
    owner_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    permissionsone ofOptional
    typestring · enumRequiredPossible values:
    or
    typestring · enumRequiredPossible values:
    or
    project_idsstring · felt_id[]RequiredExample: luCHyMruTQ6ozGk3gPJfEB
    typestring · enumRequiredPossible values:
    sync_statusstring · enumOptionalPossible values:
    typestring · enumOptionalPossible values:
    updated_atinteger · nullableOptional
    workspace_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/sources/{source_id}/update
    POST /api/v2/sources/{source_id}/update HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 119
    
    {
      "connection": {
        "blob_storage_url": "text",
        "type": "abs_bucket"
      },
      "name": "text",
      "permissions": {
        "type": "workspace_editors"
      }
    }
    {
      "automatic_sync": "enabled",
      "connection_type": "abs_bucket",
      "created_at": 1,
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "last_synced_at": 1,
      "links": {
        "self": "https://felt.com/api/v2/sources/V0dnOMOuTd9B9BOsL9C0UjmqC"
      },
      "name": "text",
      "owner_id": "luCHyMruTQ6ozGk3gPJfEB",
      "permissions": {
        "type": "workspace_editors"
      },
      "sync_status": "syncing",
      "type": "source_reference",
      "updated_at": 1,
      "workspace_id": "luCHyMruTQ6ozGk3gPJfEB"
    }

    List sources

    get

    Retrieve all data sources accessible to the authenticated user within the workspace.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Query parameters
    workspace_idstringOptional

    Only needed when using the API as part of a plugin

    Responses
    200

    Source references

    application/json
    automatic_syncstring · enumOptionalPossible values:
    connection_typestring · enumOptionalPossible values:
    created_atinteger · nullableOptional
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    last_synced_atinteger · nullableOptional
    selfstringOptionalExample: https://felt.com/api/v2/sources/V0dnOMOuTd9B9BOsL9C0UjmqC
    namestringOptional
    owner_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    permissionsone ofOptional
    typestring · enumRequiredPossible values:
    or
    typestring · enumRequiredPossible values:
    or
    project_idsstring · felt_id[]RequiredExample: luCHyMruTQ6ozGk3gPJfEB
    typestring · enumRequiredPossible values:
    sync_statusstring · enumOptionalPossible values:
    typestring · enumOptionalPossible values:
    updated_atinteger · nullableOptional
    workspace_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/sources
    GET /api/v2/sources HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    [
      {
        "automatic_sync": "enabled",
        "connection_type": "abs_bucket",
        "created_at": 1,
        "id": "luCHyMruTQ6ozGk3gPJfEB",
        "last_synced_at": 1,
        "links": {
          "self": "https://felt.com/api/v2/sources/V0dnOMOuTd9B9BOsL9C0UjmqC"
        },
        "name": "text",
        "owner_id": "luCHyMruTQ6ozGk3gPJfEB",
        "permissions": {
          "type": "workspace_editors"
        },
        "sync_status": "syncing",
        "type": "source_reference",
        "updated_at": 1,
        "workspace_id": "luCHyMruTQ6ozGk3gPJfEB"
      }
    ]
    post

    Create a new data source connection with authentication credentials and access permissions.

    Connecting the Source and inspecting its datasets will happen asynchronously after the API response is returned. To determine when the inspection process has completed, poll the Show Source endpoint and check for sync_status: completed.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Body
    connectionone ofRequired
    blob_storage_urlstringRequired

    ABS blob storage URL

    connection_stringstringRequired
    typestring · enumRequiredPossible values:
    namestringRequired
    use_casestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    base64_encoded_service_accountstring · nullableOptional

    BigQuery credentials - Base 64 encoded Service account JSON

    datasetstring · nullableOptional

    BigQuery dataset

    projectstringRequired

    BigQuery project

    typestring · enumRequiredPossible values:
    or
    catalogstring · nullableOptional

    Databricks catalog

    credentialone ofRequired
    tokenstringRequired
    typestring · enumRequiredPossible values:
    or
    client_idstringRequired
    client_secretstringRequired
    typestring · enumRequiredPossible values:
    namestringRequired
    use_casestring · enumRequiredPossible values:
    http_pathstringRequired

    Databricks server HTTP path

    schemastring · nullableOptional

    Databricks schema

    server_hostnamestringRequired

    Databricks server hostname

    typestring · enumRequiredPossible values:
    or
    tokenstring · nullableOptional

    ESRI server token

    typestring · enumRequiredPossible values:
    urlstringRequired

    ESRI FeatureServer, MapServer, or ImageServer URL

    or
    service_account_filenamestringRequired
    service_account_jsonone ofRequired
    objectOptional
    or
    stringOptional
    typestring · enumRequiredPossible values:
    namestringRequired
    use_casestring · enumRequiredPossible values:
    gs_uristringRequired

    GCS URI

    typestring · enumRequiredPossible values:
    or
    databasestringRequired

    MSSQL database name

    hoststringRequired

    MSSQL host

    passwordstringRequired

    MSSQL password

    portinteger · nullableOptional

    MSSQL port

    typestring · enumRequiredPossible values:
    userstringRequired

    MSSQL user name

    or
    databasestringRequired

    Postgres database name

    hoststringRequired

    Postgres host

    passwordstringRequired

    Postgres password

    portinteger · nullableOptional

    Postgres port

    schemastringOptional

    Postgres schema

    typestring · enumRequiredPossible values:
    userstringRequired

    Postgres user name

    or
    databasestringRequired

    Redshift database name

    hoststringRequired

    Redshift host

    passwordstringRequired

    Redshift password

    portinteger · nullableOptional

    Redshift port

    typestring · enumRequiredPossible values:
    userstringRequired

    Redshift user name

    or
    role_arnstringRequired
    role_session_namestringRequired
    typestring · enumRequiredPossible values:
    namestringRequired
    use_casestring · enumRequiredPossible values:
    s3_uristringRequired

    S3 URI

    typestring · enumRequiredPossible values:
    or
    account_idstringRequired

    Snowflake account ID

    credentialone ofRequired
    private_keystringRequired
    private_key_namestringRequired
    private_key_passphrasestringOptional
    typestring · enumRequiredPossible values:
    or
    tokenstringRequired
    typestring · enumRequiredPossible values:
    namestringRequired
    use_casestring · enumRequiredPossible values:
    databasestringRequired

    Snowflake database name

    passwordstringOptional

    Snowflake password

    rolestring · nullableOptional

    Snowflake role

    schemastring · nullableOptional

    Snowflake database schema

    typestring · enumRequiredPossible values:
    userstringRequired

    Snowflake user name

    warehousestring · nullableOptional

    Snowflake warehouse

    or
    credentialone ofRequired
    role_arnstringRequired
    role_session_namestringRequired
    typestring · enumRequiredPossible values:
    or
    connection_stringstringRequired
    typestring · enumRequiredPossible values:
    or
    service_account_filenamestringRequired
    service_account_jsonone ofRequired
    objectOptional
    or
    stringOptional
    typestring · enumRequiredPossible values:
    or
    namestringRequired

    The header name

    sensitivebooleanRequired

    Whether or not the header is sensitive. If it is marked as sensitive, then felt:redacted will be returned when viewing this header

    valuestringRequired

    The header value

    typestring · enumRequiredPossible values:
    namestringRequired
    use_casestring · enumRequiredPossible values:
    tokenstring · nullableOptional

    STAC token

    typestring · enumRequiredPossible values:
    urlstringRequired

    STAC server / asset URL

    or
    typestring · enumRequiredPossible values:
    urlstringRequired

    WFS URL

    or
    typestring · enumRequiredPossible values:
    urlstringRequired

    WMS/WMTS URL

    namestringRequired
    permissionsone ofOptional
    typestring · enumRequiredPossible values:
    or
    typestring · enumRequiredPossible values:
    or
    project_idsstring · felt_id[]RequiredExample: luCHyMruTQ6ozGk3gPJfEB
    typestring · enumRequiredPossible values:
    Responses
    202

    Source reference

    application/json
    automatic_syncstring · enumOptionalPossible values:
    connection_typestring · enumOptionalPossible values:
    created_atinteger · nullableOptional
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    last_synced_atinteger · nullableOptional
    selfstringOptionalExample: https://felt.com/api/v2/sources/V0dnOMOuTd9B9BOsL9C0UjmqC
    namestringOptional
    owner_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    permissionsone ofOptional
    typestring · enumRequiredPossible values:
    or
    typestring · enumRequiredPossible values:
    or
    project_idsstring · felt_id[]RequiredExample: luCHyMruTQ6ozGk3gPJfEB
    typestring · enumRequiredPossible values:
    sync_statusstring · enumOptionalPossible values:
    typestring · enumOptionalPossible values:
    updated_atinteger · nullableOptional
    workspace_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/sources
    POST /api/v2/sources HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 269
    
    {
      "connection": {
        "blob_storage_url": "text",
        "credentials": [
          {
            "credential": {
              "connection_string": "text",
              "type": "azure_storage_connection_string"
            },
            "name": "text",
            "use_case": "source_authentication"
          }
        ],
        "type": "abs_bucket"
      },
      "name": "text",
      "permissions": {
        "type": "workspace_editors"
      }
    }
    {
      "automatic_sync": "enabled",
      "connection_type": "abs_bucket",
      "created_at": 1,
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "last_synced_at": 1,
      "links": {
        "self": "https://felt.com/api/v2/sources/V0dnOMOuTd9B9BOsL9C0UjmqC"
      },
      "name": "text",
      "owner_id": "luCHyMruTQ6ozGk3gPJfEB",
      "permissions": {
        "type": "workspace_editors"
      },
      "sync_status": "syncing",
      "type": "source_reference",
      "updated_at": 1,
      "workspace_id": "luCHyMruTQ6ozGk3gPJfEB"
    }
    post

    Trigger a full data synchronization from the source to update all connected layers with latest data.

    Syncing will happen asynchronously after the API response is returned. To determine when the inspection process has completed, poll the Show Source endpoint and check for sync_status: completed.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    source_idstringRequired

    The ID of the source to sync

    Responses
    202

    Source reference

    application/json
    automatic_syncstring · enumOptionalPossible values:
    connection_typestring · enumOptionalPossible values:
    created_atinteger · nullableOptional
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    last_synced_atinteger · nullableOptional
    selfstringOptionalExample: https://felt.com/api/v2/sources/V0dnOMOuTd9B9BOsL9C0UjmqC
    namestringOptional
    owner_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    permissionsone ofOptional
    typestring · enumRequiredPossible values:
    or
    typestring · enumRequiredPossible values:
    or
    project_idsstring · felt_id[]RequiredExample: luCHyMruTQ6ozGk3gPJfEB
    typestring · enumRequiredPossible values:
    sync_statusstring · enumOptionalPossible values:
    typestring · enumOptionalPossible values:
    updated_atinteger · nullableOptional
    workspace_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/sources/{source_id}/sync
    POST /api/v2/sources/{source_id}/sync HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "automatic_sync": "enabled",
      "connection_type": "abs_bucket",
      "created_at": 1,
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "last_synced_at": 1,
      "links": {
        "self": "https://felt.com/api/v2/sources/V0dnOMOuTd9B9BOsL9C0UjmqC"
      },
      "name": "text",
      "owner_id": "luCHyMruTQ6ozGk3gPJfEB",
      "permissions": {
        "type": "workspace_editors"
      },
      "sync_status": "syncing",
      "type": "source_reference",
      "updated_at": 1,
      "workspace_id": "luCHyMruTQ6ozGk3gPJfEB"
    }
    get

    Retrieve detailed configuration and connection information for a specific data source.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    source_idstringRequired

    The ID of the source to show

    Responses
    200

    Source

    application/json
    automatic_syncstring · enumOptionalPossible values:
    connectionone of · nullableOptional
    blob_storage_urlstringOptional
    created_atinteger · nullableOptional
    credentialone ofOptional
    connection_stringstringRequired
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestringOptional
    source_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    updated_atinteger · nullableOptional
    use_casestring · enumOptionalPossible values:
    typestring · enumOptionalPossible values:
    or
    datasetstring · nullableOptional

    BigQuery dataset to index. If omitted all datasets will be indexed

    projectstringOptional

    BigQuery project to index

    typestring · enumOptionalPossible values:
    or
    catalogstring · nullableOptional
    created_atinteger · nullableOptional
    credentialone ofOptional
    client_idstringRequired
    client_secretstringRequired
    typestring · enumRequiredPossible values:
    or
    tokenstringRequired
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestringOptional
    source_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    updated_atinteger · nullableOptional
    use_casestring · enumOptionalPossible values:
    http_pathstringOptional
    schemastring · nullableOptional
    server_hostnamestringOptional
    typestring · enumOptionalPossible values:
    or
    typestring · enumOptionalPossible values:
    urlstringOptional
    or
    created_atinteger · nullableOptional
    credentialone ofOptional
    service_account_filenamestringRequired
    service_account_jsonone ofRequired
    objectOptional
    or
    stringOptional
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestringOptional
    source_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    updated_atinteger · nullableOptional
    use_casestring · enumOptionalPossible values:
    gs_uristringOptional
    typestring · enumOptionalPossible values:
    or
    databasestringOptional
    hoststringOptional
    portinteger · nullableOptional
    typestring · enumOptionalPossible values:
    userstringOptional
    or
    databasestringOptional
    hoststringOptional
    portinteger · nullableOptional
    schemastring · nullableOptional
    typestring · enumOptionalPossible values:
    userstringOptional
    or
    databasestringOptional
    hoststringOptional
    portinteger · nullableOptional
    typestring · enumOptionalPossible values:
    userstringOptional
    or
    created_atinteger · nullableOptional
    credentialone ofOptional
    role_arnstringRequired
    role_session_namestringRequired
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestringOptional
    source_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    updated_atinteger · nullableOptional
    use_casestring · enumOptionalPossible values:
    s3_uristringOptional
    typestring · enumOptionalPossible values:
    or
    account_idstringOptional
    created_atinteger · nullableOptional
    credentialone ofOptional
    tokenstringRequired
    typestring · enumRequiredPossible values:
    or
    private_keystringRequired
    private_key_namestringRequired
    private_key_passphrasestringOptional
    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestringOptional
    source_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    updated_atinteger · nullableOptional
    use_casestring · enumOptionalPossible values:
    databasestringOptional
    rolestring · nullableOptional
    schemastring · nullableOptional
    typestring · enumOptionalPossible values:
    userstringOptional
    warehousestring · nullableOptional
    or
    created_atinteger · nullableOptional
    credentialone ofOptional
    service_account_filenamestringRequired
    service_account_jsonone ofRequired
    objectOptional
    or
    stringOptional
    typestring · enumRequiredPossible values:
    or
    connection_stringstringRequired
    typestring · enumRequiredPossible values:
    or
    role_arnstringRequired
    role_session_namestringRequired
    typestring · enumRequiredPossible values:
    or
    namestringRequired

    The header name

    sensitivebooleanRequired

    Whether or not the header is sensitive. If it is marked as sensitive, then felt:redacted will be returned when viewing this header

    valuestringRequired

    The header value

    typestring · enumRequiredPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    namestringOptional
    source_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    updated_atinteger · nullableOptional
    use_casestring · enumOptionalPossible values:
    typestring · enumOptionalPossible values:
    urlstringOptional
    or
    typestring · enumOptionalPossible values:
    urlstringOptional
    or
    typestring · enumOptionalPossible values:
    urlstringOptional
    created_atinteger · nullableOptional
    created_atintegerOptional
    descriptionstring · nullableOptional
    geometry_typestring · enumOptionalPossible values:
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    inspection_statusstring · enumOptionalPossible values:
    namestringOptional
    typestring · enumOptionalPossible values:
    updated_atintegerOptional
    idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    last_synced_atinteger · nullableOptional
    namestringOptional
    owner_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    permissionsone ofOptional
    typestring · enumRequiredPossible values:
    or
    typestring · enumRequiredPossible values:
    or
    project_idsstring · felt_id[]RequiredExample: luCHyMruTQ6ozGk3gPJfEB
    typestring · enumRequiredPossible values:
    sync_statusstring · enumOptionalPossible values:
    typestring · enumOptionalPossible values:
    updated_atinteger · nullableOptional
    workspace_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/sources/{source_id}
    GET /api/v2/sources/{source_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "automatic_sync": "enabled",
      "connection": {
        "blob_storage_url": "text",
        "credentials": [
          {
            "created_at": 1,
            "credential": {
              "connection_string": "text",
              "type": "azure_storage_connection_string"
            },
            "id": "luCHyMruTQ6ozGk3gPJfEB",
            "name": "text",
            "source_id": "luCHyMruTQ6ozGk3gPJfEB",
            "updated_at": 1,
            "use_case": "source_authentication"
          }
        ],
        "type": "abs_bucket"
      },
      "created_at": 1,
      "datasets": [
        {
          "created_at": 1,
          "description": "text",
          "geometry_type": "polygon",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "inspection_status": "completed",
          "name": "text",
          "type": "dataset",
          "updated_at": 1
        }
      ],
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "last_synced_at": 1,
      "name": "text",
      "owner_id": "luCHyMruTQ6ozGk3gPJfEB",
      "permissions": {
        "type": "workspace_editors"
      },
      "sync_status": "syncing",
      "type": "source",
      "updated_at": 1,
      "workspace_id": "luCHyMruTQ6ozGk3gPJfEB"
    }

    Delete source

    delete

    Permanently delete a data source connection and all its associated layers and data.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    source_idstringRequired

    The ID of the source to delete

    Responses
    204

    No Content

    No content

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    delete/api/v2/sources/{source_id}
    DELETE /api/v2/sources/{source_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    

    No content

    post

    Add authentication credentials to an existing data source for secure access.

    Some sources may need to be configured with additional credentials to work with Felt. Access to S3 Buckets, for example, may be protected by IAM policies. Adding a SourceCredential-AwsAssumeRole credential to your S3 Bucket source allows Felt to connect to a private source.

    Sensitive fields in credentials, like SourceCredential-KeyPair.private_key, will be returned as felt:redacted.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    source_idstringRequired

    The ID of the source to attach the credential

    Body
    credentialone ofRequired
    role_arnstringRequired
    role_session_namestringRequired
    typestring · enumRequiredPossible values:
    or
    connection_stringstringRequired
    typestring · enumRequiredPossible values:
    or
    namestringRequired

    The header name

    sensitivebooleanRequired

    Whether or not the header is sensitive. If it is marked as sensitive, then felt:redacted will be returned when viewing this header

    valuestringRequired

    The header value

    typestring · enumRequiredPossible values:
    or
    service_account_filenamestringRequired
    service_account_jsonone ofRequired
    objectOptional
    or
    stringOptional
    typestring · enumRequiredPossible values:
    or
    private_keystringRequired
    private_key_namestringRequired
    private_key_passphrasestringOptional
    typestring · enumRequiredPossible values:
    or
    tokenstringRequired
    typestring · enumRequiredPossible values:
    namestringRequired
    use_casestring · enumRequiredPossible values:
    Responses
    202

    Source credential created

    application/json
    created_atinteger · nullableRequired
    credentialone ofRequired
    role_arnstringRequired
    role_session_namestringRequired
    typestring · enumRequiredPossible values:
    or
    connection_stringstringRequired
    typestring · enumRequiredPossible values:
    or
    namestringRequired

    The header name

    sensitivebooleanRequired

    Whether or not the header is sensitive. If it is marked as sensitive, then felt:redacted will be returned when viewing this header

    valuestringRequired

    The header value

    typestring · enumRequiredPossible values:
    or
    service_account_filenamestringRequired
    service_account_jsonone ofRequired
    objectOptional
    or
    stringOptional
    typestring · enumRequiredPossible values:
    or
    private_keystringRequired
    private_key_namestringRequired
    private_key_passphrasestringOptional
    typestring · enumRequiredPossible values:
    or
    tokenstringRequired
    typestring · enumRequiredPossible values:
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired
    source_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    updated_atinteger · nullableRequired
    use_casestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/sources/{source_id}/credentials
    POST /api/v2/sources/{source_id}/credentials HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 137
    
    {
      "credential": {
        "role_arn": "text",
        "role_session_name": "text",
        "type": "aws_assume_role"
      },
      "name": "text",
      "use_case": "stac_api_authentication"
    }
    {
      "created_at": 1,
      "credential": {
        "role_arn": "text",
        "role_session_name": "text",
        "type": "aws_assume_role"
      },
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "name": "text",
      "source_id": "luCHyMruTQ6ozGk3gPJfEB",
      "updated_at": 1,
      "use_case": "stac_api_authentication"
    }
    post

    Update existing authentication credentials for a data source connection.

    Sensitive fields in credentials, like SourceCredential-KeyPair.private_key, will be returned as felt:redacted.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    source_idstringRequired

    The ID of the source that the credential belongs to

    credential_idstringRequired

    The ID of the credential

    Body
    credentialone ofOptional
    role_arnstringOptional
    role_session_namestringOptional
    typestring · enumRequiredPossible values:
    or
    connection_stringstringOptional
    typestring · enumRequiredPossible values:
    or
    namestringRequired

    The header name

    sensitivebooleanRequired

    Whether or not the header is sensitive. If it is marked as sensitive, then felt:redacted will be returned when viewing this header

    valuestringRequired

    The header value

    typestring · enumRequiredPossible values:
    or
    service_account_filenamestringOptional
    service_account_jsonone ofOptional
    objectOptional
    or
    stringOptional
    typestring · enumRequiredPossible values:
    or
    private_keystringOptional
    private_key_namestringOptional
    private_key_passphrasestringOptional
    typestring · enumRequiredPossible values:
    or
    tokenstringOptional
    typestring · enumRequiredPossible values:
    namestringOptional
    use_casestring · enumOptionalPossible values:
    Responses
    202

    Source credential updated

    application/json
    created_atinteger · nullableRequired
    credentialone ofRequired
    role_arnstringRequired
    role_session_namestringRequired
    typestring · enumRequiredPossible values:
    or
    connection_stringstringRequired
    typestring · enumRequiredPossible values:
    or
    namestringRequired

    The header name

    sensitivebooleanRequired

    Whether or not the header is sensitive. If it is marked as sensitive, then felt:redacted will be returned when viewing this header

    valuestringRequired

    The header value

    typestring · enumRequiredPossible values:
    or
    service_account_filenamestringRequired
    service_account_jsonone ofRequired
    objectOptional
    or
    stringOptional
    typestring · enumRequiredPossible values:
    or
    private_keystringRequired
    private_key_namestringRequired
    private_key_passphrasestringOptional
    typestring · enumRequiredPossible values:
    or
    tokenstringRequired
    typestring · enumRequiredPossible values:
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired
    source_idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    updated_atinteger · nullableRequired
    use_casestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/sources/{source_id}/credentials/{credential_id}/update
    POST /api/v2/sources/{source_id}/credentials/{credential_id}/update HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 137
    
    {
      "credential": {
        "role_arn": "text",
        "role_session_name": "text",
        "type": "aws_assume_role"
      },
      "name": "text",
      "use_case": "stac_api_authentication"
    }
    {
      "created_at": 1,
      "credential": {
        "role_arn": "text",
        "role_session_name": "text",
        "type": "aws_assume_role"
      },
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "name": "text",
      "source_id": "luCHyMruTQ6ozGk3gPJfEB",
      "updated_at": 1,
      "use_case": "stac_api_authentication"
    }

    Delete source credential

    delete

    Remove authentication credentials from a data source connection.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    source_idstringRequired

    The ID of the source that the credential belongs to

    credential_idstringRequired

    The ID of the credential to delete

    Responses
    204

    No Content

    No content

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    delete/api/v2/sources/{source_id}/credentials/{credential_id}
    DELETE /api/v2/sources/{source_id}/credentials/{credential_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    

    No content

    Export map comments

    get

    Export all comments and replies from a map in CSV, JSON, or GeoJSON format.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map to export comments from.

    Query parameters
    formatstringOptional

    The format to export the comments in: 'csv', 'json' (default), or 'geojson'

    Responses
    200

    Comment export response

    application/json

    Comment Thread

    itemsanyOptional

    Comment Thread

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/comments/export
    GET /api/v2/maps/{map_id}/comments/export HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    []

    Resolve map comment

    post

    Mark a comment thread as resolved.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map that contains the comment.

    comment_idstringRequired

    The ID of the comment to resolve.

    Responses
    200

    Comment resolved response

    application/json
    comment_idstring · felt_idOptionalExample: luCHyMruTQ6ozGk3gPJfEB
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/comments/{comment_id}/resolve
    POST /api/v2/maps/{map_id}/comments/{comment_id}/resolve HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "comment_id": "luCHyMruTQ6ozGk3gPJfEB"
    }

    Delete map comment

    delete

    Permanently delete a comment or reply from the map.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map that contains the comment.

    comment_idstringRequired

    The ID of the comment to delete.

    Responses
    204

    No Content

    No content

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    delete/api/v2/maps/{map_id}/comments/{comment_id}
    DELETE /api/v2/maps/{map_id}/comments/{comment_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    

    No content

    post

    Make a layer available in the workspace library for reuse by team members.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map where the layer is located

    layer_idstringRequired

    The ID of the layer to publish

    Body
    feltServerIdstring · uuidOptional

    The Felt Server to publish into. Defaults to the workspace's default Felt Server.

    Example: 8f9a2b1c-3d4e-5f60-7a8b-9c0d1e2f3a4b
    namestringOptional

    The name to publish the layer under

    Example: My Layer
    Responses
    200

    Publish layer response

    application/json
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layers/{layer_id}/publish
    POST /api/v2/maps/{map_id}/layers/{layer_id}/publish HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 73
    
    {
      "feltServerId": "8f9a2b1c-3d4e-5f60-7a8b-9c0d1e2f3a4b",
      "name": "My Layer"
    }
    {
      "attributes": [
        {
          "name": "text",
          "type": "INTEGER"
        }
      ],
      "caption": "text",
      "geometry_type": "Line",
      "hide_from_legend": true,
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "is_spreadsheet": true,
      "last_refreshed_at": "2026-01-01T00:00:00.000Z",
      "legend_display": "default",
      "legend_visibility": "hide",
      "links": {
        "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
        "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",
      "next_refresh_at": "2026-01-01T00:00:00.000Z",
      "ordering_key": 1,
      "paused_reason": "consecutive_failures",
      "progress": 1,
      "refresh_period": "15 min",
      "refresh_status": "active",
      "status": "uploading",
      "style": {},
      "tile_url": "text",
      "type": "layer"
    }
    post

    Make a layer group available in the workspace library for reuse by team members.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    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
    feltServerIdstring · uuidOptional

    The Felt Server to publish into. Defaults to the workspace's default Felt Server.

    Example: 8f9a2b1c-3d4e-5f60-7a8b-9c0d1e2f3a4b
    namestringOptional

    The name to publish the layer group under

    Example: My Layer
    Responses
    200

    Publish layer group response

    application/json
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layer_groups/{layer_group_id}/publish
    POST /api/v2/maps/{map_id}/layer_groups/{layer_group_id}/publish HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 73
    
    {
      "feltServerId": "8f9a2b1c-3d4e-5f60-7a8b-9c0d1e2f3a4b",
      "name": "My Layer"
    }
    {
      "caption": "text",
      "id": "luCHyMruTQ6ozGk3gPJfEB",
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ],
      "legend_visibility": "hide",
      "links": {
        "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
      },
      "name": "text",
      "ordering_key": 1,
      "type": "layer_group",
      "visibility_interaction": "default"
    }
    get

    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 (POST /api/v2/duplicate_layers) and the layer id provided by this endpoint.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Query parameters
    sourcestring · enumOptional

    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.

    Default: workspacePossible values:
    Responses
    200

    LayerLibrary

    application/json
    captionstring · nullableRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    legend_visibilitystring · enum · nullableOptional

    Controls how the layer group is displayed in the legend. Defaults to "show".

    Possible values:
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D
    namestringRequired
    ordering_keyintegerOptional

    A sort order key used for ordering layers and layer groups in the legend

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    typestring · enumRequiredPossible values:
    visibility_interactionstring · enumRequired

    Controls how the layer group is displayed in the legend. Defaults to "default".

    Possible values:
    namestringRequired

    The name of the attribute

    typestring · enumOptional

    The type of the attribute

    Possible values:
    captionstring · nullableRequired
    geometry_typestring · enum · nullableRequiredPossible values:
    hide_from_legendbooleanRequired
    idstring · felt_idRequiredExample: luCHyMruTQ6ozGk3gPJfEB
    is_spreadsheetboolean · nullableOptional
    last_refreshed_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the layer's data was last updated. This includes scheduled refreshes, manual refreshes, and direct feature edits.

    legend_displaystring · enum · nullableOptional

    Controls how the layer is displayed in the legend.

    Possible values:
    legend_visibilitystring · enum · nullableOptional

    Controls whether or not the layer is displayed in the legend. Defaults to "show".

    Possible values:
    componentsstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components
    selfstringOptionalExample: https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA
    attribution_textstring · nullableOptional
    attribution_urlstring · nullableOptional
    descriptionstring · nullableOptional
    licensestring · nullableOptional
    source_abbreviationstring · nullableOptional
    source_namestring · nullableOptional
    source_urlstring · nullableOptional
    updated_atstring · date · nullableOptionalExample: 2025-03-24
    namestringRequired
    next_refresh_atstring · date-time · nullableOptional

    ISO 8601 timestamp of when the next scheduled refresh will occur. Null if refresh is disabled or paused.

    ordering_keyinteger · nullableOptional

    A sort order key used for ordering layers and layer groups in the legend

    paused_reasonstring · enum · nullableOptional

    Why the layer's refresh is paused. Null when not paused.

    Possible values:
    progressnumber · floatRequired
    refresh_periodstring · enumRequiredPossible values:
    refresh_statusstring · enumRequired

    Whether scheduled refresh is active, paused (due to failures), or disabled

    Possible values:
    statusstring · enumRequiredPossible values:
    styleobjectRequired

    The Felt Style Language style for the layer

    subtitlestring · nullableOptionalDeprecated

    Deprecated: use caption instead.

    tile_urlstring · nullableOptional

    The tile URL for this layer

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/library
    GET /api/v2/library HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "layer_groups": [
        {
          "caption": "text",
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "layers": [
            {
              "attributes": [
                {
                  "name": "text",
                  "type": "INTEGER"
                }
              ],
              "caption": "text",
              "geometry_type": "Line",
              "hide_from_legend": true,
              "id": "luCHyMruTQ6ozGk3gPJfEB",
              "is_spreadsheet": true,
              "last_refreshed_at": "2026-01-01T00:00:00.000Z",
              "legend_display": "default",
              "legend_visibility": "hide",
              "links": {
                "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
                "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",
              "next_refresh_at": "2026-01-01T00:00:00.000Z",
              "ordering_key": 1,
              "paused_reason": "consecutive_failures",
              "progress": 1,
              "refresh_period": "15 min",
              "refresh_status": "active",
              "status": "uploading",
              "style": {},
              "tile_url": "text",
              "type": "layer"
            }
          ],
          "legend_visibility": "hide",
          "links": {
            "self": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layer_groups/v13k4Ae9BRjCHHdPP5Fcm6D"
          },
          "name": "text",
          "ordering_key": 1,
          "type": "layer_group",
          "visibility_interaction": "default"
        }
      ],
      "layers": [
        {
          "attributes": [
            {
              "name": "text",
              "type": "INTEGER"
            }
          ],
          "caption": "text",
          "geometry_type": "Line",
          "hide_from_legend": true,
          "id": "luCHyMruTQ6ozGk3gPJfEB",
          "is_spreadsheet": true,
          "last_refreshed_at": "2026-01-01T00:00:00.000Z",
          "legend_display": "default",
          "legend_visibility": "hide",
          "links": {
            "components": "https://felt.com/api/v2/maps/V0dnOMOuTd9B9BOsL9C0UjmqC/layers/k441enUxQUOnZqc1ZvNsDA/components",
            "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",
          "next_refresh_at": "2026-01-01T00:00:00.000Z",
          "ordering_key": 1,
          "paused_reason": "consecutive_failures",
          "progress": 1,
          "refresh_period": "15 min",
          "refresh_status": "active",
          "status": "uploading",
          "style": {},
          "tile_url": "text",
          "type": "layer"
        }
      ],
      "type": "layer_library"
    }
    An array of URLs to import on map creation

    Move map

    Duplicate map

    Create map

    Update map

    This action cannot be undone. The map and all its layers, elements, and comments will be permanently removed.

    Export map as image

    Update map layer group

    Delete map layer group

    This action cannot be undone. The layer group and all its contained layers will be permanently removed from the map.

    List map layers

    Update map layer

    List map layer groups

    Update map layer groups

    Update layer style

    This action cannot be undone. The layer and all its data will be permanently removed from the map.

    Duplicate map layers

    This action cannot be undone. The element will be permanently removed from the map.

    Create or update map elements

    The maximum payload size for any POST to the Felt API is 1MB. Additionally, complex element geometry may be automatically simplified. If you require large, complex geometries, consider uploading your data as a Data Layer.

    List map element groups

    Create or update map element groups

    The maximum payload size for any POST to the Felt API is 1MB. Additionally, complex element geometry may be automatically simplified. If you require large, complex geometries, consider uploading your data as a Data Layer.

    List projects

    Create project

    Caution: Deleting a project deletes all of the folders and maps inside!

    Update project

    Create layer export link

    Check custom export status

    Create custom layer export

    Update source

    Create source

    Sync source

    Get source

    Any layers created from the Source will remain after it is deleted, but they will no longer be refreshed.

    Create source credential

    Update source credential

    This action cannot be undone. The comment or reply will be permanently removed from the map.

    Publish map layer

    Publish map layer group

    List library layers

    Uploading the file to Amazon S3

    Layer files aren't uploaded directly to the Felt API. Instead, they are uploaded to an S3 bucket.

    The response to this API request will include a URL and pre-signed params for you to use to upload your 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, you must perform a multipart upload, and include the file contents in the file field.

    Add layer from data source

    Refresh map layer

    With the felt_python library, you can refresh a layer with a simple function call:

    Upload map layer

    Upload Anything
    from felt_python import (refresh_file_layer, refresh_url_layer)
    
    refresh_file_layer(map_id, layer_id, file_name="features.geojson")
    refresh_url_layer(map_id, layer_id)

    With the felt_python library, you can upload a file with a simple function call:

    from felt_python import upload_file
    
    upload_file(
    Include the token as a query parameter on the Embed URL in an iframe

    Enabling Layer Export

    You can allow EmbedToken based page views to export layer data.

    • Turn on "Viewer permissions: Export data" in Map settings

    Create an Embed Token

    Usage

    <iframe src="https://felt.com/embed/map/{mapId}?token={token}"></iframe
    map_id
    ,
    file_name
    =
    "
    features.geojson
    "
    ,
    layer_name
    =
    "
    My new layer
    "
    )
    >

    Map interactions and viewport

    The Felt SDK provides methods to control the map's viewport (the visible area of the map) and handle user interactions like clicking and hovering on the viewport.

    Working with the viewport

    Getting viewport state

    You can get the current viewport state using getViewport():

    const viewport = await felt.getViewport();
    console.log(viewport.center); // { latitude: number, longitude: number }
    console.log(viewport.zoom);   // number

    Setting the viewport

    There are two main ways to set the viewport: moving to a specific point, or fitting to bounds.

    Moving to a point

    Use setViewport() to move the map to a specific location:

    felt.setViewport({
      center: {
        latitude: 37.7749,
        longitude: -122.4194
      },
      zoom: 12
    });

    Fitting to bounds

    Use fitViewportToBounds() to adjust the viewport to show a specific rectangular area:

    felt.fitViewportToBounds({
      bounds: [
        west,   // minimum longitude
        south,  // minimum latitude
        east,   // maximum longitude
        north   // maximum latitude
      ]
    });

    Responding to viewport changes

    To stay in sync with viewport changes, use the onViewportMove method:

    const unsubscribe = felt.onViewportMove({
      handler: (viewport) => {
        console.log("New center:", viewport.center);
        console.log("New zoom:", viewport.zoom);
      }
    });
    
    // Clean up when done
    unsubscribe();

    Map interactions

    Click events

    Listen for click events on the map using onPointerClick:

    Track mouse movement over the map using onPointerMove:

    1. Cleanup: Always store and call unsubscribe functions when you're done listening for events:

    1. Throttling: For pointer move events, consider throttling your handler if you're doing expensive operations:

    By using these viewport controls and interaction handlers, you can create rich, interactive experiences with your Felt map.

    Hover events

    Best practices

    const unsubscribe = felt.onPointerClick({
      handler: (event) => {
        // Location of the click
        console.log("Click location:", event.coordinate);
        
        // Features under the click
        console.log("Clicked features:", event.features);
        
        // The pixel coordinates of the cursor, measured from the top left corner of the map DOM element.
        console.log("Screen coordinates:", event.point);
        
        // Values from raster layers under the pointer.
        // Always an array - empty when no raster layers are hit.
        for (const {value, categoryName, color, layerId} of event.rasterValues) {
          console.log("Raster value:", value, categoryName);
        }
      }
    });
    const unsubscribe = felt.onPointerMove({
      handler: (event) => {
        // Current mouse location
        console.log("Mouse location:", event.coordinate);
        
        // Features under the cursor
        console.log("Hovered features:", event.features);
        
        // The pixel coordinates of the cursor, measured from the top left corner of the map DOM element.
        console.log("Screen coordinates:", event.point);
    
        // Values from raster layers under the pointer.
        // Always an array - empty when no raster layers are hit.
        for (const {value, categoryName, color, layerId} of event.rasterValues) {
          console.log("Raster value:", value, categoryName);
        }
      }
    });
    const unsubscribe = felt.onPointerMove({
      handler: (event) => {
        // Handle event...
      }
    });
    
    // Later, when you're done:
    unsubscribe();
    import { throttle } from "lodash";
    
    felt.onPointerMove({
      handler: throttle((event) => {
        // Handle frequent mouse moves...
      }, 100) // Limit to once every 100ms
    });

    Layer Components

    APIs to build dashboards

    With these APIs, you can create and edit a layer's components.

    get

    Returns all components on a layer, ordered as they appear in the app.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map the layer belongs to.

    layer_idstringRequired

    The ID of the layer the components belong to.

    Responses
    200

    Layer components list

    application/json
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumRequired

    The type of rendered interactive component. slider only works with numeric attributes.

    Default: dropdownPossible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    Attribute to filter values from.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title. Defaults to data.filter_by.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    domainstringRequired

    The band whose pixels are charted.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumOptional

    The type of rendered interactive component. A dropdown lists the band's values, so it needs a categorical band. Defaults to the band's control: dropdown for a categorical band, slider otherwise.

    Possible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    A band id such as band:1.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title. Defaults to the band's name.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/layers/{layer_id}/components
    GET /api/v2/maps/{map_id}/layers/{layer_id}/components HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    [
      {
        "config": {
          "reactive": true,
          "viewport_mode": "global"
        },
        "data": {
          "aggregate": "count",
          "format": null
        },
        "id": "text",
        "layer_id": "text",
        "layer_type": "vector",
        "title": "text",
        "type": "statistic"
      }
    ]
    post

    Creates a component on a layer.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map the layer belongs to.

    layer_idstringRequired

    The ID of the layer the component belongs to.

    Body
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired

    How the statistic is computed.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired

    How to compute the histogram distribution.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired

    How to compute the line's distribution.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired

    How to compute the resulting categories.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired

    How to aggregate the chosen attribute into a time series.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumOptional

    The type of rendered interactive component. slider only works with numeric attributes.

    Default: dropdownPossible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    Attribute to filter values from.

    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title. Defaults to data.filter_by.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    domainstringRequired

    The band whose pixels are charted.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumOptional

    The type of rendered interactive component. A dropdown lists the band's values, so it needs a categorical band. Defaults to the band's control: dropdown for a categorical band, slider otherwise.

    Possible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    A band id such as band:1.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title. Defaults to the band's name.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    Responses
    200

    Layer component

    application/json
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumRequired

    The type of rendered interactive component. slider only works with numeric attributes.

    Default: dropdownPossible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    Attribute to filter values from.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title. Defaults to data.filter_by.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    domainstringRequired

    The band whose pixels are charted.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumOptional

    The type of rendered interactive component. A dropdown lists the band's values, so it needs a categorical band. Defaults to the band's control: dropdown for a categorical band, slider otherwise.

    Possible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    A band id such as band:1.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title. Defaults to the band's name.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layers/{layer_id}/components
    POST /api/v2/maps/{map_id}/layers/{layer_id}/components HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 215
    
    {
      "config": {
        "selection": [
          "zoning",
          "in",
          [
            "residential"
          ]
        ]
      },
      "data": {
        "aggregate": "sum",
        "aggregate_by": "area_sqm",
        "format": {
          "thousandSeparated": true
        },
        "group_by": "zoning"
      },
      "title": "Total area by zoning",
      "type": "bar_chart"
    }
    {
      "config": {
        "reactive": true,
        "viewport_mode": "global"
      },
      "data": {
        "aggregate": "count",
        "format": null
      },
      "id": "text",
      "layer_id": "text",
      "layer_type": "vector",
      "title": "text",
      "type": "statistic"
    }

    Get layer component

    get

    Returns a single layer component. Includes all fields.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map the layer belongs to.

    layer_idstringRequired

    The ID of the layer the component belongs to.

    component_idstringRequired

    The ID of the layer component.

    Responses
    200

    Layer component

    application/json
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumRequired

    The type of rendered interactive component. slider only works with numeric attributes.

    Default: dropdownPossible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    Attribute to filter values from.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title. Defaults to data.filter_by.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    domainstringRequired

    The band whose pixels are charted.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumOptional

    The type of rendered interactive component. A dropdown lists the band's values, so it needs a categorical band. Defaults to the band's control: dropdown for a categorical band, slider otherwise.

    Possible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    A band id such as band:1.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title. Defaults to the band's name.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    get/api/v2/maps/{map_id}/layers/{layer_id}/components/{component_id}
    GET /api/v2/maps/{map_id}/layers/{layer_id}/components/{component_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    
    {
      "config": {
        "reactive": true,
        "viewport_mode": "global"
      },
      "data": {
        "aggregate": "count",
        "format": null
      },
      "id": "text",
      "layer_id": "text",
      "layer_type": "vector",
      "title": "text",
      "type": "statistic"
    }
    post

    Partially update the provided fields of a component.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map the layer belongs to.

    layer_idstringRequired

    The ID of the layer the component belongs to.

    component_idstringRequired

    The ID of the layer component.

    Body
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Possible values:
    dataany ofOptional

    Change how the component computes its result. data replaces as a unit when provided. Partial updates are not supported.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block. Pass null to clear the selection.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Possible values:
    dataany ofOptional

    Change how the component computes its result. data replaces as a unit when provided. Partial updates are not supported.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block. Pass null to clear the selection.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Possible values:
    dataany ofOptional

    Change how the component computes its result. data replaces as a unit when provided. Partial updates are not supported.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block. Pass null to clear the selection.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Possible values:
    dataany ofOptional

    Change how the component computes its result. data replaces as a unit when provided. Partial updates are not supported.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block. Pass null to clear the selection.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Possible values:
    dataany ofOptional

    Change how the component computes its result. data replaces as a unit when provided. Partial updates are not supported.

    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    or
    control_typestring · enumOptional

    The type of rendered interactive component. slider only works with numeric attributes.

    Possible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block. Pass null to clear the selection.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    Attribute to filter values from.

    layer_typestring · enumOptional

    The kind of layer this component is attached to.

    Default: vectorPossible values:
    titlestringOptional

    Display title.

    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Possible values:
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block. Pass null to clear the selection.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block. Pass null to clear the selection.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Possible values:
    domainstringRequired

    The band whose pixels are charted.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    or
    reactivebooleanOptional

    Whether this component reacts to other components' selections, filtering its result to match.

    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block. Pass null to clear the selection.

    viewport_modestring · enumOptional

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Possible values:
    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    or
    control_typestring · enumOptional

    The type of rendered interactive component. A dropdown lists the band's values, so it needs a categorical band.

    Possible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block. Pass null to clear the selection.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    A band id such as band:1.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    Responses
    200

    Layer component

    application/json
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Numeric attribute to bin into the distribution.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    domainstringRequired

    Numeric attribute the line is plotted against — the horizontal axis.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Attribute whose values become the categories.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    dataany ofRequired
    aggregatestring · enumRequired

    Count features.

    Possible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    or
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    Attribute to aggregate.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    Date or datetime attribute which drives the time axis.

    intervalstring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumRequired

    The type of rendered interactive component. slider only works with numeric attributes.

    Default: dropdownPossible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    Attribute to filter values from.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title. Defaults to data.filter_by.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    aggregatestring · enumRequired

    The statistic to compute over aggregate_by.

    Possible values:
    aggregate_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    countinteger · max: 9007199254740991Required

    Number of equal-width bins across the attribute's range.

    typestring · enumRequiredPossible values:
    typestring · enumRequiredPossible values:
    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.domain. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    domainstringRequired

    The band whose pixels are charted.

    formatanyOptional

    numbrojs format object. See the numbrojs format documentation.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    reactivebooleanRequired

    Whether this component reacts to other components' selections, filtering its result to match.

    Default: true
    selectionanyOptional

    Selected values of data.group_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    viewport_modestring · enumRequired

    Compute over the whole layer (global) or only the features in the current viewport (viewport).

    Default: globalPossible values:
    group_bystringRequired

    A band id such as band:1 or the styled index band index:0.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    or
    control_typestring · enumOptional

    The type of rendered interactive component. A dropdown lists the band's values, so it needs a categorical band. Defaults to the band's control: dropdown for a categorical band, slider otherwise.

    Possible values:
    pluralitystring · enumOptional

    Whether the dropdown allows filtering on multiple values or just one.

    Possible values:
    selectionanyOptional

    Selected values of data.filter_by. The visualized map layer and other components are filtered to match. Uses the same format as the FSL filters block.

    sortingstring · enumOptional

    The rendered order of dropdown options.

    Possible values:
    filter_bystringRequired

    A band id such as band:1.

    idstringRequired

    Server-assigned component id.

    layer_idstringRequired

    The layer this component is bound to.

    layer_typestring · enumRequired

    The kind of layer this component is attached to.

    Possible values:
    titlestringOptional

    Display title. Defaults to the band's name.

    typestring · enumRequired

    The component type. Immutable after creation.

    Possible values:
    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    post/api/v2/maps/{map_id}/layers/{layer_id}/components/{component_id}
    POST /api/v2/maps/{map_id}/layers/{layer_id}/components/{component_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Content-Type: application/json
    Accept: */*
    Content-Length: 133
    
    {
      "config": {
        "reactive": true,
        "viewport_mode": "global"
      },
      "data": {
        "aggregate": "count",
        "format": null
      },
      "layer_type": "vector",
      "title": "text"
    }
    {
      "config": {
        "reactive": true,
        "viewport_mode": "global"
      },
      "data": {
        "aggregate": "count",
        "format": null
      },
      "id": "text",
      "layer_id": "text",
      "layer_type": "vector",
      "title": "text",
      "type": "statistic"
    }

    Delete layer component

    delete

    Deletes a component from the layer.

    Authorizations
    AuthorizationstringRequired
    Bearer authentication header of the form Bearer <token>.
    Path parameters
    map_idstringRequired

    The ID of the map the layer belongs to.

    layer_idstringRequired

    The ID of the layer the component belongs to.

    component_idstringRequired

    The ID of the layer component.

    Responses
    204

    No Content

    No content

    401

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    403

    UnauthorizedError

    application/json
    detailstringOptional
    headerstring · enumOptionalPossible values:
    titlestringOptional
    404

    NotFoundError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    422

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    429

    Unprocessable Entity

    application/json
    detailstringRequiredExample: null value where string expected
    pointerstringRequiredExample: /data/attributes/petName
    titlestringRequiredExample: Invalid value
    500

    InternalServerError

    application/json
    detailstringOptional
    parameterstringOptional
    titlestringOptional
    delete/api/v2/maps/{map_id}/layers/{layer_id}/components/{component_id}
    DELETE /api/v2/maps/{map_id}/layers/{layer_id}/components/{component_id} HTTP/1.1
    Host: felt.com
    Authorization: Bearer YOUR_SECRET_TOKEN
    Accept: */*
    

    No content

    List layer components

    Create layer component

    The component type is set at creation and cannot be changed later.

    Update layer component

    Omitted fields keep their current value. A component's type is immutable and is not part of the update body.

    This cannot be undone.