# REST API

If you can't use our client library, you can still integrate your Ikomia SCALE deployment through the REST API.

The general workflow is as follows:

* You retrieve a project-wide token for calling your deployment from Ikomia SCALE.
* You queue a new run with your input data and parameters.
* You regularly poll for the status of the run until it completes.
* When the run is complete, the deployment returns the serialized run results.

<!-- -->

## Authentication[​](#authentication "Direct link to Authentication")

To authenticate with the Ikomia SCALE REST API, you need to provide your API token in the `Authorization` header of your requests. The token should be prefixed with `Token `.

```
curl --request GET \
  --url 'https://scale.ikomia.ai/v1/projects/jwt/?endpoint=your.scale.endpoint.url' \
  --header 'Authorization: Token YOUR_API_TOKEN'
```

Replace `your.scale.endpoint.url` with the URL of your Ikomia SCALE deployment and `YOUR_API_TOKEN` with your actual API token.

This will returns a JSON object of the following format:

```
{
  "access_token": "...",
  "expires_in": 36000,
  "token_type": "Bearer",
  "scope": "openid consume",
  "refresh_token": "...",
  "id_token": "..."
}
```

The `id_token` is the JWT you will need to use to authenticate with your deployment.

warning

The `id_token` is a sensitive piece of information. Keep it secure and do not expose it in client-side code.

info

This token can also be used to interact with your project storage space. **To enable full read/write access to storage with your JWT, add the `storage=true` query param to the token request URL**:

```
curl --request GET \
  --url 'https://scale.ikomia.ai/v1/projects/jwt/?storage=true&endpoint=your.scale.endpoint.url' \
  --header 'Authorization: Token YOUR_API_TOKEN'
```

You can then pass the JWT (`id_token`) as a `Bearer` token in the `Authorization` header of [your requests to the storage API](https://scalefs.ikomia.ai/docs).

## Running a deployment[​](#running-a-deployment "Direct link to Running a deployment")

To run a deployment, you need to send a `PUT` request to the `/api/run` endpoint. The body of the request should be a JSON object with the following properties:

* `inputs`: an array of objects representing the input data of the deployment
* `outputs`: the list of workflow tasks for which you want to retrieve outputs
* `parameters`: for each of the workflow tasks, you can overrides the default parameters of the workflow if needed.

```
curl --request PUT \
  --url 'https://your.scale.endpoint.url/api/run?advice=true' \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer YOUR_JWT' \
  --data-raw '{
    "inputs": [
      {
        "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/2wBDAQ..."
      }
    ],
    "outputs": [
      {
        "task_name": "infer_yolo_v8"
      }
    ],
    "parameters": [
      {
        "task_name": "infer_yolo_v8",
        "parameters": {
          "conf_thres": "0.5"
        }
      }
    ]
  }'
```

note

**This documentation covers only the responses formats when `advice=true` query parameter is set in the request.** We recommend always using this option to get the most detailed responses from the API.

### Inputs[​](#inputs "Direct link to Inputs")

Currently, deployments only accept images and videos as inputs. Images can be sent as Base64 encoded strings or uploaded to your project's storage, while videos must be uploaded to your project's storage.

#### Images as Base64[​](#images-as-base64 "Direct link to Images as Base64")

Just format your input object in the following format:

```
{
  "image": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAIBAQEBAQIBAQECAgICAgQDAgICAgUEBAMEBgUGBgYFBgYGBwkIBgcJBwYGCAsICQoKCgoKBggLDAsKDAkKCgr/2wBDAQ..."
}
```

#### Images/Videos as file upload[​](#imagesvideos-as-file-upload "Direct link to Images/Videos as file upload")

First, upload your image or video file to your project's storage space using the [SCALE Storage API](https://scalefs.ikomia.ai/docs):

```
curl --request 'POST' \
  --url 'https://scalefs.ikomia.ai/v1/objects/' \
  --header 'Content-Type: multipart/form-data' \
  --header 'Authorization: Bearer YOUR_JWT' \
  --form 'file=@path/to/your/image.png;type=image/png' \
```

This will return a JSON object with the `uid` of the uploaded file:

```
{
  "uid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "path": null,
  "download_url": "https://delivery.scalefs.ikomia.ai/a5136ea9-a120-4173-9bca-5cf92ac98c11/3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "is_directory_archive": false,
  "content_type": "image/png",
  "sha256": "ca8b9ba2b8ac022e17cd18c9bde2cc0291ffbfcc5549cdd76b65d12990ed3a93",
  "size": 123456,
  "created_at": "2025-07-03T08:58:20.403Z"
}
```

You can then format your input object in the following way:

```
{
  "storage_object": {
    "url": "https://scalefs.ikomia.ai/v1/objects/?uid=3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "data_type": "image"
  }
}
```

Where `url` is the URL of the uploaded file metadata (`https://scalefs.ikomia.ai/v1/objects/` with the `uid` of the object as a query parameter) and `data_type` is the type of the uploaded file (`image` or `video`).

### Outputs[​](#outputs "Direct link to Outputs")

By default, the REST API doesn't return any outputs. You need to specify which outputs you want to retrieve by providing an object for each output in the following format:

```
{
  "task_name": "infer_yolo_v8",
  "task_index": 0,
  "output_index": 1,
  "save_temporary": true
}
```

Where:

* `task_name` is the name of the workflow task (algorithm) you want to retrieve outputs for.
* `task_index` if the same algorithm appears multiple times in the workflow, the index of the wanted task (default to 0 if not specified, corresponding to the first occurrence of the algorithm in the workflow, 1 for the second, etc.).
* `output_index` if the algorithm returns multiple outputs, the index of the output you want to keep in the result (if not specified, all outputs of the given task will be returned).
* `save_temporary` if set to true, the output will be saved as a temporary object to your project's storage. (default to false if not specified, except for video outputs that are always saved to project storage)

### Parameters[​](#parameters "Direct link to Parameters")

You can override the default parameters of a workflow task by providing an object in the following format:

```
{
  "task_name": "infer_yolo_v8",
  "task_index": 0,
  "parameters": {
    "conf_thres": "0.5"
  }
}
```

Where:

* `task_name` is the name of the workflow task (algorithm) you want to set parameters for.
* `task_index` if the same algorithm appears multiple times in the workflow, the index of the wanted task (default to 0 if not specified, corresponding to the first occurrence of the algorithm in the workflow, 1 for the second, etc.).
* `parameters` is an object containing the parameters you want to set. **All parameters values must be specified as strings.**

### Response[​](#response "Direct link to Response")

The query will return a JSON object containing the current status of the deployment run:

```
{
  "uuid": "7cc8b1a6-a77a-4001-957d-6775ea9323a2",
  "state": "PENDING",
  "eta": [1000, 2000],
  "next_poll_in": 500,
  "next_poll_long": true,
  "results": null
}
```

The status object contains the following fields:

* `uuid`: The id of the deployment run.
* `state`: The current state, can be one of the following: `SENDING`, `FAILURE`, `PENDING`, `SUCCESS`.
* `eta`: An estimation of the time remaining for the deployment to complete, in milliseconds. Can be `[null, null]`.
* `next_poll_in`: The recommended time to wait before polling for the next status update, in milliseconds. Can be `null`.
* `next_poll_long`: A recommendation on whether or not to enable long polling for the next status update.
* `results`: The results of the deployment, if available.

## Polling for results[​](#polling-for-results "Direct link to Polling for results")

Your deployment is unlikely to respond with results immediately, so you will need to poll for the results of the run.

You can do this by sending a `GET` request to the `/api/results/{uuid}` endpoint, where `{uuid}` is the id of the deployment run you received in the previous response.

```
curl --request GET \
  --url 'https://your.scale.endpoint.url/api/results/{uuid}?advice=true' \
  --header 'Authorization: Bearer YOUR_JWT'
```

This will return a new object in the same format as the initial request with the updated state of the deployment run.

If the run is still ongoing, the deployment will respond with a status `202 Accepted`.

info

The deployments optionally return some hints (`eta`, `next_poll_in`, and `next_poll_long`) to help you provide eta for your user and optimize your polling strategy. These hints are based on statistics from recent previous runs and **suppose similar patterns will hold in the current run**.

This may not always be the case depending on your application, for example, if you are processing videos with a high variance in duration. We recommend testing with your specific workload to find the optimal polling strategy.

### Long polling[​](#long-polling "Direct link to Long polling")

CPU and GPU instance deployments may emit a `"next_poll_long": true` advice, recommending you to enable long polling for the next status update. Long polling means that the deployment will try to wait for the end of the run before responding to your request. This is usually when the deployment expects to have finished processing rapidly after `next_poll_in` duration.

To enable long polling, you can set the `long=true` query parameter in your status update request.

```
curl --request GET \
  --url 'https://your.scale.endpoint.url/api/results/{uuid}?advice=true&long=true' \
  --header 'Authorization: Bearer YOUR_JWT'
```

warning

It is not expected that all queries with `long=true` will return a final status and results. To avoid timeouts, they may resolve early with a partial status.

### Results[​](#results "Direct link to Results")

The deployment results will be returned as a JSON array in the same format as you can find in the JSON response of the [test interface](https://docs.ikomia.ai/scale/deployment/test-interface.md) and in the same order as the outputs you requested.

```
{
  "uuid": "7cc8b1a6-a77a-4001-957d-6775ea9323a2",
  "state": "SUCCESS",
  "results": [
    {
      "OBJECT_DETECTION": {
        "detections": [
          {
            "box": {
              "height": 804,
              "width": 291,
              "x": 9,
              "y": 250
            },
            "color": {
              "a": 54,
              "b": 253,
              "g": 11,
              "r": 70
            },
            "confidence": 0.9631829261779785,
            "id": 0,
            "label": "person"
          }
        ],
        "referenceImageIndex": 0
      }
    }
  ],
  "eta": [0, 0],
  "next_poll_in": null,
  "next_poll_long": false
}
```
