API tutorial (managed platform)

  • Updated

This page explains how to use the managed platform REST API to get digital assets such as videos, images, and NER corpus documents into the Alegion platform, create annotation tasks, and retrieve results.  

This tutorial explains how to use the API during the lifecycle of a labeling project. If you're already familiar, visit the endpoint documentation for details about each call's parameters, return types, error codes, etc.

Command examples here are for the cURL command line utility. 

 

Terminology

An "asset" is the video, image, or NER corpus document you want annotated.  Most annotation tasks involve an asset, though this is not necessarily the case (see "compound/general tasks").

A "workflow" in the Alegion platform contains all the steps and settings used to annotate your source data. It includes task designs, classification lists, and quality control configurations associated with a project. (For more detail, see the tailored workflows section.)

"Batches" are arbitrary collections of input records, as well as the annotations that get attached. Batches belong to one (and only one) workflow. Our customer success team can provide guidance on batching strategy to optimize for traceability, quality control and delivery.

An "input record" tracks the journey of an asset, in a batch, through a workflow, to produce an annotation result.

 

Getting Started

Working closely with you, Alegion customer success creates a workflow to fit your use case and accuracy requirements, then provides you the unique ID to use in API calls.  They will also provide you with API access credentials.
The API is located at https://api.alegion.com/v1
 

After setup, the lifecycle of a project is:

  1. You upload assets.
  2. You create a batch within your workflow.
  3. You create input records in the batch for those assets.
  4. Labelers work the resulting tasks.
  5. You download results using various optional criteria, including batch ID.

All of these steps can go on continuously, in parallel. For instance, results can be retrieved while labeling is ongoing, and new input records can be added at any time.

 

The first section below covers the common API operations performed in that lifecycle. The second section covers some useful but less frequent operations.

A full round trip

Let's authenticate, upload assets, create a batch, create records, and get the results.

Note

Your API key needs to be sent in the x-api-key header for every request, including /login.

Authentication

Authenticate by sending a POST request to the /login endpoint. Retrieve the access_token from the response body for use in an Authorization header in all subsequent requests.

Example request

curl -X POST 'https://api.alegion.com/v1/login' \
   -H 'x-api-key: {your-api-key}' \
   -H 'Content-Type: application/json' \
   -H 'cache-control: no-cache' \
   --data-raw '{
       "username": "{your-username}",
       "password": "{your-password}"
   }'

Example response

{
    "access_token": "access_token",
    "expires_in": 3600,
    "token_type": "bearer"
}

Token expiration

Access tokens have a defined lifespan, and requests made using an expired token will fail with an HTTP 401 error. Simply make the authentication request again and use the new access token in all subsequent requests.

 

Tip

Reusing a token is optional. You can make an authorization request for every new transaction in order to avoid dealing with expiration.

Uploading Assets

Because assets tend to be large, part of the upload work has been outsourced directly to our cloud storage provider.  Therefore, each asset upload requires several API calls. From a high level, the steps to getting an asset into the Alegion platform are as follows:

  • Register asset
  • Open upload session
  • Upload image or video file
  • Close upload session

 

Register the asset

First, provide some metadata about your asset

Example request

curl -X POST 'https://api.alegion.com/v1/assets' \
   -H 'Content-Type: application/json' \
   -H 'x-api-key: {your-api-key}' \   
   -H 'authorization: Bearer {access_token}' \
   --data-raw '{
      "name": "cars-1900 from api",
      "fileName": "cars-1900.mp4",
      "fps": 25,
      "frameCount": 1500,
      "type": "video"
}'

Example response

{
    "id": "c226197c-17c5-4cc6-9529-0098ae771148",
    "name": "cars-1900 from api",
    "fileName": "cars-1900.mp4",
    "status": "uploading",
    "source": "file",
    "type": "video",
    "createdAt": "2021-08-27T21:44:49.866238252Z",
}

The response contains the asset id, which you will use in subsequent calls related to this asset.  Note that the current status of the asset is uploading.

Create an asset upload session

Example request

curl -X POST 'https://api.alegion.com/v1/assets/{assetId}/upload' \
   -H 'x-api-key: {your-api-key}' \   
   -H 'authorization: Bearer {access_token}''
   }'

Example response

{
    "url": "https://cdn.app.alegion.com/tenant-assets/vandelay-industries/c226197c-17c5-4cc6-9529-0098ae771148?Policy=eyJTdGF0ZW1lbnQiOiBbeyJSZXNvdXJjZSI6Imh0dHBzOi8vY2RuLmFwcC5hbGVnaW9uLmNvbS90ZW5hbnQtYXNzZXRzL3ZhbmRlbGF5LWluZHVzdHJpZXMvYzIyNjE5N2MtMTdjNS00Y2M2LTk1MjktMDA5OGFlNzcxMTQ4IiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNjMwMTA0NjkyfX19XX0_&Signature=DpfMk3Vs~rJ5GLYOR4k3doaWCC5ajuFb1NbzADDazYlDPYcE9FvluZQoYkW6heWvNWJjHmHMVCFrvonTvSCRFBNJASmu37AwFk-rNkmSfRoro7nNlSrwPVlT9pgAQAMckds0pOIhNUQNibS5Jk-UDSxl8KZ8cfAIyr3jwtYVyd8R9ncHNc7w9PyOZlI8VpMmwe6YpKxfb4-8vTNTF8qzxVHTUPyAIsiS3dbIwzdx0gaRie8QN5EYYaXyGOkOd6wGQTeprka2Rmm~BC8zetWCSNudD1fzQ1sg~9-Nd9DYJQ6zgwSbSM1TrIETUMe2X9ZiwHLJZzfqSGcvCVTXHFlzJQ__&Key-Pair-Id=APKAJDMX44Y7WWY2FGYQ"
}
 

Note

The response contains a signed url. This a secure, private, pre-authorized url directly into our cloud storage provider, where you can upload the asset file. The signed url is also temporary - it expires after 60 minutes.

 

Upload the asset

Upload the asset file to the signed url using PUT. Note that because the signed url is pre-authorized, you don't need to include the x-api-key nor authorization headers in your request.

Example request

curl -v --upload-file cars-1900.mp4 'https://cdn.app.alegion.com/tenant-assets/vandelay-industries/c226197c-17c5-4cc6-9529-0098ae771148?Policy=eyJTdGF0ZW1lbnQiOiBbeyJSZXNvdXJjZSI6Imh0dHBzOi8vY2RuLmFwcC5hbGVnaW9uLmNvbS90ZW5hbnQtYXNzZXRzL3ZhbmRlbGF5LWluZHVzdHJpZXMvYzIyNjE5N2MtMTdjNS00Y2M2LTk1MjktMDA5OGFlNzcxMTQ4IiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNjMwMTA0NjkyfX19XX0_&Signature=DpfMk3Vs~rJ5GLYOR4k3doaWCC5ajuFb1NbzADDazYlDPYcE9FvluZQoYkW6heWvNWJjHmHMVCFrvonTvSCRFBNJASmu37AwFk-rNkmSfRoro7nNlSrwPVlT9pgAQAMckds0pOIhNUQNibS5Jk-UDSxl8KZ8cfAIyr3jwtYVyd8R9ncHNc7w9PyOZlI8VpMmwe6YpKxfb4-8vTNTF8qzxVHTUPyAIsiS3dbIwzdx0gaRie8QN5EYYaXyGOkOd6wGQTeprka2Rmm~BC8zetWCSNudD1fzQ1sg~9-Nd9DYJQ6zgwSbSM1TrIETUMe2X9ZiwHLJZzfqSGcvCVTXHFlzJQ__&Key-Pair-Id=APKAJDMX44Y7WWY2FGYQ'

Example response


< HTTP/2 200
< content-length: 0
< date: Fri, 27 Aug 2021 22:03:47 GMT
< etag: "d1dc268ff709a0b47b21cea0a38a59b4"
< server: AmazonS3
< x-cache: Miss from cloudfront
< via: 1.1 7f5e0d3b9ea85d0d75063a66c0ebc841.cloudfront.net (CloudFront)
< x-amz-cf-pop: HIO50-C1
< x-amz-cf-id: b2OAQzlfPTynZca9wV2I6uXnoJCCNlilSNYiTUmNZE3q3YDT3kKpvA==

HTTP 200 response code indicates success.

Close the upload session

Example request

curl -X DELETE 'https://api.alegion.com/v1/assets/{assetId}/upload' \
   -H 'x-api-key: {your-api-key}' \   
   -H 'authorization: Bearer {access_token}'

HTTP 204 response code indicates success.

Creating a batch

You can create a batch using the /workflows/{workflowId}/batches endpoint.

Example request

curl -X POST \
   https://api.alegion.com/v1/workflows/{workflowId}/batches \
   -H 'x-api-key: {your-api-key}' \
   -H 'authorization: Bearer {access_token}' \
   -H 'content-type: application/json' \
   -H 'accept: application/json' \
   --data-raw '{
         "name": "Batch Name",
         "isEnabled": false
       }'

Note

The appropriate value for isEnabled varies by use case.  Please contact your Alegion customer success manager for guidance.

Example response

{
  "id": "739b1978-cb5b-4188-9d1d-37a394d67f5a",
  "name": "Batch Name",
  "workflowId": "dac402db-b594-4f44-a2c7-87a535cf26f9",
  "priority": "normal",
  "isEnabled": false,
  "createdAt": "2019-03-25T19:45:47.275Z"
}

Note the batch id for use in subsequent calls

Creating input records for assets

Once your assets have been uploaded and your batch is created, you can create input records to send those assets through your annotation workflow.

Example request

curl -X POST 'https://api.alegion.com/v1/batches/{batchId}/records/assets' \
   -H 'x-api-key: {your-api-key}' \
   -H 'authorization: Bearer {access_token}' \
   -H 'Content-Type: application/json' \
   --data-raw '{
    "assetIds": [
        "{assetId}"
    ]
}'
 

Upload limit

This endpoint has a limit of 1,000 asset ids per request. Attempting to send more than 1,000 asset ids in a single request will result in an HTTP 422 Unprocessable Entity error.

Example response

{
    "created": [
        {
            "id": "f56e9c6c-5058-4c89-b150-b997530823ee",
            "assetId": "c226197c-17c5-4cc6-9529-0098ae771148"
        }
    ],
    "assetValidationErrors": []
}

If you get a HTTP 201 Created success response as shown above, your tasks are in the batch and are ready to be worked. You do not need to query the batch.

 

Retrieving results

Some details of retrieving results vary by use case. Please contact your Alegion customer success manager for guidance.

Selecting results to export 

Use the /exports/workflows/{workflowId}/results endpoint to list results for a workflow. Results will be paginated.  

Example request

curl -X GET \
  https://api.alegion.com/v1/exports/workflows/{workflowId}/results?batchIds={batchIds} \
   -H 'x-api-key: {your-api-key}' \
   -H 'authorization: Bearer {access_token}'

 

Example response

[{
  "id": "3fad5acd-3466-49f5-baec-6fe45eb845c3",
  "workflowId": "4cf60bf4-7092-4cfe-b7b8-e17f6674663d",
  "batchId": "e8a530d4-9490-424c-99ee-8cf1cc79cd54",
  "inputRecordId": "7ab3632c-7007-4a37-8821-873ecb474484",
  "createdAt": "2021-01-22T15:49:10.722Z",
  "iteration": 0
}]


Create an export

Use the /exports/record-result-exports endpoint to kick off export generation. 

There are two export formats to choose from: zip and json. We recommend using the ZIP format. 

ZIP Using zip filetype generates a zip file containing a directory per record result named <record-result-id>. In each record result directory, a json named <asset-name>.json containing the single record result and the asset named <asset-name>.<extension> . Example POST body:

{
    "fileType": "zip",
    "filename": "export-example.zip",
    "workflowId": "4cf60bf4-7092-4cfe-b7b8-e17f6674663d"
 }


JSON Using json fileType generates a json file containing array of results. We recommend naming the file with a .gz suffix to generate a gzipped export. Example POST body:

{
    "fileType": "json",
    "filename": "export-example.json.gz",
    "workflowId": "4cf60bf4-7092-4cfe-b7b8-e17f6674663d"
 }

 

Example request

curl -X POST \
  https://api.alegion.com/v1/exports/record-result-exports \
   -H 'x-api-key: {your-api-key}' \
   -H 'authorization: Bearer {access_token}' \
-H 'Content-Type: application/json' \ --data-raw '{ "fileType": "zip", "filename": "export-example.zip", "workflowId": "4cf60bf4-7092-4cfe-b7b8-e17f6674663d", "minCreatedAt": "2021-01-01T00:00:00Z" }'

Note the use of minCreatedAt to filter the results to be included in the new export.  Using the createdAt value for your previous export in conjunction with the minCreatedAt field in the POST body when creating a new export, you can build an export containing only the results that have been finalized since your last generated export. See the full endpoint documentation for more parameters that can be used for filtering the desired results for your export.

Example response

{
    "id": "ec02f767-66cb-4115-b530-82b9aa624217",
    "status": "in-progress",
    "filename": "export-example.zip",
    "fileType": "zip",
    "recordResultCount": 1,
    "workflowId": "4cf60bf4-7092-4cfe-b7b8-e17f6674663d",
    "createdAt": "2021-08-27T21:43:01.708946361Z",
    "createdBy": "e01fbbea-6cdd-4b25-9e4e-8e0cfda75b5f",
    "s3Path": "s3://app-dev-secure-media/domain-object/record-result-export/ec02f767-66cb-4115-b530-82b9aa624217/export-example.zip"
}

 

Wait for the export to assume a ‘ready’ status

Use the /exports/record-result-exports/{exportId} endpoint to get the export. It will be ready to download once it has assumed the ‘ready’ status.

Example request

curl -X GET https://api.alegion.com/v1/exports/record-result-exports/{exportId} \
   -H 'x-api-key: {your-api-key}' \
   -H 'authorization: Bearer {access_token}'

 

Example response

{
    "id": "ec02f767-66cb-4115-b530-82b9aa624217",
    "status": "ready",
    "filename": "export-example.zip",
    "fileType": "zip",
    "recordResultCount": 1,
    "workflowId": "4cf60bf4-7092-4cfe-b7b8-e17f6674663d",
    "createdAt": "2021-08-27T21:43:01.708946Z",
    "createdBy": "e01fbbea-6cdd-4b25-9e4e-8e0cfda75b5f",
    "s3Path": "s3://app-dev-secure-media/domain-object/record-result-export/ec02f767-66cb-4115-b530-82b9aa624217/export-example.zip"
}

 

Use the /exports/record-result-exports/{exportId}/download endpoint to get the export. When the export is in the ‘ready’ (or ‘downloaded’), get the signed url for the export.


Example request

curl -i
-X GET https://api.alegion.com/v1/exports/record-result-exports/{exportId}/download \ -H 'x-api-key: {your-api-key}' \ -H 'authorization: Bearer {access_token}' | sed -En 's/^location: (.*)\r$/\1/p'


The signed url will live in the location header of the response and will expire after 10 seconds. Get the export using the signed url. The -i parameter to curl makes it display the response headers.  The sed command extracts the location header value.

Example request

curl -o export-example.zip "{signed-url}"

It is important to put the signed url in quotes, because it contains characters that will be interpreted by the shell otherwise.

 

About pagination

Some API responses are large enough that it makes sense to paginate them. Any paginated response will provide a Link header and a X-Total-Count header and will accept pagination related paramaters in the query string.

Pagination request parameters

  • page: Which page number to return
  • pageSize: How many records per page
  • sort: -createdAt or +createdAt, to sort by createdAt descending or ascending, respectively

Example pagination response headers: Link and X-Total-Count

Link: <https://api.alegion.com/v1/batches/{batchId}/records?page=1&pageSize=20&sort=-createdAt>;rel="first",
    <https://api.alegion.com/v1/batches/{batchId}/records?page=1&pageSize=20&sort=-createdAt>;rel="prev",
    <https://api.alegion.com/v1/batches/{batchId}/records?page=3&pageSize=20&sort=-createdAt>;rel="next",
    <https://api.alegion.com/v1/batches/{batchId}/records?page=3&pageSize=20&sort=-createdAt>;rel="last"
X-Total-Count: 42

 

Checking for doneness

Alegion does not have a "callback" mechanism for notifications when a batch is "ready for pickup". This is for two reasons:

  • Batches don't have a defined end as explained above.
  • Alegion is platform-agnostic with respect to the client calling our API, and any single mechanism (e.g. webhooks) would not in practice work for a substantial portion of our customers.

However, it is trivial to call the results endpoint with pagination parameters of page=1 and pageSize=1, then read the X-Total-Count response header to see how many results are available. Provided your system keeps track of how many records were sent into the batch, you'll know when it's complete.

But: There are two other task states that are considered "final" but are not returned by the results endpoint: exception and canceled. These need to be counted separately. Read on for the explanation of these exception state, and the way to retrieve the exception count.

 

Other calls and concepts

Filtering results

You can filter results using the following parameters.

  • minCreatedAt: to exclude results finalized before this datetime
  • maxCreatedAt: to exclude results finalized after this datetime

Note, these might live in the POST body or as query parameters. Please check the API documentation for the endpoint you are using.

Example

Suppose your system knows the last time it requested results from a batch. To query for only new results that became final after that, use minCreatedAt:

curl -X GET \
https://api.alegion.com/v1/batches/{batchId}/results?minCreatedAt=2020-01-01T10:00:00.000Z \
   -H 'x-api-key: {your-api-key}' \
   -H 'authorization: Bearer {access_token}'

 

Common errors

Malformed Batch ID

Sending a seriously malformed batch ID will return an HTTP 422 with the following body:

{
    "message": "Failed to convert value of type 'java.lang.String' to required type 'java.util.UUID'; nested exception is java.lang.IllegalArgumentException: Invalid UUID string: {batch_id}"
}

Missing, Incorrect, or Expired Token

Any sort of problem with your access token will return an HTTP 401 error with an empty body.

Missing or Incorrect API key

If the x-api-key header is not sent properly, HTTP 403will be returned.

Uploading input records for non-Asset-based workflows

This section shows how to encode an input record using JSON.

Each input record has this structure:

  • a data member containing
    • a list of key-value pairs where
      • the key is a fieldname determined by the task design
      • the value is displayed to the labeler
  • metadata (optional): any string:
    When used, metadata will be associated with that input record throughout its lifetime. Use it to attach context to a record to track it as it moves through the Alegion platform. For instance, you can use it to store the record's corresponding unique ID in your database.
 

Warning

metadata is a reserved word and must be a sibling to the input record data field, not a child of data

Valid:

[
  {
    "data": {
      "input_fieldname": "this is my value"
    },
    "metadata": "external_ID"
  }
]

Invalid:

[
  {
    "data": {
      "input_fieldname": "this is my value",
      "metadata": "external_ID"
    }
  }
]

Use the /batches/{batchId}/records/import endpoint to bulk load JSON input records into your batch. The request body is an array of single input records.

 

Example request

curl -X POST https://api.alegion.com/v1/batches/{batchId}/records/import \
   -H 'x-api-key: {your-api-key}' \
   -H 'authorization: Bearer {access_token}' \
   -H 'content-type: application/json' \
   --data-raw '[
    {
        "data": {
            "input_fieldname_1": "this is my value on record 1",
            "input_fieldname_2": "another field value on record 1"
        },
        "metadata": "sample_metadata"
    },
    {
        "data": {
            "input_fieldname_1": "this is my value on record 2",
            "input_fieldname_2": "another field value on record 2"
        },
        "metadata": "more_sample_metadata"
    }
]'

 

Example response

[
    {
        "id": "309ec5c5-6589-47fc-bd3d-c5b4edeb5d57",
        "data": {
            "input_fieldname_1": "this is my value on record 1",
            "input_fieldname_2": "another field value on record 1"
        },
        "metadata": "sample_metadata"
        "createdAt": "2019-11-15T14:26:17.661Z",
        "workflowStageId": "string",
        "status": "queued"
    },
    {
        "id": "83224129-b65f-4533-8f06-d25333a21759",
        "data": {
            "input_fieldname_1": "this is my value on record 2",
            "input_fieldname_2": "another field value on record 2"
        },
        "metadata": "more_sample_metadata"
        "createdAt": "2019-11-15T14:26:17.661Z",
        "workflowStageId": "string",
        "status": "queued"
    }
]

If you get a success response as shown above, your tasks are in the batch and are ready to be worked. You do not need to query the batch.

 

Upload limit

The import endpoints currently limit imports to 1,000 records per request. Attempting to send more than 1,000 records in a single request will result in an HTTP 422 Unprocessable Entity error.

 

Listing your workflows

To retrieve an array of all workflows in your account, use the /workflows endpoint. Results will be paginated.

Example request

curl -X GET https://api.alegion.com/v1/workflows \
      -H 'x-api-key: {your-api-key}' \
      -H 'Authorization: Bearer {access_token}'

Example response

[
  {
    "id": "dac402db-b594-4f44-a2c7-87a535cf26f9",
    "name": "Workflow name",
    "description": "Workflow description",
    "isActive": true,
    "isVisible": true,
    "isArchived": false,
    "createdAt": "2018-09-26T18:35:38.188Z",
    "isLimitWorkerToOncePerInputRecord": false
  }
]

 

Listing batches within a workflow

To retrieve an array of all batches for a given workflow, use the /workflows/{workflowId}/batches endpoint. Results will be paginated.  Input record counts by status will also be rolled up in the response.  In the example below, there are 2 complete input records and none in any other status.

Example request

curl -X GET \
  https://api.alegion.com/v1/workflows/{workflowId}/batches \
   -H 'x-api-key: {your-api-key}' \
   -H 'Authorization: Bearer {access_token}'

Example response

[
   {
"id": "6ca34705-239c-424c-9b8e-1fd44ad0f0e8",
"name": "Batch Name",
"workflowId": "dadc6d1e-9fb3-4e74-9285-0ad01a27b373",
"priority": "normal",
"isEnabled": true,
"createdAt": "2021-07-13 22:12:49.504323+00",
"complete": 2,
"inProgress": 0,
"queued": 0,
"archived": 0,
"archiving": 0,
"adminReview": 0,
"content": 0,
"exceptions": 0,
"canceled": 0,
"publishedForReview": false,
"status": "Active"
}
]

 

Get metadata about a batch

Use a GET to the /batches/{batchId} endpoint to retrieve metadata about a batch. Note that this returns the properties of a batch as a container object, and does not return information about the input records, batch status, or results.

Example request

curl -X GET https://api.alegion.com/v1/batches/{batchId} \
   -H 'x-api-key: {your-api-key}' \
   -H 'Authorization: Bearer {access_token}'

Example response

{
      "id": "3c9fa471-882b-4d92-82d4-ece202606ba6",
      "name": "Batch Name",
      "workflowId": "dac402db-b594-4f44-a2c7-87a535cf26f9",
      "isEnabled": true,
      "createdAt": "2019-03-26T17:47:03.399Z"
}

 

List a batch's input records

Use the /batches/{batchId}/records endpoint to retrieve input records belonging to a batch. Results will be paginated.

Example request

curl -X GET \
  https://api.alegion.com/v1/batches/{batchId}/records \
-H 'x-api-key: {your-api-key}' \ -H 'authorization: Bearer {access_token}'

Example response

[
    {
        "id": "046b6c7f-0b8a-43b9-b35d-6489e6daee91",
        "createdAt": "2017-11-14T21:02:36.491Z",
        "metadata": "aeiou",
        "data": "aeiou",
        "workflowStageId": "046b6c7f-0b8a-43b9-b35d-6489e6daee91",
        "status": "in-progress"
    }
]

 

Task exceptions

"Exception" has a special meaning in Alegion, specifically with regard to tasks. (Consider it an overloaded term, unrelated to how programmers normally use the word.)

Labelers report a task exception when for whatever reason a task cannot be worked, for instance when an image fails to render. Task exceptions go into a special queue for review. If the situation was temporary (e.g. permissions that expire on an S3 bucket, "internet weather"), those tasks can be restarted and proceed normally, eventually appearing in the final results.

However, if the situation was not temporary (e.g. a bad filename in the input data), the tasks can be canceled, in which case they will not appear in the final results. (Tasks can be canceled for other administrative reasons as well.)

This is an intentional and constructive task design pattern, and depending on your use case, there are other ways to employ exceptions usefully. (Alegion's customer success team will guide you in this.)

Counting exceptions and canceled tasks

To complete the picture of batch status described above, combine the count from the results endpoint with the count of exception and canceled tasks from the records endpoint with these specific query parameters:

  • status=exception,canceled
  • page=1
  • pageSize=1

 

 
Share This