The Chart Annotations API lets you programmatically annotate important dates and time ranges like feature releases and marketing campaigns on your organization's charts. You can organize annotations into categories and use hourly granularity for precise timing.
This API uses basic authentication, using the API key and secret key for your project. Pass base64-encoded credentials in the request header like {api-key}:{secret-key}. api-key replaces username, and secret-key replaces the password.
Your authorization header should look something like this:
--header 'Authorization: Basic YWhhbWwsdG9uQGFwaWdlZS5jb206bClwYXNzdzByZAo'
For more information, see Find your API Credentials
| Region | Endpoint |
|---|---|
| Standard server | https://amplitude.com/api/3/annotations |
| EU residency server | https://analytics.eu.amplitude.com/api/3/annotations |
Manage annotation categories to organize your annotations. Create categories, update their names, and assign them to annotations.
curl --location --request POST 'https://amplitude.com/api/3/annotation-categories' \
--header 'Authorization: Basic {api-key}:{secret-key}' \
--header 'Content-Type: application/json' \
--data-raw '{
"category": "Releases"
}'
POST /api/3/annotation-categories HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
Content-Type: application/json
{
"category": "Releases"
}
| Parameter | Description |
|---|---|
category |
Required. String. The name of the category. |
{
"data": {
"id": 6789,
"name": "Releases"
}
}
400 - Invalid field409 - Category already exists
curl --location --request GET 'https://amplitude.com/api/3/annotation-categories' \
-u '{api-key}:{secret-key}'
GET /api/3/annotation-categories HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
| Parameter | Description |
|---|---|
category |
Optional. String. If specified, returns only the specified category. Otherwise, returns all categories. |
{
"data": [
{
"id": 12345,
"name": "Alerts"
},
{
"id": 6789,
"name": "Releases"
}
]
}
400 - Invalid category404 - Category not found
curl --location --request GET 'https://amplitude.com/api/3/annotation-categories/:category_id' \
-u '{api-key}:{secret-key}'
GET /api/3/annotation-categories/:category_id HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
| Parameter | Description |
|---|---|
category_id |
Required. Integer. The ID of the category. |
{
"data": {
"id": 12345,
"name": "Alerts"
}
}
400 - Invalid category ID404 - Category not found
curl --location --request PUT 'https://amplitude.com/api/3/annotation-categories/:category_id' \
--header 'Authorization: Basic {api-key}:{secret-key}' \
--header 'Content-Type: application/json' \
--data-raw '{
"category": "Updated Category Name"
}'
PUT /api/3/annotation-categories/:category_id HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
Content-Type: application/json
{
"category": "Updated Category Name"
}
| Parameter | Description |
|---|---|
category_id |
Required. Integer. The ID of the category to update. |
| Parameter | Description |
|---|---|
category |
Required. String. The new name of the category. |
{
"data": {
"id": 569,
"category": "Updated category name"
}
}
400 - Invalid category ID404 - Category not found409 - Category already exists
curl --location --request DELETE 'https://amplitude.com/api/3/annotation-categories/:category_id' \
-u '{api-key}:{secret-key}'
DELETE /api/3/annotation-categories/:category_id HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
| Parameter | Description |
|---|---|
category_id |
Required. Integer. The ID of the category to delete. |
{
"success": true
}
400 - Invalid category ID404 - Category not foundAssign a category to multiple annotations at once.
curl --location --request PUT 'https://amplitude.com/api/3/annotation-categories/bulk/:category_id' \
--header 'Authorization: Basic {api-key}:{secret-key}' \
--header 'Content-Type: application/json' \
--data-raw '{
"annotation_ids": [12345, 67890, 11111]
}'
PUT /api/3/annotation-categories/bulk/:category_id HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
Content-Type: application/json
{
"annotation_ids": [12345, 67890, 11111]
}
| Parameter | Description |
|---|---|
category_id |
Required. Integer. The ID of the category to assign. |
| Parameter | Description |
|---|---|
annotation_ids |
Required. Array. A list of annotation IDs to update. |
{
"data": [
{
"id": 12345,
"start": "2025-12-18T15:00:00+00:00",
"label": "test",
"details": null,
"category": {
"id": 12345,
"category": "Alerts"
},
"end": null,
"chart_id": null
},
…
]
}
400 - Invalid category ID400 - Invalid annotation IDs400 - One or more invalid annotation ID404 - Category not foundCreate, retrieve, update, and delete chart annotations. Annotations can span single dates or time ranges with hourly granularity.
curl --location --request POST 'https://amplitude.com/api/3/annotations' \
--header 'Authorization: Basic {api-key}:{secret-key}' \
--header 'Content-Type: application/json' \
--data-raw '{
"label": "Feature X Release",
"start": "2025-11-01T07:00:00+00:00",
"category": "Releases",
"chart_id": "abc123",
"details": "This marks the release of feature X",
"end": "2025-11-10T07:00:00+01:00"
}'
POST /api/3/annotations HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
Content-Type: application/json
{
"label": "Feature X Release",
"start": "2025-11-01T07:00:00+00:00",
"category": "Releases",
"chart_id": "abc123",
"details": "This marks the release of feature X",
"end": "2025-11-10T07:00:00+01:00"
}
| Parameter | Description |
|---|---|
label |
Required. String. The title of your annotation. |
start |
Required. String. Timestamp corresponding to the start of this annotation in ISO 8601 format (YYYY-MM-DDThh:mmTZD). For example: "2025-11-01T07:00:00+00:00". |
category |
Optional. String. The name of the category that the annotation belongs to. |
chart_id |
Optional. String. The ID of the chart (found in the URL) to annotate. If you don't include chart_id, the annotation is global and appears on all charts for your project. |
details |
Optional. String. Details for the annotation. |
end |
Optional. String. Timestamp corresponding to the end of this annotation in ISO 8601 format (YYYY-MM-DDThh:mmTZD). For example: "2025-11-10T07:00:00+01:00". |
{
"data": {
"id": 12345,
"start": "2025-11-01T07:00:00+00:00",
"details": "This marks the release of feature X",
"category": {
"id": 45678,
"name": "Releases"
},
"end": "2025-11-10T07:00:00+01:00",
"label": "Feature X Release",
"chart_id": null
}
}
400 - Invalid field404 - Category not foundRetrieves all chart annotations in your project. Supports filtering by category, chart, and date range.
curl --location --request GET 'https://amplitude.com/api/3/annotations?category=Releases&start=2025-11-01T07:00:00+00:00&end=2025-11-30T07:00:00+00:00' \
-u '{api-key}:{secret-key}'
GET /api/3/annotations?category=Releases&start=2025-11-01T07:00:00+00:00&end=2025-11-30T07:00:00+00:00 HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
| Parameter | Description |
|---|---|
category |
Optional. String. If specified, only returns annotations in this category. Doesn't combine with chart_id filter. |
chart_id |
Optional. String. If specified, only returns annotations that show on this chart. Doesn't combine with category filter. |
start |
Optional. String. If specified, only returns annotations that occur after start in ISO 8601 format (YYYY-MM-DDThh:mmTZD). For example: "2025-11-10T07:00:00+01:00". |
end |
Optional. String. If specified, only returns annotations that occur before end in ISO 8601 format (YYYY-MM-DDThh:mmTZD). If the annotation spans a date range, the annotation's end date must be before end input. For example: "2025-11-10T07:00:00+01:00". |
{
"data": [
{
"id": 12345,
"start": "2025-11-01T07:00:00+00:00",
"details": "This marks the release of feature X",
"category": {
"id": 45678,
"name": "Releases"
},
"end": "2025-11-10T07:00:00+01:00",
"label": "Feature X Release",
"chart_id": null
}
]
}
400 - Invalid request409 - ConflictRetrieves a single chart annotation by ID.
curl --location --request GET 'https://amplitude.com/api/3/annotations/:annotation_id' \
-u '{api-key}:{secret-key}'
GET /api/3/annotations/:annotation_id HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
| Parameter | Description |
|---|---|
annotation_id |
Required. Integer. The ID of the annotation to retrieve. |
{
"data": {
"id": 12345,
"start": "2025-11-01T07:00:00+00:00",
"details": "This marks the release of feature X",
"category": {
"id": 45678,
"name": "Releases"
},
"end": "2025-11-10T07:00:00+01:00",
"label": "Feature X Release",
"chart_id": null
}
}
400 - Invalid annotation ID404 - Annotation not foundUpdates a specific annotation. Supports partial updates—only the fields you specify in the request body are updated.
curl --location --request PUT 'https://amplitude.com/api/3/annotations/:annotation_id' \
--header 'Authorization: Basic {api-key}:{secret-key}' \
--header 'Content-Type: application/json' \
--data-raw '{
"label": "Updated Feature X Release",
"end": "2025-11-15T07:00:00+01:00"
}'
PUT /api/3/annotations/:annotation_id HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
Content-Type: application/json
{
"label": "Updated Feature X Release",
"end": "2025-11-15T07:00:00+01:00"
}
| Parameter | Description |
|---|---|
annotation_id |
Required. Integer. The ID of the annotation to update. |
| Parameter | Description |
|---|---|
label |
Optional. String. The title of your annotation. |
start |
Optional. String. Timestamp corresponding to the start of this annotation in ISO 8601 format (YYYY-MM-DDThh:mmTZD). For example: "2025-11-01T07:00:00+00:00". |
category |
Optional. String. The name of the category that the annotation belongs to. |
chart_id |
Optional. String. The ID of the chart (found in the URL) to annotate. If you don't include chart_id, the annotation is global and appears on all charts for your project. Set to null to remove the association to a specific chart and make the annotation visible globally. |
details |
Optional. String. Details for the annotation. |
end |
Optional. String. Timestamp corresponding to the end of this annotation in ISO 8601 format (YYYY-MM-DDThh:mmTZD). For example: "2025-11-10T07:00:00+01:00". Set to null to remove the end time. |
{
"data": {
"id": 12345,
"start": "2025-11-01T07:00:00+00:00",
"details": "This marks the release of feature X",
"category": {
"id": 45678,
"name": "Releases"
},
"end": "2025-11-15T07:00:00+01:00",
"label": "Updated Feature X Release",
"chart_id": null
}
}
400 - Invalid field404 - Annotation not found404 - Category not found
curl --location --request DELETE 'https://amplitude.com/api/3/annotations/:annotation_id' \
-u '{api-key}:{secret-key}'
DELETE /api/3/annotations/:annotation_id HTTP/1.1
Host: amplitude.com
Authorization: Basic {api-key}:{secret-key} #credentials must be base64 encoded
| Parameter | Description |
|---|---|
annotation_id |
Required. Integer. The ID of the annotation to delete. |
{
"success": true
}
400 - Invalid annotation ID404 - Annotation not foundMay 21st, 2024
Need help? Contact Support
Visit Amplitude.com
Have a look at the Amplitude Blog
Learn more at Amplitude Academy
© 2025 Amplitude, Inc. All rights reserved. Amplitude is a registered trademark of Amplitude, Inc.