# Working with annotations

{% hint style="warning" %}

#### Note: Annotations were previously referred to as Elements.

References have been updated in the app and documentation, while naming in the REST API and JS SDK remains unchanged.
{% endhint %}

Annotations live at the top layer of a map, and are created directly inside the Felt app.

{% hint style="info" %}
Combining annotations with [webhooks](/rest-api/listening-to-updates-using-webhooks.md) is a great way to create interactive data apps in Felt.
{% endhint %}

## Listing all annotations on a map

Annotations live at the top layer of a map, and are created directly inside the Felt app.

Annotations are returned as a [GeoJSON Feature Collection](https://geojson.org/).

{% tabs %}
{% tab title="curl" %}

```bash
# Your API token and map ID should look like this:
# FELT_API_TOKEN="felt_pat_ABCDEFUDQPAGGNBmX40YNhkCRvvLI3f8/BCwD/g8"
# MAP_ID="CjU1CMJPTAGofjOK3ICf1D"
FELT_API_TOKEN="<YOUR_API_TOKEN>"
MAP_ID="<YOUR_MAP_ID>"

curl -L \
  -H "Authorization: Bearer ${FELT_API_TOKEN}" \
  "https://felt.com/api/v2/maps/${MAP_ID}/elements"
```

{% endtab %}

{% tab title="Python" %}

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

r = requests.get(
  f"http://felt.com/api/v2/maps/{map_id}/elements",
  headers={"Authorization": f"Bearer {api_token}"}
)
assert r.ok
print(r.json())
```

{% endtab %}

{% tab title="felt-python" %}

```python
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)
```

{% endtab %}
{% endtabs %}

## Listing all annotation groups

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

{% tabs %}
{% tab title="curl" %}

```bash
curl -L \
  -H "Authorization: Bearer ${FELT_API_TOKEN}" \
  "https://felt.com/api/v2/maps/${MAP_ID}/element_groups"
```

{% endtab %}

{% tab title="Python" %}

```python
r = requests.get(
  f"http://felt.com/api/v2/maps/{map_id}/elements",
  headers={"Authorization": f"Bearer {api_token}"}
)
assert r.ok
print(r.json())
```

{% endtab %}

{% tab title="felt-python" %}

```python
from felt_python import list_element_groups

list_element_groups(map_id)
```

{% endtab %}
{% endtabs %}

## Create or update new annotations

Each annotation is represented by a feature in the `POST`ed GeoJSON Feature Collection.

For each feature, including an existing annotation ID (`felt:id`) will result in the annotation being updated on the map. If no annotation ID is provided (or a non-existent one) , a new annotation will be created.

{% tabs %}
{% tab title="curl" %}

```bash
curl -L \
  -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"}}]}'
```

{% endtab %}

{% tab title="Python" %}

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

r = requests.post(
  f"http://felt.com/api/v2/maps/{map_id}/elements",
  headers={"Authorization": f"Bearer {api_token}"},
  json=new_elements
)
assert r.ok
print(r.json())
```

{% endtab %}

{% tab title="felt-python" %}

```python
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)
```

{% endtab %}
{% endtabs %}

## Delete an annotation

Annotations can be deleted by referencing them by ID

{% tabs %}
{% tab title="curl" %}

```bash
curl -L \
  -X DELETE \
  -H "Authorization: Bearer ${FELT_API_TOKEN}" \
  "https://felt.com/api/v2/maps/${MAP_ID}/elements/{ELEMENT_ID}"
```

{% endtab %}

{% tab title="Python" %}

```python
element_id = "<YOUR_ELEMENT_ID>"

r = requests.delete(
  f"http://felt.com/api/v2/maps/{map_id}/elements/{element_id}",
  headers={"Authorization": f"Bearer {api_token}"},
)
assert r.ok
```

{% endtab %}

{% tab title="felt-python" %}

```python
from felt_python import delete_element

element_id = "<YOUR_ELEMENT_ID>"

delete_element(map_id, element_id)
```

{% endtab %}
{% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://developers.felt.com/rest-api/working-with-annotations.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
