curl --request POST \
--url https://data.otterly.ai/v1/reports/brand/{reportId}/annotations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"date": "2025-04-10",
"text": "Launched spring running campaign"
}
'import requests
url = "https://data.otterly.ai/v1/reports/brand/{reportId}/annotations"
payload = {
"date": "2025-04-10",
"text": "Launched spring running campaign"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({date: '2025-04-10', text: 'Launched spring running campaign'})
};
fetch('https://data.otterly.ai/v1/reports/brand/{reportId}/annotations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://data.otterly.ai/v1/reports/brand/{reportId}/annotations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'date' => '2025-04-10',
'text' => 'Launched spring running campaign'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://data.otterly.ai/v1/reports/brand/{reportId}/annotations"
payload := strings.NewReader("{\n \"date\": \"2025-04-10\",\n \"text\": \"Launched spring running campaign\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://data.otterly.ai/v1/reports/brand/{reportId}/annotations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"date\": \"2025-04-10\",\n \"text\": \"Launched spring running campaign\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://data.otterly.ai/v1/reports/brand/{reportId}/annotations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"date\": \"2025-04-10\",\n \"text\": \"Launched spring running campaign\"\n}"
response = http.request(request)
puts response.read_body{
"id": "01HXAN7K2YV9D3M8N0G6Q5R4S3",
"brandReportId": "01HXBR1DGM5XY8Z2N3KQ7VAW4P",
"date": "2025-04-10",
"type": "note",
"text": "Launched spring running campaign",
"createdBy": "4f7a1c2e9b8d4e6f",
"createdDate": "2025-04-10T09:15:00.000Z",
"updatedDate": "2025-04-10T09:15:00.000Z"
}{
"message": "Validation failed",
"target": "query",
"errors": [
{
"path": "country",
"message": "Required",
"code": "invalid_type"
}
]
}{
"message": "Report not found"
}{
"message": "Report not found"
}{
"message": "Report not found"
}{
"message": "Report not found"
}Add a note to a brand report
Adds a note on a day of the brand report, authored by the API key user. Only notes can be created: recommendation markers are added from the recommendations page in the app, and a type other than note or a recommendationId is a 400. Annotations may not show in the dashboard until annotations are enabled there for your account; they are stored and returned by the API either way.
curl --request POST \
--url https://data.otterly.ai/v1/reports/brand/{reportId}/annotations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"date": "2025-04-10",
"text": "Launched spring running campaign"
}
'import requests
url = "https://data.otterly.ai/v1/reports/brand/{reportId}/annotations"
payload = {
"date": "2025-04-10",
"text": "Launched spring running campaign"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({date: '2025-04-10', text: 'Launched spring running campaign'})
};
fetch('https://data.otterly.ai/v1/reports/brand/{reportId}/annotations', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://data.otterly.ai/v1/reports/brand/{reportId}/annotations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'date' => '2025-04-10',
'text' => 'Launched spring running campaign'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://data.otterly.ai/v1/reports/brand/{reportId}/annotations"
payload := strings.NewReader("{\n \"date\": \"2025-04-10\",\n \"text\": \"Launched spring running campaign\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://data.otterly.ai/v1/reports/brand/{reportId}/annotations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"date\": \"2025-04-10\",\n \"text\": \"Launched spring running campaign\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://data.otterly.ai/v1/reports/brand/{reportId}/annotations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"date\": \"2025-04-10\",\n \"text\": \"Launched spring running campaign\"\n}"
response = http.request(request)
puts response.read_body{
"id": "01HXAN7K2YV9D3M8N0G6Q5R4S3",
"brandReportId": "01HXBR1DGM5XY8Z2N3KQ7VAW4P",
"date": "2025-04-10",
"type": "note",
"text": "Launched spring running campaign",
"createdBy": "4f7a1c2e9b8d4e6f",
"createdDate": "2025-04-10T09:15:00.000Z",
"updatedDate": "2025-04-10T09:15:00.000Z"
}{
"message": "Validation failed",
"target": "query",
"errors": [
{
"path": "country",
"message": "Required",
"code": "invalid_type"
}
]
}{
"message": "Report not found"
}{
"message": "Report not found"
}{
"message": "Report not found"
}{
"message": "Report not found"
}Authorizations
Provide your API key as a Bearer token: Authorization: Bearer YOUR_API_KEY.
Path Parameters
Brand report identifier.
1"01HX7K2YV9D3M8N0G6Q5R4S3T2"
Body
Response
The created note.
Annotation identifier.
1"01HX7K2YV9D3M8N0G6Q5R4S3T2"
Brand report the annotation belongs to.
1"01HX7K2YV9D3M8N0G6Q5R4S3T2"
Marked calendar day, YYYY-MM-DD.
note for a free-text note; recommendation for a recommendation marked as done in the app. Only notes can be created or edited through the API.
note, recommendation Annotation text.
Opaque identifier of the user who created the annotation.
Creation timestamp (ISO 8601).
Last update timestamp (ISO 8601).
Recommendation the annotation marks. Present only when type is recommendation.