> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/xamarin/annotation/annotation-handling.md).

# Annotation handling

Learn how to customize annotation handling for Xamarin.Android with Apryse SDK. Intercept and customize annotation events, get notified after actions, and enhance user interactions. Explore more custo

Apryse SDK allows you to intercept annotation events and add custom code for when they are triggered.

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

## Customize annotation handling for Xamarin.Android

{% hint style="info" %}
**This tutorial only applies to Xamarin.Android. See Xamarin.iOS equivalent here .**
{% endhint %}

By default, the Tools library will respond to user actions such as a click event on a link or form widget, or a property change event on a selected annotation. It is possible to customize such behavior before it is executed within the Tools library, as well as getting notified of an action after it has happened.

## Intercept annotation events

If you would like to customize the behavior executed in response to user actions **prior** to it being handled by the Tools library, it is possible to do so with the `BasicAnnotationListener.onInterceptAnnotationHandling(Annot, Bundle, int)` API. If this method returns true, then it will intercept executing the default logic.

In `BasicAnnotationListener.onInterceptAnnotationHandling(Annot, Bundle, int)`, the second parameter, `Bundle`, contains the name of the action intercepted by this function, as well as some extra information. You can get the name of the intercepted action by calling `bundle.getString(Tool.METHOD_FROM)`:

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
    if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
        String methodCalling = extra.getString(Tool.METHOD_FROM);
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
override fun onInterceptAnnotationHandling(annot: Annot?, extra: Bundle?, toolMode: ToolMode): Boolean {
    if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
        val methodCalling = extra.getString(Tool.METHOD_FROM)
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

To get extra information, first obtain the information keys by calling `bundle.getStringArray(Tool.KEYS)`:

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
String[] paramKeys = extra.getStringArray(Tool.KEYS)
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
val paramKeys = extra!!.getStringArray(Tool.KEYS)
```

{% endcode %}
{% endtab %}
{% endtabs %}

Then, you can get the information values by looping on each key obtained above:

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
    if (extra != null && extra.containsKey(Tool.KEYS)) {
        String[] paramKeys = extra.getStringArray(Tool.KEYS);
        if (paramKeys != null) {
            for (String key : paramKeys) {
                // Gets the information value
                Object param = extra.get(key);
            }
        }
    }
}
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
override fun onInterceptAnnotationHandling(annot: Annot?, extra: Bundle?, toolMode: ToolMode): Boolean {
    if (extra != null && extra.containsKey(Tool.KEYS)) {
        val paramKeys = extra.getStringArray(Tool.KEYS)
        if (paramKeys != null) {
            for (key in paramKeys) {
                // Gets the information value
                val param = extra.get(key)
            }
        }
    }
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

### Common use cases

#### Links

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
mToolManager.setBasicAnnotationListener(new ToolManager.BasicAnnotationListener() {
    @Override
    public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
        try {
            // Intercept clicking link annotation by return true
            if (annot.getType() == Annot.e_Link) {
                Log.d("InterceptAnnot", "handling link annotation");
                return true;
            }
        } catch (PDFNetException e) {
            e.printStackTrace();
        }
        // return false so the other events can continue executing
        return false;
    }
});
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
mToolManager.setBasicAnnotationListener(object : ToolManager.BasicAnnotationListener {
    override fun onInterceptAnnotationHandling(annot: Annot?, extra: Bundle?, toolMode: ToolMode?): Boolean {
        try {
            // Intercept clicking link annotation by return true
            if (annot!!.type == Annot.e_Link) {
                Log.d("InterceptAnnot", "handling link annotation")
                return true
            }
        } catch (e: PDFNetException) {
            e.printStackTrace()
        }
        // return false so the other events can continue executing
        return false
    }
})
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Form widgets

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
mToolManager.setBasicAnnotationListener(new ToolManager.BasicAnnotationListener() {
    @Override
    public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
        try {
            // Intercept clicking widget annotation by return true
            if (annot.getType() == Annot.e_Widget) {
                Log.d("InterceptAnnot", "handling widget annotation");
                return true;
            }
        } catch (PDFNetException e) {
            e.printStackTrace();
        }
        // return false so the other events can continue executing
        return false;
    }
});
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
mToolManager.setBasicAnnotationListener(object : ToolManager.BasicAnnotationListener {
    override fun onInterceptAnnotationHandling(annot: Annot?, extra: Bundle?, toolMode: ToolMode?): Boolean {
        try {
            // Intercept clicking widget annotation by return true
            if (annot!!.type == Annot.e_Widget) {
                Log.d("InterceptAnnot", "handling widget annotation")
                return true
            }
        } catch (e: PDFNetException) {
            e.printStackTrace()
        }
        // return false so the other events can continue executing
        return false
    }
})
```

{% endcode %}
{% endtab %}
{% endtabs %}

#### Full sample code

For example, the following code demonstrates several scenarios and how you can get notified **before** each: clicking on a radio button, changing the annotation opacity, and clicking on a link. See the comments in the code for details.

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
mToolManager.setBasicAnnotationListener(new ToolManager.BasicAnnotationListener() {
    @Override
    public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
        /*
            For example, when a radio button is clicked, this code will print:
            calling method: handleWidget
            property: OTHER
        */
        if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
            String methodCalling = extra.getString(Tool.METHOD_FROM);
            Log.d("InterceptAnnot", "calling method " + methodCalling);
            AnnotationProperty.Property property = AnnotationProperty.getProperty(methodCalling);
            Log.d("InterceptAnnot", "property: " + property);
        }
        /*
            For example, when annotation opacity is about to be changed to 50%, this code will print:
            calling method: editOpacity
            property: OPACITY
            key: opacity
            value: 0.5
        */
        if (extra != null && extra.containsKey(Tool.KEYS)) {
            String[] paramKeys = extra.getStringArray(Tool.KEYS);
            if (paramKeys != null) {
                for (String key : paramKeys) {
                    Object param = extra.get(key);
                    Log.d("InterceptAnnot", "key: " + key);
                    Log.d("InterceptAnnot", "value: " + param.toString());
                }
            }
        }
        try {
            // Intercept radio button from clicking by return true
            if(annot.getType() == Annot.e_Widget) {
                Widget w = new Widget(annot);
                Field field = w.getField();
                if (field != null && field.isValid() && field.getType() == Field.e_radio) {
                    return true;
                }
            }
            // Intercept clicking link annotation by return true
            if (annot.getType() == Annot.e_Link) {
                Log.d("InterceptAnnot", "handling link annotation");
            }
        } catch (PDFNetException e) {
            e.printStackTrace();
        }
        // return false so the other events can continue executing
        return false;
    }
});
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
mToolManager.setBasicAnnotationListener(object : ToolManager.BasicAnnotationListener {
    override fun onInterceptAnnotationHandling(annot: Annot?, extra: Bundle?, toolMode: ToolMode?): Boolean {
        /*
      For example, when a radio button is clicked, this code will print:
      calling method: handleWidget
      property: OTHER
      */
        if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
            val methodCalling = extra.getString(Tool.METHOD_FROM)
            Log.d("InterceptAnnot", "calling method " + methodCalling)
            val property = AnnotationProperty.getProperty(methodCalling)
            Log.d("InterceptAnnot", "property: " + property)
        }
        /*
      For example, when annotation opacity is about to be changed to 50%, this code will print:
      calling method: editOpacity
      property: OPACITY
      key: opacity
      value: 0.5
      */
        if (extra != null && extra.containsKey(Tool.KEYS)) {
            val paramKeys = extra.getStringArray(Tool.KEYS)
            if (paramKeys != null) {
                for (key in paramKeys) {
                    val param = extra.get(key)
                    Log.d("InterceptAnnot", "key: " + key)
                    Log.d("InterceptAnnot", "value: " + param.toString())
                }
            }
        }
        try {
            // Intercept radio button from clicking by return true
            if (annot!!.type == Annot.e_Widget) {
                val w = Widget(annot)
                val field = w.getField()
                if (field != null && field.isValid() && field.getType() === Field.e_radio) {
                    return true
                }
            }
            // Intercept clicking link annotation by return true
            if (annot!!.type == Annot.e_Link) {
                Log.d("InterceptAnnot", "handling link annotation")
            }
        } catch (e: PDFNetException) {
            e.printStackTrace()
        }
        // return false so the other events can continue executing
        return false
    }
})
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Get notified after an action

If you simply want to get notified **after** the action has happened, you can do so via the `AnnotationModificationListener.onAnnotationsModified(Map<Annot, Integer>)` API. This event callback is raised when an annotation change has occurred. For example, in order to get notified when the value of a checkbox has been changed and when annotation opacity has been changed, do the following:

{% tabs %}
{% tab title="Java" %}
{% code lineNumbers="true" %}

```java
ToolManager.AnnotationModificationListener annotationModificationListener = new ToolManager.AnnotationModificationListener() {
    @Override
    public void onAnnotationsModified(Map<Annot, Integer> annots, Bundle extra) {
        /*
            For example, when a checkbox's value has been changed, this code will print:
            calling method: handleWidget
            property: OTHER
        */
        if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
            String methodCalling = extra.getString(Tool.METHOD_FROM);
            Log.d("AnnotationsModified", "calling method " + methodCalling);
            AnnotationProperty.Property property = AnnotationProperty.getProperty(methodCalling);
            Log.d("AnnotationsModified", "property: " + property);
        }
        /*
            For example, when annotation opacity is changed to 50%, this code will print:
            calling method: editOpacity
            property: OPACITY
            key: opacity
            value: 0.5
        */
        if (extra != null && extra.containsKey(Tool.KEYS)) {
            String[] paramKeys = extra.getStringArray(Tool.KEYS);
            if (paramKeys != null) {
                for (String key : paramKeys) {
                    Object param = extra.get(key);
                    Log.d("AnnotationsModified", "key: " + key);
                    Log.d("AnnotationsModified", "value: " + param.toString());
                }
            }
        }
    }
};
mToolManager.addAnnotationModificationListener(annotationModificationListener);
```

{% endcode %}
{% endtab %}

{% tab title="Kotlin" %}
{% code lineNumbers="true" %}

```kotlin
val annotationModificationListener: ToolManager.AnnotationModificationListener = object : ToolManager.AnnotationModificationListener {
  override fun onAnnotationsModified(annots: MutableMap<Annot, Int>?, extra: Bundle?) {
    /*
      For example, when a checkbox's value has been changed, this code will print:
      calling method: handleWidget
      property: OTHER
      */
    if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
      val methodCalling = extra.getString(Tool.METHOD_FROM)
      Log.d("AnnotationsModified", "calling method " + methodCalling)
      val property = AnnotationProperty.getProperty(methodCalling)
      Log.d("AnnotationsModified", "property: " + property)
    }
    /*
      For example, when annotation opacity is changed to 50%, this code will print:
      calling method: editOpacity
      property: OPACITY
      key: opacity
      value: 0.5
      */
    if (extra != null && extra.containsKey(Tool.KEYS)) {
      val paramKeys = extra.getStringArray(Tool.KEYS)
      if (paramKeys != null) {
        for (key in paramKeys) {
          val param = extra.get(key)
          Log.d("AnnotationsModified", "key: " + key)
          Log.d("AnnotationsModified", "value: " + param.toString())
        }
      }
    }
  }
}
mToolManager.addAnnotationModificationListener(annotationModificationListener)
```

{% endcode %}
{% endtab %}
{% endtabs %}

{% code lineNumbers="true" %}

```csharp
mToolManager.AnnotationsModified += (sender, e) =>
{
    var extra = e.Extra;
    /*
        For example, when checkbox value has been changed, this code will print:
        calling method: handleWidget
        property: OTHER
    */
    if (extra != null && extra.ContainsKey(Tool.MethodFrom))
    {
        String methodCalling = extra.GetString(Tool.MethodFrom);
        Console.WriteLine("AnnotationsModified calling method " + methodCalling);
        var property = pdftron.PDF.Model.AnnotationProperty.GetProperty(methodCalling);
        Console.WriteLine("AnnotationsModified property: " + property);
    }

    /*
        For example, when changed annotation opacity to 50%
        calling method: editOpacity
        property: OPACITY
        key: opacity
        value: 0.5
    */
    if (extra != null && extra.ContainsKey(Tool.Keys))
    {
        String[] paramKeys = extra.GetStringArray(Tool.Keys);
        if (paramKeys != null)
        {
            foreach (String key in paramKeys)
            {
                Object param = extra.Get(key);
                Console.WriteLine("AnnotationsModified key: " + key);
                Console.WriteLine("AnnotationsModified value: " + param.ToString());
            }
        }
    }

    // Do something with the annots
    foreach (var item in e.Annots)
    {
        var nativeAnnot = item.Key;
        var annot = TypeConvertHelper.ConvAnnotToManaged(nativeAnnot);
        if (annot != null && annot.IsValid())
        {
            Annot.Type type = annot.GetType();
            Console.WriteLine("AnnotationsModified: type: " + type);
        }
    }
};
```

{% endcode %}

We are always interested in expanding the customization options through APIs, and will be adding more options in the future. If you would like to suggest changes, please don't hesitate to [get in touch](https://apryse.com/form/feature-request).
{% endtab %}

{% tab title="iOS" %}

## Customize annotation handling for Xamarin.iOS

{% hint style="info" %}
**This tutorial only applies to Xamarin.iOS. See Xamarin.Android equivalent here .**
{% endhint %}

Annotation and PDF interaction is implemented within the open-source [`Tools.framework`](/xamarin/annotation/tools-overview.md#ios). This includes annotation creation & selection, text selection, form filling and link following.

The behavior is implemented via a collection of "Tools": classes that derive from the abstract base class [`PTTool`](https://sdk.apryse.com/api/xamarinios/tools/api/pdftron.PDF.Tools.PTTool.html) and that are coordinated by a [`PTToolManager`](https://sdk.apryse.com/api/xamarinios/tools/api/pdftron.PDF.Tools.PTToolManager.html). The `PTToolManager` provides the ability to customize tool behavior, and enable/disable the ability for users to create or edit annotations (both in general and on an annotation type by annotation type basis).

## Create and edit annotations

To disable (or re-enable) the ability to create or edit annotations, options can be altered as shown below. When disabled, the relevant annotation tool is removed from the [annotation toolbar](/xamarin/annotation/annotation-toolbar.md#ios), and from the [`UIMenuController`](https://developer.apple.com/uikit/uimenucontroller/).

{% code lineNumbers="true" %}

```csharp
// disables all text annotation types (highlights, underlines, etc.)
ToolManager.HighlightAnnotationOptions.CanCreate = false;
ToolManager.HighlightAnnotationOptions.CanEdit = false;
ToolManager.UnderlineAnnotationOptions.CanCreate = false;
ToolManager.UnderlineAnnotationOptions.CanEdit = false;
ToolManager.StrikeOutAnnotationOptions.CanCreate = false;
ToolManager.StrikeOutAnnotationOptions.CanEdit = false;
ToolManager.SquigglyAnnotationOptions.CanCreate = false;
ToolManager.SquigglyAnnotationOptions.CanEdit = false;
```

{% endcode %}

## Annotation interaction and UIMenuController

Further control over annotation interaction behaviour via the [`PTToolManagerDelegate`](https://sdk.apryse.com/api/xamarinios/tools/api/pdftron.PDF.Tools.PTToolManagerDelegate.html) protocol.

There are several methods that allow you to be notified of, and if desired modify or prevent, default behavior from occurring. For all methods, if `false` is returned, then the default behavior will not occur.

1. [PTToolManager.ShouldSelectAnnotation](https://sdk.apryse.com/api/xamarinios/tools/api/pdftron.PDF.Tools.PTToolManager.html#pdftron_PDF_Tools_PTToolManager_ShouldSelectAnnotation)This method is called just before an annotation is selected. The [annotation object](https://sdk.apryse.com/api/xamarinios/pdfnet/api/pdftron.PDF.Annot.html) itself is available for the decision making process, and for further action if needed.
2. [PTToolManager.ShouldShowMenu](https://sdk.apryse.com/api/xamarinios/tools/api/pdftron.PDF.Tools.PTToolManager.html#pdftron_PDF_Tools_PTToolManager_ShouldShowMenu)This method is called just before the selection popup menu is shown. The [`UIMenuController`](https://developer.apple.com/uikit/uimenucontroller/) object is passed so that menu items can be added or removed as required.
3. [PTToolManager.ShouldHandleLinkAnnotation](https://sdk.apryse.com/api/xamarinios/tools/api/pdftron.PDF.Tools.PTToolManager.html#pdftron_PDF_Tools_PTToolManager_ShouldHandleLinkAnnotation)This method is called just before a link is followed. The link is provided so that alternate action can be taken if required.
4. [PTToolManager.ShouldSwitchToTool](https://sdk.apryse.com/api/xamarinios/tools/api/pdftron.PDF.Tools.PTToolManager.html#pdftron_PDF_Tools_PTToolManager_ShouldSwitchToTool)This method is called just before a tool is activated. The [tool](https://sdk.apryse.com/api/xamarinios/tools/api/pdftron.PDF.Tools.PTTool.html) is available for the decision making process.

### Example

The sample code uses `ShouldShowMenu` to restrict use of the [`UIMenuController`](https://developer.apple.com/uikit/uimenucontroller/) to copying and defining text found in the PDF. This is done by stopping the UIMenuController from popping up in any case other than selecting text, and by removing options to highlight/underline etc. from the selected text UIMenuController popup.

{% code lineNumbers="true" %}

```csharp
mToolManager.ShouldShowMenu = (sender, menuController, annotation, pageNumber) =>
{
    // remove all items except signature and free text
    if (mToolManager.Tool is pdftron.PDF.Tools.PanTool)
    {
        menuController.MenuItems = removeQuickMenuItem(menuController.MenuItems);
    }
    return true;
};

UIMenuItem[] removeQuickMenuItem(UIMenuItem[] items) {
    var itemsArray = new List<UIMenuItem>(items);
    var itemsToRemove = new List<String> {
        "Note",
        "Ink",
        "Arrow",
        "Line",
        "Rectangle",
        "Ellipse"
    };

    for (int i = 0; i < items.Length; i++) {
        var itemStr = PDFViewCtrlToolsUtil.ToolsBundle.GetLocalizedString(items[i].Title, null);
        if (itemsToRemove.Contains(itemStr)) {
            itemsArray.Remove(items[i]);
        }
    }
    return itemsArray.ToArray();
}
```

{% endcode %}

| Default Menu Options                                                                                                                                                                                                                            | Customized Menu Options                                                                                                                                                                                                                         |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ![](https://653871032-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgjsBtuYmcKhWOdM9VCg4%2Fuploads%2Fgit-blob-55e916ff02b74ab6cb35fca25c8c12d06cd278db%2F88f82bec5692d821728ec1fd0ff1860c9630593b-746x1057.png?alt=media) | ![](https://653871032-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgjsBtuYmcKhWOdM9VCg4%2Fuploads%2Fgit-blob-ee82a7419077954663982f94d692161f2c653f04%2Fddb2d8e7e95dbf073f7da8507bf2c147134feef9-746x1057.png?alt=media) |
| ![](https://653871032-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgjsBtuYmcKhWOdM9VCg4%2Fuploads%2Fgit-blob-225567763808518b0cdc9ad2210677505b4bb9a3%2F5b9d090ef5112a9f2e87b2bc809d575cca1f557b-746x1057.png?alt=media) | ![](https://653871032-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgjsBtuYmcKhWOdM9VCg4%2Fuploads%2Fgit-blob-6539b7069d6136aa5d6387137322c164d3cbe3a2%2F2f8c10ab1ee744c15211ccc853f46b5923701f3b-746x1057.png?alt=media) |

## Override classes

`Tools.framework` frequently creates new instances of objects defined within the framework (e.g. a new instance of `PTAnnotEditTool` is created when a user taps on an annotation). In order to customize certain aspects of the default behavior, it is required to create and use a subclass of the built-in tool. To enable this without requiring source code modification, `Tools.framework` includes a system to "inject" an externally defined subclass that will be used by the `Tools.framework` during its normal operation. This is done via the `PTOverrides` class as follows:

{% code lineNumbers="true" %}

```csharp
// EGAnnotEditTool is an externally defined class that derives from PTAnnotEditTool
var cls = new Class(typeof(PTAnnotEditTool));
var own = new Class(typeof(EGAnnotEditTool));
PTOverrides.OverrideClass(cls, own);
```

{% endcode %}

Note that in order to be compatible with the external override system, the base class must conform to the `PTOverridable` protocol.

## Customize by modifying the source code

Because `Tools.framework` is open source, any and all changes are possible by editing the source code directly. The project is found in `/Lib/Tools/src`.

If you customize the tools source code, you will likely want to use a universal framework (one that contains architectures for both simulators and devices), which is *not* done automatically by Xcode. The Tools project includes a custom script step that automatically creates a universal framework, located in a folder next to the default build location, with the name `{Debug,Release}-universal`.

(Building a universal framework also be done manually by first building for device, then simulator, and using the terminal command `xcrun -sdk iphoneos lipo -create` to merge the binaries (`Tools.framework/Tools`) into a universal binary.)

Then create the Xamarin binding as described here: [Create Tools package from PDFViewCtrlTools Objective-C source code ](/xamarin/learn-more/objc-ios.md).
{% endtab %}
{% endtabs %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## 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, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/xamarin/annotation/annotation-handling.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

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.
