# Call Annotation Resource

> \[!WARNING]
>
> Currently the Call Annotation API is only available for the United States (US1) Region. Find more information on the [Twilio Regional Product and Feature Availability page](/docs/global-infrastructure/regional-product-and-feature-availability).

A **Call Annotation** captures subjective experience details for a voice call.

For instance, a Call Annotation can contain information about

* call quality issues,
* spam labeling,
* customer-internal tags, and
* other meta data.

Using the **Call Annotation Resource**, you can

* [get the Call Annotation](#get-the-call-annotation-for-a-specific-call), or
* [update the Call Annotation](#update-the-call-annotation-for-a-specific-call)

for a specific call.

To get a list of Call Summaries with specific Call Annotations, you can use the [Call Summaries Resource](/docs/voice/voice-insights/api/call/call-summaries-resource).

## Annotation Properties

```json
{"type":"object","refName":"insights.v1.call.annotation","modelName":"insights_v1_call_annotation","properties":{"call_sid":{"type":"string","minLength":34,"maxLength":34,"pattern":"^CA[0-9a-fA-F]{32}$","nullable":true,"description":"The unique SID identifier of the Call."},"account_sid":{"type":"string","minLength":34,"maxLength":34,"pattern":"^AC[0-9a-fA-F]{32}$","nullable":true,"description":"The unique SID identifier of the Account."},"answered_by":{"type":"string","nullable":true,"description":"Specifies which entity answered the call as determined by Answering Machine Detection. Possible enumerated values, one of: `human`, `machine`. `human` indicates the call was answered by a person. `machine` indicates the call was answered by an answering machine.","enum":["unknown_answered_by","human","machine"],"refName":"annotation_enum_answered_by","modelName":"annotation_enum_answered_by"},"connectivity_issue":{"type":"string","nullable":true,"description":"Specifies if the call had any connectivity issues. One of `no_connectivity_issue`, `invalid_number`, `caller_id`, `dropped_call`, or `number_reachability`.","enum":["unknown_connectivity_issue","no_connectivity_issue","invalid_number","caller_id","dropped_call","number_reachability"],"refName":"annotation_enum_connectivity_issue","modelName":"annotation_enum_connectivity_issue"},"quality_issues":{"type":"array","nullable":true,"description":"Specifies if the call had any subjective quality issues. Possible values are one or more of `no_quality_issue`, `low_volume`, `choppy_robotic`, `echo`, `dtmf`, `latency`, `owa`, or `static_noise`.","items":{"type":"string"}},"spam":{"type":"boolean","nullable":true,"description":"Specifies if the call was a spam call. Use this to provide feedback on whether calls placed from your account were marked as spam, or if inbound calls received by your account were unwanted spam. Is of type Boolean: true, false. Use true if the call was a spam call."},"call_score":{"type":"integer","nullable":true,"description":"Specifies the Call Score, if available. This is of type integer. Use a range of 1-5 to indicate the call experience score, with the following mapping as a reference for rating the call [5: Excellent, 4: Good, 3 : Fair, 2 : Poor, 1: Bad]."},"comment":{"type":"string","nullable":true,"description":"Specifies any comments pertaining to the call. Twilio does not treat this field as PII, so no PII should be included in comments."},"incident":{"type":"string","nullable":true,"description":"Incident or support ticket associated with this call. The `incident` property is of type string with a maximum character limit of 100. Twilio does not treat this field as PII, so no PII should be included in `incident`."},"url":{"type":"string","format":"uri","nullable":true}}}
```

## Get the Call Annotation for a specific Call

`GET https://insights.twilio.com/v1/Voice/{CallSid}/Annotation`

### Path parameters

```json
[{"name":"CallSid","in":"path","description":"The unique SID identifier of the Call.","schema":{"type":"string","minLength":34,"maxLength":34,"pattern":"^CA[0-9a-fA-F]{32}$"},"required":true}]
```

Get a Call Annotation

```js
// Download the helper library from https://www.twilio.com/docs/node/install
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";

// Find your Account SID and Auth Token at twilio.com/console
// and set the environment variables. See http://twil.io/secure
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const client = twilio(accountSid, authToken);

async function fetchAnnotation() {
  const annotation = await client.insights.v1
    .calls("CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
    .annotation()
    .fetch();

  console.log(annotation.callSid);
}

fetchAnnotation();
```

```python
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client

# Find your Account SID and Auth Token at twilio.com/console
# and set the environment variables. See http://twil.io/secure
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
auth_token = os.environ["TWILIO_AUTH_TOKEN"]
client = Client(account_sid, auth_token)

annotation = (
    client.insights.v1.calls("CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
    .annotation()
    .fetch()
)

print(annotation.call_sid)
```

```csharp
// Install the C# / .NET helper library from twilio.com/docs/csharp/install

using System;
using Twilio;
using Twilio.Rest.Insights.V1.Call;
using System.Threading.Tasks;

class Program {
    public static async Task Main(string[] args) {
        // Find your Account SID and Auth Token at twilio.com/console
        // and set the environment variables. See http://twil.io/secure
        string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID");
        string authToken = Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN");

        TwilioClient.Init(accountSid, authToken);

        var annotation =
            await AnnotationResource.FetchAsync(pathCallSid: "CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");

        Console.WriteLine(annotation.CallSid);
    }
}
```

```java
// Install the Java helper library from twilio.com/docs/java/install

import com.twilio.Twilio;
import com.twilio.rest.insights.v1.call.Annotation;

public class Example {
    // Find your Account SID and Auth Token at twilio.com/console
    // and set the environment variables. See http://twil.io/secure
    public static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID");
    public static final String AUTH_TOKEN = System.getenv("TWILIO_AUTH_TOKEN");

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
        Annotation annotation = Annotation.fetcher("CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX").fetch();

        System.out.println(annotation.getCallSid());
    }
}
```

```go
// Download the helper library from https://www.twilio.com/docs/go/install
package main

import (
	"fmt"
	"github.com/twilio/twilio-go"
	"os"
)

func main() {
	// Find your Account SID and Auth Token at twilio.com/console
	// and set the environment variables. See http://twil.io/secure
	// Make sure TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN exists in your environment
	client := twilio.NewRestClient()

	resp, err := client.InsightsV1.FetchAnnotation("CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	} else {
		if resp.CallSid != nil {
			fmt.Println(*resp.CallSid)
		} else {
			fmt.Println(resp.CallSid)
		}
	}
}
```

```php
<?php

// Update the path below to your autoload.php,
// see https://getcomposer.org/doc/01-basic-usage.md
require_once "/path/to/vendor/autoload.php";

use Twilio\Rest\Client;

// Find your Account SID and Auth Token at twilio.com/console
// and set the environment variables. See http://twil.io/secure
$sid = getenv("TWILIO_ACCOUNT_SID");
$token = getenv("TWILIO_AUTH_TOKEN");
$twilio = new Client($sid, $token);

$annotation = $twilio->insights->v1
    ->calls("CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
    ->annotation()
    ->fetch();

print $annotation->callSid;
```

```ruby
# Download the helper library from https://www.twilio.com/docs/ruby/install
require 'twilio-ruby'

# Find your Account SID and Auth Token at twilio.com/console
# and set the environment variables. See http://twil.io/secure
account_sid = ENV['TWILIO_ACCOUNT_SID']
auth_token = ENV['TWILIO_AUTH_TOKEN']
@client = Twilio::REST::Client.new(account_sid, auth_token)

annotation = @client
             .insights
             .v1
             .calls('CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX')
             .annotation
             .fetch

puts annotation.call_sid
```

```bash
# Install the twilio-cli from https://twil.io/cli

twilio api:insights:v1:voice:annotation:fetch \
   --call-sid CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
```

```bash
curl -X GET "https://insights.twilio.com/v1/Voice/CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX/Annotation" \
-u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN
```

```json
{
  "account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "call_sid": "CAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  "answered_by": "human",
  "connectivity_issue": "invalid_number",
  "quality_issues": [
    "low_volume"
  ],
  "spam": true,
  "call_score": 2,
  "comment": "this is a call",
  "incident": "https://twilio.zendesk.com/support/tickets/17353089",
  "url": "https://insights.twilio.com/v1/Voice/CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Annotation"
}
```

## Update the Call Annotation for a specific Call

`POST https://insights.twilio.com/v1/Voice/{CallSid}/Annotation`

> \[!NOTE]
>
> Call Annotations can be updated as long as the Call Summary record is addressable via the API.

### Path parameters

```json
[{"name":"CallSid","in":"path","description":"The unique string that Twilio created to identify this Call resource. It always starts with a CA.","schema":{"type":"string","minLength":34,"maxLength":34,"pattern":"^CA[0-9a-fA-F]{32}$"},"required":true}]
```

### Request body parameters

```json
{"schema":{"type":"object","title":"UpdateAnnotationRequest","properties":{"AnsweredBy":{"type":"string","description":"Specify which entity answered the call as determined by Answering Machine Detection. Use this to provide feedback on Answering Machine Detection accuracy. Possible enumerated values, one of: `human`, `machine`. `human` indicates the call was answered by a person. `machine` indicates the call was answered by an answering machine.","enum":["unknown_answered_by","human","machine"],"refName":"annotation_enum_answered_by","modelName":"annotation_enum_answered_by"},"ConnectivityIssue":{"type":"string","description":"Specify if the call had any connectivity issues. Possible enumerated values, one of `no_connectivity_issue`, `invalid_number`, `caller_id`, `dropped_call`, or `number_reachability`.","enum":["unknown_connectivity_issue","no_connectivity_issue","invalid_number","caller_id","dropped_call","number_reachability"],"refName":"annotation_enum_connectivity_issue","modelName":"annotation_enum_connectivity_issue"},"QualityIssues":{"type":"string","description":"Specify if the call had any subjective quality issues. Possible values, one or more of `no_quality_issue`, `low_volume`, `choppy_robotic`, `echo`, `dtmf`, `latency`, `owa`, `static_noise`. Use comma separated values to indicate multiple quality issues for the same call."},"Spam":{"type":"boolean","description":"A boolean flag to indicate if the call was a spam call. Use this to provide feedback on whether calls placed from your account were marked as spam, or if inbound calls received by your account were unwanted spam. Use `true` if the call was a spam call."},"CallScore":{"type":"integer","nullable":true,"description":"Specify the call score. This is of type integer. Use a range of 1-5 to indicate the call experience score, with the following mapping as a reference for rating the call [5: Excellent, 4: Good, 3 : Fair, 2 : Poor, 1: Bad]."},"Comment":{"type":"string","description":"Specify any comments pertaining to the call. `comment` has a maximum character limit of 100. Twilio does not treat this field as PII, so no PII should be included in the `comment`."},"Incident":{"type":"string","description":"Associate this call with an incident or support ticket. The `incident` parameter is of type string with a maximum character limit of 100. Twilio does not treat this field as PII, so no PII should be included in `incident`."}}},"examples":{"update":{"value":{"lang":"json","value":"{\n  \"AnsweredBy\": \"human\",\n  \"ConnectivityIssue\": \"invalid_number\",\n  \"QualityIssues\": \"low_volume,choppy_robotic\",\n  \"Spam\": true,\n  \"CallScore\": 2,\n  \"Comment\": \"this is a call\",\n  \"Incident\": \"https://twilio.zendesk.com/support/tickets/17353089\"\n}","meta":"","code":"{\n  \"AnsweredBy\": \"human\",\n  \"ConnectivityIssue\": \"invalid_number\",\n  \"QualityIssues\": \"low_volume,choppy_robotic\",\n  \"Spam\": true,\n  \"CallScore\": 2,\n  \"Comment\": \"this is a call\",\n  \"Incident\": \"https://twilio.zendesk.com/support/tickets/17353089\"\n}","tokens":[["{","#C9D1D9"],"\n  ",["\"AnsweredBy\"","#7EE787"],[":","#C9D1D9"]," ",["\"human\"","#A5D6FF"],[",","#C9D1D9"],"\n  ",["\"ConnectivityIssue\"","#7EE787"],[":","#C9D1D9"]," ",["\"invalid_number\"","#A5D6FF"],[",","#C9D1D9"],"\n  ",["\"QualityIssues\"","#7EE787"],[":","#C9D1D9"]," ",["\"low_volume,choppy_robotic\"","#A5D6FF"],[",","#C9D1D9"],"\n  ",["\"Spam\"","#7EE787"],[":","#C9D1D9"]," ",["true","#79C0FF"],[",","#C9D1D9"],"\n  ",["\"CallScore\"","#7EE787"],[":","#C9D1D9"]," ",["2","#79C0FF"],[",","#C9D1D9"],"\n  ",["\"Comment\"","#7EE787"],[":","#C9D1D9"]," ",["\"this is a call\"","#A5D6FF"],[",","#C9D1D9"],"\n  ",["\"Incident\"","#7EE787"],[":","#C9D1D9"]," ",["\"https://twilio.zendesk.com/support/tickets/17353089\"","#A5D6FF"],"\n",["}","#C9D1D9"]],"annotations":[],"themeName":"github-dark","style":{"color":"#c9d1d9","background":"#0d1117"}}}},"encodingType":"application/x-www-form-urlencoded","conditionalParameterMap":{}}
```

Update a Comment

```js
// Download the helper library from https://www.twilio.com/docs/node/install
const twilio = require("twilio"); // Or, for ESM: import twilio from "twilio";

// Find your Account SID and Auth Token at twilio.com/console
// and set the environment variables. See http://twil.io/secure
const accountSid = process.env.TWILIO_ACCOUNT_SID;
const authToken = process.env.TWILIO_AUTH_TOKEN;
const client = twilio(accountSid, authToken);

async function updateAnnotation() {
  const annotation = await client.insights.v1
    .calls("CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
    .annotation()
    .update({ answeredBy: "human" });

  console.log(annotation.callSid);
}

updateAnnotation();
```

```python
# Download the helper library from https://www.twilio.com/docs/python/install
import os
from twilio.rest import Client

# Find your Account SID and Auth Token at twilio.com/console
# and set the environment variables. See http://twil.io/secure
account_sid = os.environ["TWILIO_ACCOUNT_SID"]
auth_token = os.environ["TWILIO_AUTH_TOKEN"]
client = Client(account_sid, auth_token)

annotation = (
    client.insights.v1.calls("CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
    .annotation()
    .update(answered_by="human")
)

print(annotation.call_sid)
```

```csharp
// Install the C# / .NET helper library from twilio.com/docs/csharp/install

using System;
using Twilio;
using Twilio.Rest.Insights.V1.Call;
using System.Threading.Tasks;

class Program {
    public static async Task Main(string[] args) {
        // Find your Account SID and Auth Token at twilio.com/console
        // and set the environment variables. See http://twil.io/secure
        string accountSid = Environment.GetEnvironmentVariable("TWILIO_ACCOUNT_SID");
        string authToken = Environment.GetEnvironmentVariable("TWILIO_AUTH_TOKEN");

        TwilioClient.Init(accountSid, authToken);

        var annotation = await AnnotationResource.UpdateAsync(
            answeredBy: AnnotationResource.AnsweredByEnum.Human,
            pathCallSid: "CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");

        Console.WriteLine(annotation.CallSid);
    }
}
```

```java
// Install the Java helper library from twilio.com/docs/java/install

import com.twilio.Twilio;
import com.twilio.rest.insights.v1.call.Annotation;

public class Example {
    // Find your Account SID and Auth Token at twilio.com/console
    // and set the environment variables. See http://twil.io/secure
    public static final String ACCOUNT_SID = System.getenv("TWILIO_ACCOUNT_SID");
    public static final String AUTH_TOKEN = System.getenv("TWILIO_AUTH_TOKEN");

    public static void main(String[] args) {
        Twilio.init(ACCOUNT_SID, AUTH_TOKEN);
        Annotation annotation = Annotation.updater("CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
                                    .setAnsweredBy(Annotation.AnsweredBy.HUMAN)
                                    .update();

        System.out.println(annotation.getCallSid());
    }
}
```

```go
// Download the helper library from https://www.twilio.com/docs/go/install
package main

import (
	"fmt"
	"github.com/twilio/twilio-go"
	insights "github.com/twilio/twilio-go/rest/insights/v1"
	"os"
)

func main() {
	// Find your Account SID and Auth Token at twilio.com/console
	// and set the environment variables. See http://twil.io/secure
	// Make sure TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN exists in your environment
	client := twilio.NewRestClient()

	params := &insights.UpdateAnnotationParams{}
	params.SetAnsweredBy("human")

	resp, err := client.InsightsV1.UpdateAnnotation("CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
		params)
	if err != nil {
		fmt.Println(err.Error())
		os.Exit(1)
	} else {
		if resp.CallSid != nil {
			fmt.Println(*resp.CallSid)
		} else {
			fmt.Println(resp.CallSid)
		}
	}
}
```

```php
<?php

// Update the path below to your autoload.php,
// see https://getcomposer.org/doc/01-basic-usage.md
require_once "/path/to/vendor/autoload.php";

use Twilio\Rest\Client;

// Find your Account SID and Auth Token at twilio.com/console
// and set the environment variables. See http://twil.io/secure
$sid = getenv("TWILIO_ACCOUNT_SID");
$token = getenv("TWILIO_AUTH_TOKEN");
$twilio = new Client($sid, $token);

$annotation = $twilio->insights->v1
    ->calls("CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")
    ->annotation()
    ->update(["answeredBy" => "human"]);

print $annotation->callSid;
```

```ruby
# Download the helper library from https://www.twilio.com/docs/ruby/install
require 'twilio-ruby'

# Find your Account SID and Auth Token at twilio.com/console
# and set the environment variables. See http://twil.io/secure
account_sid = ENV['TWILIO_ACCOUNT_SID']
auth_token = ENV['TWILIO_AUTH_TOKEN']
@client = Twilio::REST::Client.new(account_sid, auth_token)

annotation = @client
             .insights
             .v1
             .calls('CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
             .annotation
             .update(answered_by: 'human')

puts annotation.call_sid
```

```bash
# Install the twilio-cli from https://twil.io/cli

twilio api:insights:v1:voice:annotation:update \
   --call-sid CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
   --answered-by human
```

```bash
curl -X POST "https://insights.twilio.com/v1/Voice/CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Annotation" \
--data-urlencode "AnsweredBy=human" \
-u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN
```

```json
{
  "account_sid": "ACaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "call_sid": "CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "answered_by": "human",
  "connectivity_issue": "invalid_number",
  "quality_issues": [
    "low_volume",
    "choppy_robotic"
  ],
  "spam": true,
  "call_score": 2,
  "comment": "this is a call",
  "incident": "https://twilio.zendesk.com/support/tickets/17353089",
  "url": "https://insights.twilio.com/v1/Voice/CAaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Annotation"
}
```
