# Setup

Learn how to get your API key and how to send requests to the platform.

### Obtaining an API key

All accounts can request an API key by visiting the ["API Settings" section of your account](https://annolab.ai/settings/api-keys)&#x20;

![How to get to settings page from dashboard](/files/-MRHD5kDiJLuUx3Nfco1)

On the api-key page you can generate a new key with READ, WRITE, or both privileges.&#x20;

![](/files/-MRHDnpdpPGrMZ6Grauu)

If you generate a new key, please remember to copy the key to a safe location. This will be your only opportunity to copy the key and if you lose it you will need to generate a new one.

### Sending an API Request

Anno Lab accepts generic http requests that can be made from any programming language. Throughout this documentation site we have provided code samples to see concrete usage in action. Authorization for the request must be included in the header, specifically in the `Authorization` section with the pattern shown below.&#x20;

For particular routes and depending on how you send the request, you also may need to manually set the `Content-Type` header to have the value `application/json`. Many packages will automatically set this header (such as python `requests` used throughout this tutorial when you pass data using the json argument).&#x20;

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

project = {
  'name': 'New NER Project'
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/project/create'

response = requests.post(url, headers=headers, json=project)

print(response.json())
```

{% endtab %}
{% endtabs %}


# AnnoLab SDK

Python SDK to interact with AnnoLab

AnnoLab has a python SDK to improve the experience of performing certain AnnoLab actions. We highly recommend using this SDK for things like uploading files, as it greatly speeds uploads and simplifies the experience.

[Pypi link](https://pypi.org/project/annolab/)

### Installing via pip

```
pip install annolab
```

### Using the sdk

To get started, ensure you have an annolab account at <https://app.annolab.ai/signup> and have created an API Key. Instructions for creating an API Key may be found at <https://docs.annolab.ai/>.

1. Create an instance of the SDK passing your api\_key.

```python
from annolab import Annolab
lab = AnnoLab(api_key='YOUR_API_KEY')
```

### Using the sdk to upload pdf source

For pdf uploads to work, the user associated with your api key must have permissions to edit sources on your project. Permissions can be modified by admins on the appropriate project details page found under <https://app.annolab.ai/projects>

Obtain the project

```python
project = lab.find_project('My Project')
```

Upload from a local file system to a specific directory in your project. OCR the pdf using annolab OCR

```python
project.create_pdf_source(
    file='/path/to/file', 
    name='custom_name.pdf', 
    directory='Uploads',
    ocr=True,
    ocrProvider='textract_plus', # textract_plus is the same as "Annolab" OCR
)
```

### Using the sdk to upload pdf source and trigger an AI workflow

For pdf uploads invoking workflows to work, the user associated with your api key must have permissions to edit sources on your project and must have the ability to "run" machine learning models on your project.

Obtain the project

```python
project = lab.find_project('My Project')
```

Upload from a local file system to a specific directory in your project. Use the OCR provider and suite of ML models specified by a workflow

```python
project.create_pdf_source(
    file='/path/to/file', 
    name='custom_name.pdf', 
    directory='Uploads',
    workflow='aircraft_title', 
)
```


# Projects

Projects are the highest level abstraction in the Annotation Lab platform. They contain directories, source files, schemas, and annotation layers. They are also the scope at which work can be shared.

## Create Project

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/project/create`

Create a new project within your group&#x20;

#### Headers

| Name          | Type   | Description                                                                                                                                                             |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p>Where you put your api key. Creating a project requires a key with "Write" permissions.<br><br><code>{"Authorization": "Api-key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name | Type   | Description                                                                                                                  |
| ---- | ------ | ---------------------------------------------------------------------------------------------------------------------------- |
| name | string | <p>Name of the project you wish to create. Must be unique for your group<br><br><code>{"name": "New NER Project"}</code></p> |

{% tabs %}
{% tab title="201 Project was successfully created" %}

```
{
    "name": "New NER Project",
    "id": 22,
    "groupId": 14
}
```

{% endtab %}

{% tab title="400 Project creation failed" %}

```
{
    "message": "Information about why creation failed"
}
```

{% endtab %}
{% endtabs %}

Examples of how to make a project create request

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

project = {
  'name': 'New NER Project'
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/project/create'

response = requests.post(url, headers=headers, json=project)

print(response.json())
```

{% endtab %}
{% endtabs %}

## Get Project

<mark style="color:blue;">`GET`</mark> `https://api.annolab.ai/v1/project/{identifier}`

Return details of a project given an identifier&#x20;

#### Path Parameters

| Name       | Type   | Description                                                                                                                                                                                          |
| ---------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| identifier | string | <p>Either the name or the id of a project<br><br><code>url = "<https://api.annolab.ai/v1/project/New%20NER%20Project>"</code><br><br><code>url = "<https://api.annolab.ai/v1/project/12>"</code></p> |

#### Headers

| Name          | Type   | Description                                                                                                                                                            |
| ------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p>Where you put your api key. Getting a project requires an  key with "Read" permissions<br><br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

{% tabs %}
{% tab title="200 Project successfully retrieved" %}

```
{
    "name": "New NER Project",
    "id": 22,
    "groupId": 14
}
```

{% endtab %}

{% tab title="404 Could not find a project matching the information" %}

```
{}
```

{% endtab %}
{% endtabs %}


# Directories

Directories are containers for Source Files that can be used to help organize the contents of a project

## Create Directory

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/directory/create`

Create a new directory within the project

#### Headers

| Name          | Type   | Description                                                                                                                                                           |
| ------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p>Where you put your api key. Creating a directory requires a key with "Write" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name              | Type   | Description                                                                                                       |
| ----------------- | ------ | ----------------------------------------------------------------------------------------------------------------- |
| projectIdentifier | string | Identifier of the project that the directory will be created within. Either id or the unique name of the project. |
| name              | string | Name of the directory you wish to create                                                                          |

{% tabs %}
{% tab title="201 The directory was created" %}

```
{
    "name": "Wikipedia Subset",
    "id": 12,
    "projectname": "New NER Project",
    "projectId": 22
}
```

{% endtab %}

{% tab title="400 The directory could not be created" %}

```
{
    "message": "explanation for why directory could not be created"
}
```

{% endtab %}
{% endtabs %}

Example of how to make the request to create a directory

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

directory = {
  'projectIdentifier': 'New NER Project',
  'name': 'Wikipedia Subset'
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/directory/create'

response = requests.post(url, headers=headers, json=directory)

print(response.json())
```

{% endtab %}
{% endtabs %}


# Source Files

Source files are files that contain things you want to annotate or run models on. Currently we support PDF and .txt file formats

## Retrieve source information

<mark style="color:blue;">`GET`</mark> `https://api.annolab.ai/v1/source/{source_id}`

Returns basic source information, including a signed URL to download the original file and its tags.

#### Query Parameters

| Name                                         | Type | Description      |
| -------------------------------------------- | ---- | ---------------- |
| source\_id<mark style="color:red;">\*</mark> | Int  | Id of the source |

#### Headers

| Name                                            | Type   | Description                                                                              |
| ----------------------------------------------- | ------ | ---------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Your API key<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

{% tabs %}
{% tab title="200: OK " %}

{% endtab %}
{% endtabs %}

```json
// Example Response
{
    "id": 2,
    "projectName": "My Project",
    "projectId": 1,
    "directoryName": "Uploads",
    "directoryId": 1,
    "name": "REGISTRATION.pdf",
    "sourceName": "REGISTRATION.pdf",
    "type": "pdf",
    "text": "Example PDF Text",
    "url": "https://download-example-url.pdf",
    "createdAt": "2023-05-22T20:32:02.633Z",
    "tags": [
        {
            "domainEntityId": 1,
            "typeName": "Airframe Inventory",
            "attributes": [
                {
                    "name": "Make",
                    "value": "CESSNA"
                },
                {
                    "name": "Model",
                    "value": "421C"
                },
                {
                    "name": "Serial Number",
                    "value": "421C-5837"
                }
            ],
            "createdBy": {
                "id": 58473,
                "email": "testuser@gmail.com",
                "username": "testuser"
            }
        }
    ]
}
```

## Upload a PDF

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/source/upload-pdf`

Upload a PDF and specify an OCR method to apply. (optional) invoke a workflow of AI models

#### Headers

| Name                                            | Type   | Description                                                                                                                                                           |
| ----------------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Creating a directory requires a key with "Write" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                                | Type            | Description                                                                                                                                        |
| --------------------------------------------------- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| projectIdentifier<mark style="color:red;">\*</mark> | string\|number  | Either id of the project or name of the project where file will reside                                                                             |
| directoryIdentifier                                 | string          | name of the directory where the file will reside                                                                                                   |
| sourceIdentifier<mark style="color:red;">\*</mark>  | string          | Name of the source that will be created                                                                                                            |
| ocrProvider                                         | string          | Only used if processMode is set to OCR. Valid values are "textract", "textract\_plus", and "gcv". "textract\_plus" recommended for highest quality |
| preprocessor                                        | string          | Valid options are "faa" and None.                                                                                                                  |
| groupName<mark style="color:red;">\*</mark>         | string          | Name of the group that owns the project                                                                                                            |
| tags                                                | CanonicalTag\[] | Array of [CanonicalTag](/annotations-and-relations/canonical-tags#canonicaltag-object) objects                                                     |
| workflow                                            | string          | Workflow (aka package of AI models) that will be invoked immediately after upload. Recommend "FAA\_CD\_WITH\_VLM" or "FAA\_CD\_WITH\_TAGGING"      |
| processMode                                         | string          | Use "OCR" if the pdf is not already text enriched. Use "EXTRACT" if pdf already has text embedded                                                  |

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

```python
import os
import json
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

url_base = 'https://api.annolab.ai'

input_pdf = '/Users/grantdelozier/devel/ocr-these3/TEST-REGISTRATION.PDF'

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = url_base+'/v1/source/create-pdf'

requestBody = {
  'groupName': 'AnnoLab',
  'projectIdentifier': 'title-demo',
  'directoryIdentifier': 'testing',
  'sourceIdentifier': 'TEST-REGISTRATION.PDF',
  'preprocessor': 'faa',
  'processMode': 'OCR',
  'ocrProvider': 'textract_plus',
  'workflow': 'FAA_CD'
}

fileToUpload = {
  'file': ('TEST-REGISTRATION.PDF', open(input_pdf, 'rb'), 'application/pdf')
}

url = url_base+'/v1/source/upload-pdf'

response = requests.post(url, headers=headers, data=requestBody, files=fileToUpload)
print(response.json())

```

{% endtab %}
{% endtabs %}

## Create Source Text

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/source/create-text`

Create a new text file source within a directory.

#### Headers

| Name                                            | Type   | Description                                                                                                                                                           |
| ----------------------------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | string | <p>Where you put your api key. Creating a directory requires a key with "Write" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                | Type   | Description                                                                                      |
| ------------------- | ------ | ------------------------------------------------------------------------------------------------ |
| projectIdentifier   | string | Identifier for the project that will contain the source file. Either the id or the unique name   |
| directoryIdentifier | string | Identifier for the directory that will contain the source file. Either the id or the unique name |
| sourceName          | string | Name of the file you wish to create                                                              |
| text                | string | Text that exists within the file                                                                 |

{% tabs %}
{% tab title="201 Source text was successfully created" %}

```
{
    "sourceName": "athens.txt,
    "directoryName": "Wikipedia Subset",
    "directoryId": 12,
    "projectName": "New NER Project",
    "projectId": 22,
    "id": 145
}
```

{% endtab %}
{% endtabs %}

This code shows how to create a new text file source

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

source = {
  'projectIdentifier': 'New NER Project',
  'directoryIdentifier': 'Wikipedia Subset',
  'sourceName': 'athens.txt'
  'text': 'Athens (Greek: Αθήνα, Athína), is the capital city of Greece with a metropolitan population of 3.7 million inhabitants.'
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/source/create-text'

response = requests.post(url, headers=headers, json=source)

print(response.json())
```

{% endtab %}
{% endtabs %}


# Annotation Types

Annotation types are the valid annotation labels that can be applied to source material.

## Create Annotation Type

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/annotation-type/create`

Create a new annotation type within your schema

#### Headers

| Name                                            | Type   | Description                                                                                                                                                        |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Authorization<mark style="color:red;">\*</mark> | string | <p>Where you put your api key. Creating a schema requires a key with "Write" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                                | Type    | Description                                                                                                                           |
| --------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| isRelation                                          | boolean | Whether the type being created is intended for use as an annotation relation type. Defaults to False                                  |
| color                                               | string  | <p>Hex code for the color of the annotation type <br><code>color: "#D00021B"</code> <br>if not provided it will be auto generated</p> |
| typeName<mark style="color:red;">\*</mark>          | string  | Name of the annotation type that will be created                                                                                      |
| projectIdentifier<mark style="color:red;">\*</mark> | string  | Identifier for the project that will contain the annotation type. Either the id or the unique name.                                   |
| category                                            | string  | Category grouping for the annotation type                                                                                             |
| isDocumentClassification                            | boolean | Boolean for whether the annotation type is a document  type classification                                                            |

{% tabs %}
{% tab title="201 Annotation type was created successfully" %}

```
{
    "schemaName": "NER",
    "schemaId": 7,
    "key": "place-name",
    "color": "#F882FD",
    "typeId": "51",
    "name": "Place Name"
}
```

{% endtab %}
{% endtabs %}

This code shows how to create a new annotation type

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

annotationType = {
  'projectIdentifier': 'New NER Project',
  'category': 'NER',
  'typeName': 'Place Name' 
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/annotation-type/create'

response = requests.post(url, headers=headers, json=annotationType)

print(response.json())
```

{% endtab %}
{% endtabs %}


# Model Inferences

Inferences are how you request model predictions of annotations on your source files

All model inference requests are asynchronous, meaning you must make the request and then poll for the status.

## Request Inference

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/infer/batch`

Creates an model inference job to be run on one or more source files

#### Headers

| Name                                            | Type   | Description                                                                                                                                                                                        |
| ----------------------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | string | <p>Where you put your api key. Requesting inferences requires a "Model Run" permission on the project where sources exist<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                                    | Type            | Description                                                                                            |
| ------------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------ |
| projectIdentifier<mark style="color:red;">\*</mark>     | string          | Identifier of the project that contains the source files. Either id or the unique name of the project. |
| modelIdentifier<mark style="color:red;">\*</mark>       | string          | Identifier of the model that will be run. Either id or the unique name of the model.                   |
| sourceIds<mark style="color:red;">\*</mark>             | array           | array of source ids pointing to where models will be run                                               |
| outputLayerIdentifier<mark style="color:red;">\*</mark> | string\|integer | layer in which predictions will be generated                                                           |
| groupName<mark style="color:red;">\*</mark>             | String          | name of the group user belongs to                                                                      |

{% tabs %}
{% tab title="201 The inference job was created and is in queue" %}

```json
{
    "inferenceJobId": 12,
    "status": "Queued",
    "projectName": "Sample Project",
    "projectId": 1,
    "outputLayerName": "Gold Set",
    "outputLayerId": 12,
    "sourceIds": [3240, 4414],
}
```

{% endtab %}

{% tab title="400 The inference could not be started" %}

```
{
    "message": "explanation for why directory could not be created"
}
```

{% endtab %}
{% endtabs %}

## Request Inference Status

<mark style="color:blue;">`GET`</mark> `https://api.annolab.ai/v1/infer/batch/{job_id}`

Returns the status of the inference job

#### Path Parameters

| Name                                    | Type    | Description                                             |
| --------------------------------------- | ------- | ------------------------------------------------------- |
| jobId<mark style="color:red;">\*</mark> | Integer | Integer representing the inference job that was spawned |

#### Headers

| Name                                            | Type   | Description                                                                                                                                                                                        |
| ----------------------------------------------- | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | string | <p>Where you put your api key. Requesting inferences requires a "Model Run" permission on the project where sources exist<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

{% tabs %}
{% tab title="201 The inference job was created and is in queue" %}

```
{
    "inferenceJobId": 12,
    "status": "Queued",
    "projectId": 1,
    "sourceIds": [3240, 4414]
}
```

{% endtab %}

{% tab title="400 The inference could not be started" %}

```
{
    "message": "explanation for why directory could not be created"
}
```

{% endtab %}

{% tab title="404: Not Found Permissions problem or job doesn't exist" %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

This code shows how to call a specific model on 2 sources, poll status until the model inference is complete, then retrieve the results.

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

```python
import requests
import time

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

inferenceBody = {
  'groupName': 'Company Name',
  'projectIdentifier': 'My Project',
  'sourceIds': [4024, 5853],
  'modelIdentifier': 'Staple + Classify Documents',
  'outputLayerIdentifier': 'Gold Set'
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/infer/batch'

response = requests.post(url, headers=headers, json=inferenceBody)

print(response.json())

get_url = 'https://api.annolab.ai/v1/infer/batch/'+response.json()['inferenceJobId']
maximum_timeout_seconds = 1800
time_taken = 0 
inference_is_finished = False

start_time = time.time()
while not inference_is_finished and time_taken < maximum_timeout_seconds:
  status_response = requests.get(get_url, headers=headers, json=inferenceBody).json()
  if status_response['status'] in ['Finished', 'Errored']:
    print("Inference Finished")
    print(status_response)
    inference_is_finished = True
  time_taken = time.time() - start_time
```

{% endtab %}
{% endtabs %}


# Annotations

Annotations one of the fundamental building blocks of extracted data. They say that a portion of a source has some special meaning

## Create Annotation

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/annotation/create`

Create an annotation of some type on a source file. For text file sources, an annotation may reside over an array of character offsets or may simply be a document level (manual) annotation.

#### Headers

| Name          | Type   | Description                                                                                                                                                                 |
| ------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p>Where you put your api key. Creating an annotation requires a key with "Write" permissions.<br><br><code>{"Authorization": "Api-key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

<table><thead><tr><th>Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>clientId</td><td>string</td><td>string or integer that will be "passed through" the request. Useful in situations where async or bulk requests are used, and relation inserts will follow annotation inserts.</td></tr><tr><td>offsets</td><td>array</td><td>Array of integers describing where the annotation exists in terms of character offsets inside the source text. Leave undefined for document-level annotations or image annotations.</td></tr><tr><td>preventDuplication</td><td>boolean</td><td>Boolean indicating whether duplication protection should be in place. By default this is set to true. <br><br>Duplication being defined by any annotation with the exact same annotation type, offsets, layer, and source. Usually you only want to set this to false if you have multiple manual annotations (e.g. non-offset based) of the same type that you need to add on a source.</td></tr><tr><td>value</td><td>string</td><td>User defined value associated with the annotation</td></tr><tr><td>directoryIdentifier</td><td>string</td><td>Identifier of the directory containing the source that will have the annotation. Either the id or the unique name.</td></tr><tr><td>annoTypeIdentifier</td><td>string</td><td>Identifier of the annotation type associated with the annotation. Either the id or the unique name.</td></tr><tr><td>projectIdentifier</td><td>string</td><td>Identifier of the project containing the annotation. Either the id or the unique name.</td></tr><tr><td>layerIdentifier</td><td>integer</td><td>Identifier of the layer containing the annotation. Either the id or the unique name.</td></tr><tr><td>sourceIdentifier</td><td>integer</td><td>Identifier of the source where the annotation will be created. Either the id or the unique name.</td></tr><tr><td>textBounds</td><td>Geometry|Null</td><td><p>Polygon or MultiPolygon geometry object describing the location of the text the annotation contains within the page. </p><p></p><p>IMPORTANT: Ensure coordinates are in provided clockwise order, ideally from top-left. Otherwise annotations may not render correctly in AnnoLab or other viewers utilizing polygon data.</p><p></p><p>Example:</p><pre class="language-json"><code class="lang-json">{
  "type": "MultiPolygon",
  "coordinates": [
    [[
      [ 0.33, 0.32 ],
      [ 0.37, 0.32 ],
      [ 0.37, 0.34 ],
      [ 0.33, 0.34 ],
      [ 0.33, 0.32 ]
    ]],
    [[
      [ 0.376, 0.329 ],
      [ 0.405, 0.329 ],
      [ 0.405, 0.344 ],
      [ 0.376, 0.344 ],
      [ 0.376, 0.329 ]
    ]]
  ],
}
</code></pre></td></tr><tr><td>imageBounds</td><td>Geometry|Null</td><td><p>Polygon or MultiPolygon geometry object describing the location of the box drawn by a model or user on the page (always rectangular).<br><br>IMPORTANT: Ensure coordinates are provided in clockwise order, ideally from top-left. Otherwise annotations may not render correctly in AnnoLab or other viewers utilizing polygon data.<br><br>Example:</p><pre class="language-json"><code class="lang-json">{
  "type": "Polygon",
  "coordinates": [
    [
      [ 0.33, 0.32 ],
      [ 0.37, 0.32 ],
      [ 0.37, 0.34 ],
      [ 0.33, 0.34 ],
      [ 0.33, 0.32 ]
    ]
  ],
}
</code></pre></td></tr></tbody></table>

{% tabs %}
{% tab title="200 Annotation already exists" %}

```
{
  "id": 44,
  "typeId": 51,
  "typeName": "Place Name",
  "layerId": 5,
  "sourceId": 145,
  "typeId": 112,
  "value": '{latitude:"37.983810", longitude:"23.727539"}',
  "rawValue": 'Athens',
  "offsets": [0, 5]
 }
```

{% endtab %}

{% tab title="201 Annotation was successfully created" %}

```
{
  "id": 44,
  "typeId": 51,
  "typeName": "Place Name",
  "layerId": 5,
  "sourceId": 145,
  "typeId": 112,
  "value": '{latitude:"37.983810", longitude:"23.727539"}',
  "rawValue": 'Athens',
  "offsets": [0, 5]
}
```

{% endtab %}

{% tab title="400 Annotation creation failed" %}

```
{
    "message": "Information about why creation failed"
}
```

{% endtab %}
{% endtabs %}

Examples of how to make an annotation create request

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

annotation = {
  'annoTypeIdentifier': 'Place Name',
  'projectIdentifier': 'New NER Project',
  'layerIdentifier': 'NER Gold',
  'sourceIdentifier': 145,
  'offsets': [0, 5],
  'directoryIdentifier': 'Wikipedia Subset',
  'value': '{latitude:"37.983810", longitude:"23.727539"}'
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/annotation/create'

response = requests.post(url, headers=headers, json=annotation)

print(response.json())
```

{% endtab %}
{% endtabs %}

## Bulk Create Annotations

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/annotation/bulk-create`

Create a set of up to 2000 annotations in one request (can be a mix of many different annotation types and spread across many source files). \
\
80% faster than individual inserts in most cases

#### Headers

| Name          | Type   | Description                                                                                                                                                               |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p>Where you put your api key. Creating annotations requires a key with "write" permissions.<br><br><code>{"Authorization": "Api-key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name               | Type    | Description                                                                                                                                                                                                                                                                                                                                                                                 |
| ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| preventDuplication | boolean | <p>Boolean indicating whether duplication protection should be in place. By default this will be set to true<br><br>Duplication being defined by any annotation with the exact same annotation type, offsets, layer, and source. <br><br>We recommend only setting this to false if you are 100% sure that no duplications exist in the request, in which case it will be much quicker.</p> |
| annotations        | array   | Array of annotation objects that you wish to insert.A maximum of 2000 annotations can be created in one request.                                                                                                                                                                                                                                                                            |

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

```
```

{% endtab %}
{% endtabs %}

Examples of how to bulk create annotations

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

bulk_request = {
  'preventDuplication': True
  'annotations': [
    {
      'annoTypeIdentifier': 'Place Name',
      'projectIdentifier': 'New NER Project',
      'schemaIdentifier': 'NER',
      'layerIdentifier': 'NER Gold',
      'sourceIdentifier': 145,
      'offsets': [0, 5],
      'directoryIdentifier': 'Wikipedia Subset',
      'value': '{latitude:"37.983810", longitude:"23.727539"}',
      'clientId': "24a"
    },
    {
      'annoTypeIdentifier': 'Place Name',
      'projectIdentifier': 'New NER Project',
      'schemaIdentifier': 'NER',
      'layerIdentifier': 'NER Gold',
      'sourceIdentifier': 145,
      'offsets': [120, 128],
      'directoryIdentifier': 'Wikipedia Subset',
      'value': '{latitude:"37.983810", longitude:"23.727539"}',
      'clientId': "24b"
    }
  ]
}

url = 'https://api.annolab.ai/v1/annotation/bulk-create'

response = requests.post(url, headers=headers, json=bulk_request)
```

{% endtab %}
{% endtabs %}

## Annotation Object

An object corresponding to a single annotation

<table><thead><tr><th width="193.33333333333331">Attribute Name</th><th>Type</th><th>Description</th></tr></thead><tbody><tr><td>annotationId</td><td>Integer</td><td>Unique id for the annotation</td></tr><tr><td>sourceReferenceId</td><td>Integer</td><td>Unique id for the file that contains the annotation</td></tr><tr><td>typeName</td><td>String</td><td>Name of the type of annotation</td></tr><tr><td>value</td><td>String</td><td>By default is the text that the annotation contains (can be manually overidden)</td></tr><tr><td>pageNumber</td><td>Integer</td><td>Starting page of the annotation</td></tr><tr><td>endPageNumber</td><td>Integer|Null</td><td>Ending page of the annotation (if single page annotation will be null)</td></tr><tr><td>offsets</td><td>Integer[]</td><td>Array describing character offsets of the annotation within the source</td></tr><tr><td>textBounds</td><td>Geometry|Null</td><td><p>MultiPolygon geometry object describing the location of the text the annotation contains within the page. </p><p></p><p>IMPORTANT: Ensure coordinates are in provided clockwise order, ideally from top-left. Otherwise annotations may not render correctly in AnnoLab or other viewers utilizing polygon data.</p><p></p><p>Example:</p><pre class="language-json"><code class="lang-json">{
  "type": "MultiPolygon",
  "coordinates": [
    [[
      [ 0.33, 0.32 ],
      [ 0.37, 0.32 ],
      [ 0.37, 0.34 ],
      [ 0.33, 0.34 ],
      [ 0.33, 0.32 ]
    ]],
    [[
      [ 0.376, 0.329 ],
      [ 0.405, 0.329 ],
      [ 0.405, 0.344 ],
      [ 0.376, 0.344 ],
      [ 0.376, 0.329 ]
    ]]
  ],
}
</code></pre></td></tr><tr><td>imageBounds</td><td>Geometry|Null</td><td><p>Polygon or MultiPolygon geometry object describing the location of the box drawn by a model or user on the page (always rectangular).<br><br>IMPORTANT: Ensure coordinates are provided in clockwise order, ideally from top-left. Otherwise annotations may not render correctly in AnnoLab or other viewers utilizing polygon data.<br><br>Example:</p><pre class="language-json"><code class="lang-json">{
  "type": "Polygon",
  "coordinates": [
    [
      [ 0.33, 0.32 ],
      [ 0.37, 0.32 ],
      [ 0.37, 0.34 ],
      [ 0.33, 0.34 ],
      [ 0.33, 0.32 ]
    ]
  ],
}
</code></pre></td></tr><tr><td>createdBy</td><td>Integer</td><td>User id that created the annotation (or user id that invoked the model)</td></tr><tr><td>updatedBy</td><td>Integer</td><td>User Id that updated the annotation</td></tr><tr><td>confidence</td><td>Float</td><td>Value between 0 and 100 representing the confidence of the OCR translation of any text bounds the annotation contains. <br>If annotation contains multiple text bounds, will be an average of all containing texts.</td></tr><tr><td>score</td><td>Float</td><td>Value between 0 and 1 representing sureness of a machine learning model in applying the annotation.<br><br>We calculate this by taking the average of the SoftMax for all tokens comprising the annotation</td></tr><tr><td>layerId</td><td>Integer</td><td>Id for the layer that contains the annotation</td></tr><tr><td>isReviewed</td><td>Boolean</td><td>Has the annotation been reviewed</td></tr><tr><td>reviewedBy</td><td>Integer|Null</td><td>Reviewer that reviewed the annotation</td></tr><tr><td>reviewedAt</td><td>DateTime|Null</td><td>Time of review</td></tr><tr><td>modelSourceId</td><td>Integer</td><td>Id for the model that produced the annotation</td></tr><tr><td>modelSource</td><td>String</td><td>Name of the model that produced the annotation</td></tr></tbody></table>

```json
{
    'annotationId': 403992,
    'sourceReferenceId': 12341, 
    'typeName': 'Grantor', 
    'value': ' Carsuo', 
    'pageNumber': 3, 
    'endPageNumber': null, 
    'offsets': [1320, 1326], 
    'textBounds': {'type': 'MultiPolygon', 'coordinates': [[[[0.565917551517487, 0.769474387168884], [0.609824299812317, 0.769511699676514], [0.609820425510406, 0.778583765029907], [0.565913617610931, 0.778546392917633], [0.565917551517487, 0.769474387168884]]]]}, 
    'imageBounds': null, 
    'createdBy': 5, 
    'updatedBy': null, 
    'confidence': 96.7900390625, 
    'score': 0.7074922025203705, 
    'layerId': 635, 
    'isReviewed': False, 
    'reviewedBy': null, 
    'reviewedAt': null, 
    'modelSourceId': 12, 
    'modelSource': 'Party Name Extractor'
}
```

## CanonicalAnnotation Object

An abstract form of an annotation that is not grounded in any explicit mention or context, simplified to the components of name and value.&#x20;

These objects cannot be created directly, instead they exist as attributes of [CanonicalTag](/annotations-and-relations/canonical-tags#canonicaltag-object) objects.

<table><thead><tr><th width="166.33333333333331">Attribute Name</th><th width="163">Type</th><th>Description</th></tr></thead><tbody><tr><td>name</td><td>String</td><td>The annotation type name. Must already exist as an annotation type in your project</td></tr><tr><td>value</td><td>String</td><td>Canonical value describing the annotation</td></tr></tbody></table>

```json
{
    "name": "Make",
    "value": "Cessna",
}
```


# Canonical Tags

Unique entities described by a set of annotations

Canonical Tags are a way to reference a singular entity that is comprised of multiple fixed annotations. This is a useful abstraction when dealing with things like Airframes (Make, Model, Serial), People (First, Middle, Last), or Land (Section, Township, Range, QQ1, QQ2, etc). They are intended as a uniquely disambiguating abstraction for the multiple ways that a single entity can be expressed or written in a document.

Canonical Tags exist in two states. In their unattached state as [CanonicalTag](#canonicaltag-object) objects and as [AttachedCanonicalTag](#attachedcanonicaltag-object) object when describing a CanonicalTag that has been attached to an entire instrument or source file.

## CanonicalTag Object

A canonical tag describes a unique entity defined by a type and an array of attributes

| Attribute Name  | Type                                                                                        | Description                                                                                                                                                          |
| --------------- | ------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| typeName        | String                                                                                      | Name describing the type of canonical tag                                                                                                                            |
| attributes      | [CanonicalAnnotation](/annotations-and-relations/annotations#canonicalannotation-object)\[] | Array of canonical annotations that comprise the canonical tag                                                                                                       |
| domainEntityId? | Integer                                                                                     | Unique id describing the canonical tag object                                                                                                                        |
| status?         | String                                                                                      | <p>"Created" or "Found"<br>Returned when creating tags in bulk to reflect whether each tag already exists (Found) or was newly created in the request (Created).</p> |

```json
{
  "typeName": "Airframe Inventory",  
  "attributes": [
      {"name": "Make", "value": "Beech"}, {"name": "Model", "value": "C24R"}, {"name": "Serial Number", "value": "MC-453"}
  ]
}
```

## List the tags in a project

<mark style="color:blue;">`GET`</mark> `https://api.annolab.ai/v1/project/{group_name}/{project_name}/tags`

Returns a paginated list of tags in a project. Returns a limit of 10,000 tags per page/request.

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name | Type    | Description                                                                                                                                              |
| ---- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| page | Integer | <p>Which page to return. Defaults to 1.<br>E.g. { "page" : 1 } returns first 1,000 results. { "page" : 2 } returns results 1,001 through 2,000. etc.</p> |

{% tabs %}
{% tab title="200: OK " %}

```json
[{
  "typeName": "Airframe Tag",
  "domainEntityId": 235,
  "attributes": [
      {"name": "Make", "value": "Raytheon"}, 
      {"name": "Model", "value": "850XP"}, 
      {"name": "Serial Number", "value": "755"},
      {"name": "Internal ID", "value": 4501}
  ],
  "createdBy": {"id": 14, "email": "tester@gmail.com", "username": "tester"}
}, {
  "typeName": "Airframe Tag",
  "domainEntityId": 240,
  "attributes": [
      {"name": "Make", "value": "CESSNA"}, 
      {"name": "Model", "value": "T303"}, 
      {"name": "Serial Number", "value": "T30300300"},
      {"name": "Internal ID", "value": 3561}
  ],
  "createdBy": {"id": 14, "email": "tester@gmail.com", "username": "tester"}
}]
```

{% endtab %}
{% endtabs %}

## Create one or more Tags

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/tag`

Creates canonical tags. (Does not attach). If an identical canonical tag already exists, it does not create at duplicate.

#### Headers

| Name                                            | Type | Description                                                                                                                                                         |
| ----------------------------------------------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> |      | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                                | Type            | Description                                                                           |
| --------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------- |
| projectIdentifier<mark style="color:red;">\*</mark> | String\|Number  | Project name or id of the project                                                     |
| tags<mark style="color:red;">\*</mark>              | CanonicalTag\[] | List of [CanonicalTag](#canonicaltag-object) objects to create                        |
| groupName                                           | String          | Name of the group that owns the project (only required if projectIdentifer is string) |

{% tabs %}
{% tab title="201: Created Array of created (or found) CanonicalTag objects." %}

```json
[{
  "typeName": "Airframe Tag",
  "domainEntityId": 235,
  "attributes": [
      {"name": "Make", "value": "Raytheon"}, 
      {"name": "Model", "value": "850XP"}, 
      {"name": "Serial Number", "value": "755"},
      {"name": "Internal ID", "value": 4501}
  ],
  "createdBy": {"id": 14, "email": "tester@gmail.com", "username": "tester"}
}, {
  "typeName": "Airframe Tag",
  "domainEntityId": 240,
  "attributes": [
      {"name": "Make", "value": "CESSNA"}, 
      {"name": "Model", "value": "T303"}, 
      {"name": "Serial Number", "value": "T30300300"},
      {"name": "Internal ID", "value": 3561}
  ],
  "createdBy": {"id": 14, "email": "tester@gmail.com", "username": "tester"}
}]
```

{% endtab %}
{% endtabs %}

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX' 

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

create_tag_url = 'https://api.annolab.ai/v1/tag'

project_name = "title-demo" 
group_name = "AnnoLab"
tag_list = [
  {
    'typeName': 'Airframe Inventory', 
    'attributes': [
      {'name': 'Make', 'value': 'Cessna'},
      {'name': 'Model', 'value': '501'},
      {'name': 'Serial Number', 'value': '501-0050'}
    ]
  }
]

tagPayload = {
  "projectIdentifier": project_name,
  "groupName": group_name,
  "tags": tag_list
}

r = requests.post(create_tag_url, headers=headers, json=tagPayload)

json_response = r.json()

print(json_response)

```

{% endtab %}
{% endtabs %}

## Edit a tag's values

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/tag/{domain_entity_id}`

Edits a [CanonicalTag](#canonicaltag-object)'s typeName and/or attributes. Does not alter attachments.

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                            | Type                   | Description                                                                                                                                   |
| ----------------------------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| typeName<mark style="color:red;">\*</mark>      | String                 | Name describing the type of canonical tag                                                                                                     |
| attributes\[]<mark style="color:red;">\*</mark> | CanonicalAnnotation\[] | Array of [CanonicalAnnotation](/annotations-and-relations/annotations#canonicalannotation-object)\[] objects that comprise the canonical tag. |

{% tabs %}
{% tab title="200: OK " %}

```json
{
    "typeName": "Airframe Tag",
    "domainEntityId": 235,
    "attributes": [
        {"name": "Make", "value": "Raytheon"}, 
        {"name": "Model", "value": "850XP"}, 
        {"name": "Serial Number", "value": "755"},
        {"name": "Internal ID", "value": 4501}
    ],
    "createdBy": {"id": 14, "email": "tester@gmail.com", "username": "tester"}
}
```

{% endtab %}
{% endtabs %}

## Delete a single tag by its domainEntityId

<mark style="color:red;">`DELETE`</mark> `https://api.annolab.ai/v1/tag/{domainEntityId}`

Deletes a [CanonicalTag](#canonicaltag-object). Delete will cascade and delete all related [AttachedCanonicalTag](#attachedcanonicaltag-object) objects as well.

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

{% tabs %}
{% tab title="200: OK " %}

{% endtab %}
{% endtabs %}

## Bulk delete tags by values

<mark style="color:red;">`DELETE`</mark> `https://api.annolab.ai/v1/tag`

Deletes a [CanonicalTag](#canonicaltag-object). Delete will cascade and delete all related [AttachedCanonicalTag](#attachedcanonicaltag-object) objects as well.

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                                | Type            | Description                                                                                         |
| --------------------------------------------------- | --------------- | --------------------------------------------------------------------------------------------------- |
| projectIdentifier<mark style="color:red;">\*</mark> | String\|Integer | String of the project containing the tag or the unique identifier of the project                    |
| tags<mark style="color:red;">\*</mark>              | CanonicalTag\[] | List of [CanonicalTag](#canonicaltag-object) objects to delete                                      |
| groupName                                           | String          | Name of the group that owns the project (only required if projectIdentifier is a string and not id) |

{% tabs %}
{% tab title="200: OK " %}

```javascript
{
}
```

{% endtab %}
{% endtabs %}

## AttachedCanonicalTag Object

An attached canonical tag object describes the attachment of a canonical tag to some Instrument or Source

<table><thead><tr><th width="206.33333333333331">Attribute Name</th><th width="211">Type</th><th>Description</th></tr></thead><tbody><tr><td>tagType</td><td>String</td><td>What the canonical tag is attached to. Can be attached to either "Instrument" or "Source"</td></tr><tr><td>typeName</td><td>String</td><td>Name describing the type of canonical tag</td></tr><tr><td>domainEntityId</td><td>Integer</td><td>Unique id of the canonical tag</td></tr><tr><td>annotationId?</td><td>Integer</td><td>Unique id describing where the canonical tag is attached. e.g. the unique id of the instrument</td></tr><tr><td>sourceReferenceId?</td><td>Integer</td><td>Unique id describing where the canonical tag is attached. e.g. the unique id of the file</td></tr><tr><td>attributes</td><td><a href="/pages/-MR1mhs6Kumxrgzkeijp#canonicalannotation-object">CanonicalAnnotation</a>[]</td><td>Array of canonical annotations that comprise the canonical tag</td></tr><tr><td>createdBy</td><td>UserObject|Null</td><td>Object that consists of a id, email, and username associated with the person who assigned the tag </td></tr></tbody></table>

```json
{
  "tagType": "Instrument", 
  "typeName": "Airframe Inventory", 
  "domainEntityId": 39, 
  "annotationId": 402970, 
  "attributes": [
      {"name": "Make", "value": "Beech"}, {"name": "Model", "value": "C24R"}, {"name": "Serial Number", "value": "MC-453"}
  ],
  "createdBy": {
      "id": 15,
      "email": "tester@gmail.com",
      "usernname": "tester"
  }
}
```

## Attach a tag to an instrument

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/instrument-tag`

Attaches a canonical tag to an instrument.&#x20;

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                           | Type         | Description                                                |
| ---------------------------------------------- | ------------ | ---------------------------------------------------------- |
| instrumentId<mark style="color:red;">\*</mark> | Integer      | Unique identifier for the instrument you wish to attach to |
| tag<mark style="color:red;">\*</mark>          | CanonicalTag | [CanonicalTag](#canonicaltag-object) object to attach      |

{% tabs %}
{% tab title="201: Created Information about the AttachedCanonicalTag that was created" %}

```javascript
{
  "tagType": "Instrument",
  "typeName": "Airframe Tag",
  "domainEntityId": 235,
  "attributes": [
      {"name": "Make", "value": "Raytheon"}, 
      {"name": "Model", "value": "850XP"}, 
      {"name": "Serial Number", "value": "755"},
      {"name": "Internal ID", "value": 4501}
  ],
  "createdBy": {"id": 14, "email": "tester@gmail.com", "username": "tester"}
}
```

{% endtab %}
{% endtabs %}

## Unattach a tag from an instrument

<mark style="color:red;">`DELETE`</mark> `https://api.annolab.ai/v1/instrument-tag`

Removes a canonical tag attachment from an instrument

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                           | Type         | Description                                                |
| ---------------------------------------------- | ------------ | ---------------------------------------------------------- |
| instrumentId<mark style="color:red;">\*</mark> | Integer      | Unique identifier for the instrument you wish to attach to |
| tag<mark style="color:red;">\*</mark>          | CanonicalTag | [CanonicalTag](#canonicaltag-object) object to delete      |

{% tabs %}
{% tab title="204: No Content " %}

```javascript
{
    // Response
}
```

{% endtab %}
{% endtabs %}

## (Alternate) Unattach a tag from an instrument

<mark style="color:red;">`DELETE`</mark> `https://api.annolab.ai/v1/instrument-tag/{instrument_id}/{domain_entity_id}`

Alternative endpoint to unattach a tag from an instrument using the instrument id and domain entity id of the tag.

An instrument id is equivalent to the annotation id of a classification annotation.

#### Path Parameters

| Name                                             | Type    | Description                                                                                                                            |
| ------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| instrument\_id<mark style="color:red;">\*</mark> | Integer | The instrument\_id from which to unattach the tag. An instrument id is equivalent to the annotation id of a classification annotation. |
| domain\_entity\_id                               | Integer | The domain\_entity\_id of the canonical tag.                                                                                           |

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

{% tabs %}
{% tab title="200: OK The tag was unattached succesfully." %}

{% endtab %}

{% tab title="404: Not Found Either the tag or instrument do not exist, or the tag is not attached to that instrument." %}

{% endtab %}
{% endtabs %}

## Attach a tag to a source

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/source-tag`

Attaches a canonical tag to a source.

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                                | Type              | Description                                                                                                                         |
| --------------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| projectIdentifier<mark style="color:red;">\*</mark> | String \| Integer | Either the project name or id of the project containing the source. If passing the project name, groupName is a required parameter. |
| groupName                                           | String            | The name of the group which owns the project. Required when passing a project name.                                                 |
| directoryIdentifier                                 | String \| Integer | Name or id of the directory containing the source. Required when passing a source name.                                             |
| sourceIdentifier<mark style="color:red;">\*</mark>  | String \| Integer | Either the source file name or id of the source to attach the tag. If passing source name, directoryIdentifier is required.         |
| tag<mark style="color:red;">\*</mark>               | CanonicalTag      | [CanonicalTag](#canonicaltag-object) object to attach                                                                               |

{% tabs %}
{% tab title="201: Created Information about the newly created attachment" %}

```
{
  "tagType": "Source File",
  "typeName": "Airframe Tag",
  "domainEntityId": 235,
  "attributes": [
      {"name": "Make", "value": "Raytheon"}, 
      {"name": "Model", "value": "850XP"}, 
      {"name": "Serial Number", "value": "755"},
      {"name": "Internal ID", "value": 4501}
  ],
  "createdBy": {"id": 14, "email": "tester@gmail.com", "username": "tester"}
}
```

{% endtab %}
{% endtabs %}

## Unattach a tag from a source.

<mark style="color:red;">`DELETE`</mark> `https://api.annolab.ai/v1/source-tag`

Removes a canonical tag attachment from a source

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                                | Type              | Description                                                                                                                         |
| --------------------------------------------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| projectIdentifier<mark style="color:red;">\*</mark> | String \| Integer | Either the project name or id of the project containing the source. If passing the project name, groupName is a required parameter. |
| sourceIdentifier<mark style="color:red;">\*</mark>  | String \| Integer | Either the source file name or id of the source to attach the tag. If passing source name, directoryIdentifier is required.         |
| tag<mark style="color:red;">\*</mark>               | CanonicalTag      | [CanonicalTag](#canonicaltag-object) object to attach                                                                               |
| groupName                                           | String            | The name of the group which owns the project. Required when passing a project name.                                                 |
| directoryIdentifier                                 | String \| Integer | Name or id of the directory containing the source. Required when passing a source name.                                             |

{% tabs %}
{% tab title="201: Created " %}

{% endtab %}
{% endtabs %}

## (Alternate) Unattach a tag from a source

<mark style="color:red;">`DELETE`</mark> `https://api.annolab.ai/v1/source-tag/{source_id}/{domain_entity_id}`

Alternative endpoint to unattach a tag from a source using the source id and domain entity id of the tag.

#### Path Parameters

| Name               | Type    | Description                                           |
| ------------------ | ------- | ----------------------------------------------------- |
| source\_id         | Integer | Id of the source file from which to unattach the tag. |
| domain\_entity\_id | Integer | The domain\_entity\_id of the canonical tag.          |

#### Headers

| Name          | Type   | Description                                                                                                                                                         |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

{% tabs %}
{% tab title="200: OK The tag was successfully unattached from the source file." %}

{% endtab %}

{% tab title="404: Not Found Either the tag or source do not exist, or the tag is not attached to that source." %}

{% endtab %}
{% endtabs %}


# Instruments

Instruments are a special format produced by Export Instruments and Search Instruments

## Instrument Object

An object corresponding to one instrument (aka Sub-Document)

#### Attributes

<table><thead><tr><th width="198.33333333333331">Name</th><th width="159">Type</th><th>Description</th></tr></thead><tbody><tr><td>id</td><td>Integer</td><td>Unique id for this instrument</td></tr><tr><td>sourceReferenceId</td><td>Integer</td><td>Id of the file that contains the instrument</td></tr><tr><td>sourceName</td><td>String</td><td>Name of the file that contains the instrument</td></tr><tr><td>startPageNumber</td><td>Integer</td><td>Page where the instrument starts</td></tr><tr><td>endPageNumber</td><td>Integer</td><td>Page where the instrument ends</td></tr><tr><td>typeName</td><td>String</td><td>The instrument type (e.g. "Amendment")</td></tr><tr><td>canonicalTags</td><td><a href="/pages/ChNRBfs1yYB3MPtzchXd#canonical-tag-object">CanonicalTag</a>[]</td><td>Array of canonical tags associated with the Instrument</td></tr><tr><td>annotations</td><td><a href="/pages/-MR1mhs6Kumxrgzkeijp#annotation-object">Annotation</a>[]</td><td>Array of annotations that the instrument contains</td></tr><tr><td>reviewedBy</td><td>UserObject|null</td><td>User object consisting of id, email, and username for the person who last reviewed the instrument</td></tr><tr><td>reviewedAt</td><td>String</td><td>ISO DateTime object of the time which the instrument was last reviewed</td></tr></tbody></table>

```json
{
    'id': 402970, 
    'sourceReferenceId': 1921, 
    'sourceName': "Example_File.pdf", 
    'startPageNumber': 3, 
    'endPageNumber': 5, 
    'typeName': "Bill of Sale",
    'reviewedBy': null,
    'reviewedAt': null, 
    'canonicalTags': [
        {
            'tagType': "Instrument", 
            'typeName': "Airframe Inventory", 
            'domainEntityId': 39, 
            'annotationId': 402970, 
            'attributes': [
                {'name': "Make", 'value': "Beech"}, {'name': "Model", 'value': "C24R"}, {'name': "Serial Number", 'value': "MC-453"}
            ],
            'createdBy': {
                'id': 15,
                'email': "tester@gmail.com",
                'usernname': "tester"
            }
        }
    ], 
    'annotations': [
        {
            'annotationId': 403992,
            'sourceReferenceId': 1921, 
            'typeName': "Grantor", 
            'value': "Carsuo", 
            'pageNumber': 3, 
            'endPageNumber': null, 
            'offsets': [1321, 1326], 
            'textBounds': {'type': 'MultiPolygon', 'coordinates': [[[[0.565917551517487, 0.769474387168884], [0.609824299812317, 0.769511699676514], [0.609820425510406, 0.778583765029907], [0.565913617610931, 0.778546392917633], [0.565917551517487, 0.769474387168884]]]]}, 
            'imageBounds': null, 
            'createdBy': 5, 
            'updatedBy': null, 
            'confidence': 96.7900390625, 
            'score': 0.7074922025203705, 
            'layerId': 635, 
            'isReviewed': False, 
            'reviewedBy': null, 
            'reviewedAt': null, 
            'modelSourceId': 12, 
            'modelSource': "Party Name Extractor"
        }
    ]
}
```


# Relations

## Create Annotation Relation

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/relation/create`

Create a new relation between two annotations. If a relation of the type already exists between the two annotation ids, then the existing relation will be returned and a duplicate will not be created.

#### Headers

| Name          | Type   | Description                                                                                                                                                             |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p>Where you put your api key. Creating a project requires a key with "Write" permissions.<br><br><code>{"Authorization": "Api-key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name               | Type    | Description                                                                                                                                                  |
| ------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| annoTypeIdentifier | string  | Identifier for the annotation type  of the relation. Either the id or the unique name. Must be an annotation type with isRelation: true or request will fail |
| projectIdentifier  | string  | Identifier of the project containing the layer. Either the id or the unique name.                                                                            |
| successorId        | integer | id of the annotation that is the child of the relation                                                                                                       |
| predecessorId      | integer | id of the annotation that is the parent of the relation                                                                                                      |
| value              | string  | value of the annotation                                                                                                                                      |

{% tabs %}
{% tab title="200 Relation already exists" %}

```
{
  "id": 72,
  "successorId": 44,
  "predecessorId": 12,
  "typeName": "Coreference",
  "typeId": 112,
  "value": '',
 }
```

{% endtab %}

{% tab title="201 Relation was successfully created" %}

```
{
  "id": 72,
  "successorId": 44,
  "predecessorId": 12,
  "typeName": "Coreference",
  "typeId": 112,
  "value": '',
 }
```

{% endtab %}

{% tab title="400 Relation creation failed" %}

```
{
    "message": "Information about why creation failed"
}
```

{% endtab %}
{% endtabs %}

Examples of how to make a layer create request

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

relation = {
  'relationTypeName': 'Coreference',
  'projectIdentifier': 'New NER Project',
  'successorId': 112,
  'predecessorId': 141,
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/relation/create'

response = requests.post(url, headers=headers, json=relation)

print(response.json())
```

{% endtab %}
{% endtabs %}


# Annotation Layers

Annotation layers are containers for annotations and can be used to "version" annotations and experiment outputs.

## Create Annotation Layer

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/layer/create`

Create a new annotation layer for your project&#x20;

#### Headers

| Name          | Type   | Description                                                                                                                                                             |
| ------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p>Where you put your api key. Creating a project requires a key with "Write" permissions.<br><br><code>{"Authorization": "Api-key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name              | Type    | Description                                                                                                                                                            |
| ----------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| layerName         | string  | Name of the layer that will be created                                                                                                                                 |
| projectIdentifier | string  | Identifier of the project containing the layer. Either the id or the unique name.                                                                                      |
| isGold            | boolean | boolean for whether the layer being created is a "Gold Set" i.e. a layer with data that will be considered truth when compared against annotation or experiment layers |
| description       | string  | Name of the project you wish to create. Must be unique for your group                                                                                                  |

{% tabs %}
{% tab title="201 Project was successfully created" %}

```
{
    "projectName": "New NER Project",
    "projectId": 1,
    "layerName": "NER Gold",
    "id": 5,
    "isGold": true,
    "description": 'Use the NER Schema for this layer. Only "approved" annotations should be kept in this layer'
}
```

{% endtab %}

{% tab title="400 Project creation failed" %}

```
{
    "message": "Information about why creation failed"
}
```

{% endtab %}
{% endtabs %}

Examples of how to make a layer create request

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

layer = {
  'projectIdentifier': 'New NER Project',
  'layerName': 'NER Gold'
  'isGold': True,
  'description': 'Use the NER Schema for this layer. Only "approved" annotations should be kept in this layer'
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/layer/create'

response = requests.post(url, headers=headers, json=layer)

print(response.json())
```

{% endtab %}
{% endtabs %}


# Export Instruments

Export instrument level data so that you can consume the data in your own internal applications

## Export instruments and their data

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/export/instruments`

Export all information related to instruments that meet filter criteria. Can include annotation data, source files, and tags.

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                           | Type    | Description                                                                                                                                                                                                                                                                                                                                                              |
| ---------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| projectOwner<mark style="color:red;">\*</mark> | String  | Group Name that owns the project (viewable in "All Projects" page)                                                                                                                                                                                                                                                                                                       |
| projectName<mark style="color:red;">\*</mark>  | String  | Name of the project you wish to export from                                                                                                                                                                                                                                                                                                                              |
| tagFilter                                      | Object  | <p>Filter export to include/exclude instruments with tags of these types attached. Applies to instrument's source file tags as well.</p><p></p><p>These filters act as an "OR" condition, so specifying two tags means any instrument with either will be exported.<br><code>{"includeTypes": \["Airframe Inventory"], "excludeTypes": \["Engine Inventory"]}</code></p> |
| sourceFilter                                   | String  | Filters export to only those instruments that have a source file name equal to sourceFilter                                                                                                                                                                                                                                                                              |
| includeFiles                                   | Boolean | If true, splits each instrument into individual files for export                                                                                                                                                                                                                                                                                                         |

{% tabs %}
{% tab title="201: Created Export Request created. Response contains information on how to check status of export request" %}

```javascript
{
    'message': "Export Request Successful. To check export status make a GET request at exportStatusUrl in response body",
    'exportStatusUrl': "https://api.annolab.ai/v1/export/status/341",
    'exportJob': {'id': 341, 'status': "initialized", 'projectId': 148, 'isInstrumentsExport': true}
}
```

{% endtab %}
{% endtabs %}

This code shows how to request an instrument export, then download the export contents.

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

<pre class="language-python"><code class="lang-python">import requests
import time

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

exportRequestBody = {
  'projectOwner': 'Group Name owning project',
  'projectName': 'Example Project Name',
  'tagFilter': {
    'includeTypes': ["Airframe Inventory"],
    'excludeTypes': ["Engine Inventory"],
  },
  'sourceFilter': "Test_PDF.pdf",
  'includeFiles': True
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/export/instruments'

<strong>response = requests.post(url, headers=headers, json=exportRequestBody, stream=True)
</strong>
status_url = response.json()['exportStatusUrl']
export_status = response.json()['exportJob']['status']

if response.status_code == 201:
  while export_status not in ['finished', 'errored']:
    response = requests.get(status_url, headers=headers).json()
    print(response)
    export_status = response['status']
    if export_status not in ['finished', 'errored']:
      time.sleep(15)
  
  if export_status == 'finished':
    signed_url = response['downloadUrl']
    download_response = requests.get(signed_url, stream=True)
    export_file_name = 'example_export.zip'
    if download_response.status_code == 200:
      with open(export_file_name, 'wb') as f:
        for chunk in download_response.iter_content(1024):
          f.write(chunk)
    print("Export download finished see: ", export_file_name)
    
</code></pre>

{% endtab %}
{% endtabs %}

### Example Export Format

Once an export is completed, you will see a zip file on your file system

<figure><img src="/files/kyNgNTE12zCuKmS3whFs" alt=""><figcaption></figcaption></figure>

Opening the zip file will reveal one .json (jsonlines file) and a folder named pdfs (if you specified `includeFiles: true` in your export request)

<figure><img src="/files/Wz9idJHyvOtlP4BQScqQ" alt=""><figcaption><p>example_export.zip extracted</p></figcaption></figure>

Exported instrument pdfs will have a name of the form `<Instrument Type>_<page start>-<page end>_<instrument id>.pdf`

The  `instruments.json` file will contain json lines of [Instrument Objects](/annotations-and-relations/instruments#instrument-object)


# Export Project

Export projects so that you can train your own ML models

## Export Project Files

<mark style="color:green;">`POST`</mark> `https://api.annolab.ai/v1/export/project`

Export requested project details. Each element of the project will have its own "json lines" file and be included in a zip file package.

#### Headers

| Name          | Type   | Description                                                                                                                                                         |
| ------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization | string | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                                | Type            | Description                                                                                                              |
| --------------------------------------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------ |
| includeTextBounds                                   | boolean         | boolean of whether you want x,y text bounds of text of any pdfs in project                                               |
| annotationLayerIds                                  | array           | Array of layer ids that you wish to export. defaults to all layers                                                       |
| includeSources                                      | boolean         | boolean of whether you want source files to be include with the export. defaults to false                                |
| annotationLayerNames                                | array           | Array of strings containing the names of annotation layers you wish to be included in the export. defaults to all layers |
| projectIdentifier<mark style="color:red;">\*</mark> | string\|integer | Identifier for the project that will contain the annotation type. Either the id or the unique name.                      |
| includeAnnotationTypes                              | boolean         | Boolean to include annotation types with export. Defaults to false                                                       |
| sourceIds                                           | array           | array of source ids to export within the project                                                                         |

{% tabs %}
{% tab title="200 Export was generated successfully. content will be a zip file containing up to 6 json lines files and sub folders for each directory (if includeSources=True) |-------- <projectName>.annotations.jsonl|-------- <projectName>.atntypes.jsonl|-------- <projectName>.layers.jsonl|-------- <projectname>.relations.jsonl|-------- <projectName>.sources.jsonl" %}

```
{
    headers: {
        'Content-Type': 'application/zip',
        'Content-Disposition': `attachment; filename=New Ner Project.zip`
    }
    content: <byte-stream>
}
```

{% endtab %}
{% endtabs %}

This code shows how to request a project export

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

```python
import requests

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

exportRequestBody = {
  'projectIdentifier': 'New NER Project',
  'includeSources': True,
  'includeAnnotationTypes': True,
  'includeTestBounds': False
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/export/project'

response = requests.post(url, headers=headers, json=exportRequestBody, stream=True)

if r.status_code == 200:
  d = r.headers['content-disposition']
  fileName = re.findall("filename=(.+)", d)[0]
  with open(fileName, 'wb') as f:
    for chunk in r.iter_content(1024):
      f.write(chunk)
```

{% endtab %}
{% endtabs %}


# Search Instruments

Search a project for instruments and annotations that match the search criteria

## Search instruments and their data

<mark style="color:blue;">`GET`</mark> `https://api.annolab.ai/v1/instrument/search`

Search a project for information related to instruments that meet search filter criteria. Returns a maximum of 100 instruments and their annotations per page. \
\
If you need individual pdf files exported for each instrument, try using the [Export Instruments api](/exports/export-instruments)

#### Headers

| Name                                            | Type   | Description                                                                                                                                                         |
| ----------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Authorization<mark style="color:red;">\*</mark> | String | <p>Where you put your api key. Exporting a project requires a key with "Read" permissions.<br><code>{"Authorization": "Api-Key XXXXXXX-XXXXXXX-XXXXXXX"}</code></p> |

#### Request Body

| Name                                           | Type    | Description                                                                                                                                                                                                                                                                                                                                                        |
| ---------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| projectOwner<mark style="color:red;">\*</mark> | String  | Group Name that owns the project (viewable in "All Projects" page)                                                                                                                                                                                                                                                                                                 |
| projectName<mark style="color:red;">\*</mark>  | String  | Name of the Project where you want to search                                                                                                                                                                                                                                                                                                                       |
| tagFilter                                      | Object  | <p>Filter search to include/exclude instruments with tags of these types attached. Applies to instrument's source file tags as well.<br><br>These filters act as an "OR" condition, so specifying two tags means any instrument with either will be returned.<br><code>{"includeTypes": \["Airframe Inventory"], "excludeTypes": \["Engine Inventory"]}</code></p> |
| sourceFilter                                   | String  | Filters export to only those instruments that have a source file name equal to sourceFilter                                                                                                                                                                                                                                                                        |
| page                                           | Integer | Search result pagination number                                                                                                                                                                                                                                                                                                                                    |

{% tabs %}
{% tab title="201: Created Your search result (100 instruments at a time)" %}

```javascript
{
    'page': 1,
    'hasMorePages': false,
    'results': []
}
```

{% endtab %}
{% endtabs %}

## Search Result Object

| Attribute Name | Type                                                                      | Description                                                          |
| -------------- | ------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| page           | Integer                                                                   | The page of the search result                                        |
| hasMorePages   | Boolean                                                                   | Whether the search result has additional pages that can be requested |
| results        | [Instrument](/annotations-and-relations/instruments#instrument-object)\[] | Array of Instrument objects that comprise the search result          |

```json
{ 
    'page': 1, 
    'hasMorePages': false, 
    'results': []
}
```

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

```python
import requests
import time

ANNO_LAB_API_KEY = 'XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX'

searchBody = {
  'projectOwner': 'Group Name owning project',
  'projectName': 'Example Project Name',
  'tagFilter': {
    "includeTypes": ["Airframe Inventory"],
    "excludeTypes": ["Engine Inventory"]}
  },
  'sourceFilter': "Test_PDF.pdf"
}

headers = {
  'Authorization': 'Api-Key '+ANNO_LAB_API_KEY,
}

url = 'https://api.annolab.ai/v1/instrument/search'

response = requests.post(url, headers=headers, json=searchBody, stream=True).json()

search_result = response['results']
#Do something with search result here

#Continue paging your search until there are no more pages 
#(only 100 instruments returned per page)
while response['hasMorePages']:
  searchBody['page'] = response['page'] + 1
  response = requests.get(url, headers=headers, json=searchBody, stream=True).json()
  search_result = response['results']
  #Do something with search result here
  

```

{% endtab %}
{% endtabs %}


# Abstracts

Abstracts are an ordered collection of instruments and typically represent a title summary.

### Abstract Object

#### Attributes

| Name        | Type                                                                              | Description                                               |
| ----------- | --------------------------------------------------------------------------------- | --------------------------------------------------------- |
| id          | Integer                                                                           | Unique id of the abstract                                 |
| key         | String                                                                            | A unique key for the abstract                             |
| tags        | [CanonicalTag](/annotations-and-relations/canonical-tags#canonical-tag-object)\[] | Tags associated with this abtract.                        |
| instruments | [AbstractInstrument](#abstract-instrument-object)\[]                              | Instruments in this abstract                              |
| projectId   | Integer                                                                           | Id of the abstract's project                              |
| createdAt   | String                                                                            | ISO formatted DateTime when the abstract was created      |
| updatedAt   | String                                                                            | ISO formatted DateTime when the abstract was last updated |
| createdBy   | UserObject\|null                                                                  | Original creator of the abstract                          |
| updatedBy   | UserObject\|null                                                                  | Last user who updated the abstract                        |

### Abstract Instrument Object


