---
title: Labeling
description: The Labeling API lets you create, list, retrieve, and delete labeling.
---

# Labeling

The Labeling API lets you create, list, retrieve, and delete labeling.

> **Auto-generated** from the public OpenAPI spec — this page never
> drifts from the running API. Base URL `https://api.arcnm.io`. Authenticate with
> the `X-API-Key` header (see [Authentication](../authentication.md)).

## List Labeling Campaigns

`GET /api/v1/parts/labeling/campaigns`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `status` | query | string | no |  |
| `limit` | query | integer | no | Maximum number of results to return. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/labeling/campaigns \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `count` | integer |  |
| `data` | LabelingCampaignPublic[] |  |

**Example response**

```json
{
  "count": 0,
  "data": [
    {
      "acceptance_alpha": 0.8,
      "closed_at": "2026-06-01T12:00:00Z",
      "consensus_method": "dawid_skene",
      "created_at": "2026-06-01T12:00:00Z",
      "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "description": "string",
      "gold_fraction": 0.1,
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "string",
      "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "resolved_count": 0,
      "status": "string",
      "target_redundancy": 3,
      "task_count": 0
    }
  ]
}
```

## Create Labeling Campaign

`POST /api/v1/parts/labeling/campaigns`

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `acceptance_alpha` | number | no |  |
| `consensus_method` | string | no |  |
| `description` | string | no |  |
| `gold_fraction` | number | no |  |
| `name` | string | yes |  |
| `target_redundancy` | integer | no |  |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/campaigns \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string"
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "name": "string"
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "name": "string"
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `201` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `201`

| Field | Type | Description |
| --- | --- | --- |
| `acceptance_alpha` | number |  |
| `closed_at` | string |  |
| `consensus_method` | string |  |
| `created_at` | string |  |
| `created_by_user_id` | string |  |
| `description` | string |  |
| `gold_fraction` | number |  |
| `id` | string |  |
| `name` | string |  |
| `org_id` | string |  |
| `project_id` | string |  |
| `resolved_count` | integer |  |
| `status` | string |  |
| `target_redundancy` | integer |  |
| `task_count` | integer |  |

**Example response**

```json
{
  "acceptance_alpha": 0.8,
  "closed_at": "2026-06-01T12:00:00Z",
  "consensus_method": "dawid_skene",
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "description": "string",
  "gold_fraction": 0.1,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "resolved_count": 0,
  "status": "string",
  "target_redundancy": 3,
  "task_count": 0
}
```

## Get Labeling Campaign

`GET /api/v1/parts/labeling/campaigns/{campaign_id}`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id} \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `acceptance_alpha` | number |  |
| `closed_at` | string |  |
| `consensus_method` | string |  |
| `created_at` | string |  |
| `created_by_user_id` | string |  |
| `description` | string |  |
| `gold_fraction` | number |  |
| `id` | string |  |
| `name` | string |  |
| `org_id` | string |  |
| `project_id` | string |  |
| `resolved_count` | integer |  |
| `status` | string |  |
| `target_redundancy` | integer |  |
| `task_count` | integer |  |

**Example response**

```json
{
  "acceptance_alpha": 0.8,
  "closed_at": "2026-06-01T12:00:00Z",
  "consensus_method": "dawid_skene",
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "description": "string",
  "gold_fraction": 0.1,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "resolved_count": 0,
  "status": "string",
  "target_redundancy": 3,
  "task_count": 0
}
```

## List Campaign Assignments

`GET /api/v1/parts/labeling/campaigns/{campaign_id}/assignments`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/assignments \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/assignments",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/assignments", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `count` | integer |  |
| `data` | CampaignAssignmentPublic[] |  |

**Example response**

```json
{
  "count": 0,
  "data": [
    {
      "annotator_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "annotator_email": "dev@example.com",
      "campaign_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "invited_at": "2026-06-01T12:00:00Z",
      "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "status": "string"
    }
  ]
}
```

## Create Campaign Assignment

`POST /api/v1/parts/labeling/campaigns/{campaign_id}/assignments`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `display_name` | string | no |  |
| `email` | string | yes |  |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/assignments \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "dev@example.com"
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/assignments",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "email": "dev@example.com"
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/assignments", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "email": "dev@example.com"
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `201` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `201`

| Field | Type | Description |
| --- | --- | --- |
| `assignment` | CampaignAssignmentPublic |  |
| `magic_link_token` | string |  |

**Example response**

```json
{
  "assignment": {
    "annotator_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "annotator_email": "dev@example.com",
    "campaign_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "invited_at": "2026-06-01T12:00:00Z",
    "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "status": "string"
  },
  "magic_link_token": "string"
}
```

## Revoke Campaign Assignment

`DELETE /api/v1/parts/labeling/campaigns/{campaign_id}/assignments/{assignment_id}`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |
| `assignment_id` | path | string | yes | Identifier of the assignment. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X DELETE https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/assignments/{assignment_id} \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.delete(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/assignments/{assignment_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/assignments/{assignment_id}", {
  method: "DELETE",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `annotator_account_id` | string |  |
| `annotator_email` | string |  |
| `campaign_id` | string |  |
| `id` | string |  |
| `invited_at` | string |  |
| `org_id` | string |  |
| `status` | string |  |

**Example response**

```json
{
  "annotator_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "annotator_email": "dev@example.com",
  "campaign_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "invited_at": "2026-06-01T12:00:00Z",
  "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "status": "string"
}
```

## Close Labeling Campaign

`POST /api/v1/parts/labeling/campaigns/{campaign_id}/close`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/close \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/close",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/close", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `acceptance_alpha` | number |  |
| `closed_at` | string |  |
| `consensus_method` | string |  |
| `created_at` | string |  |
| `created_by_user_id` | string |  |
| `description` | string |  |
| `gold_fraction` | number |  |
| `id` | string |  |
| `name` | string |  |
| `org_id` | string |  |
| `project_id` | string |  |
| `resolved_count` | integer |  |
| `status` | string |  |
| `target_redundancy` | integer |  |
| `task_count` | integer |  |

**Example response**

```json
{
  "acceptance_alpha": 0.8,
  "closed_at": "2026-06-01T12:00:00Z",
  "consensus_method": "dawid_skene",
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "description": "string",
  "gold_fraction": 0.1,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "resolved_count": 0,
  "status": "string",
  "target_redundancy": 3,
  "task_count": 0
}
```

## Next Labeling Task

`POST /api/v1/parts/labeling/campaigns/{campaign_id}/next-task`

Atomically claim the next open task for the current annotator.

Serves one task they haven't submitted that still needs submissions,
reserving it under a short lease (:data:`CLAIM_TTL`) so two annotators
pulling concurrently never get the same task. Mixes hidden honeypots so
the realized fraction of served gold tasks trends to the campaign's
``gold_fraction``. Returns null when the queue is drained for this
annotator.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/next-task \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/next-task",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/next-task", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `calculation_id` | string |  |
| `campaign_id` | string |  |
| `detail_kind` | string |  |
| `dfm_issue_id` | string |  |
| `drawing_bbox` | number[] |  |
| `face_uuid` | string |  |
| `feature_id` | string |  |
| `field_name` | string |  |
| `field_path` | string |  |
| `id` | string |  |
| `n_required` | integer |  |
| `part_revision_id` | string |  |
| `pmi_id` | string |  |
| `position` | number[] |  |
| `predicted_value` | object |  |
| `prompt` | string |  |
| `status` | string |  |
| `target_kind` | string |  |

**Example response**

```json
{
  "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "campaign_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "detail_kind": "string",
  "dfm_issue_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "drawing_bbox": [
    0
  ],
  "face_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "feature_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "field_name": "string",
  "field_path": "string",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "n_required": 3,
  "part_revision_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "pmi_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "position": [
    0
  ],
  "predicted_value": null,
  "prompt": "string",
  "status": "string",
  "target_kind": "string"
}
```

## Promote Labeling Campaign

`POST /api/v1/parts/labeling/campaigns/{campaign_id}/promote`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/promote \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/promote",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/promote", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `accepted` | boolean |  |
| `alpha` | number |  |
| `forced` | boolean |  |
| `promoted` | integer |  |

**Example response**

```json
{
  "accepted": true,
  "alpha": 0,
  "forced": true,
  "promoted": 0
}
```

## Labeling Campaign Quality

`GET /api/v1/parts/labeling/campaigns/{campaign_id}/quality`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/quality \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/quality",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/quality", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `acceptance_alpha` | number |  |
| `accepted` | boolean |  |
| `alpha` | number |  |
| `annotators` | AnnotatorQuality[] |  |
| `n_submissions` | integer |  |
| `n_tasks` | integer |  |

**Example response**

```json
{
  "acceptance_alpha": 0,
  "accepted": true,
  "alpha": 0,
  "annotators": [
    {
      "annotator_user_id": "string",
      "consensus_agreement": 0,
      "gold_accuracy": 0,
      "n_submissions": 0,
      "reliability": 0,
      "trust": 0
    }
  ],
  "n_submissions": 0,
  "n_tasks": 0
}
```

## List Labeling Tasks

`GET /api/v1/parts/labeling/campaigns/{campaign_id}/tasks`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |
| `status` | query | string | no |  |
| `limit` | query | integer | no | Maximum number of results to return. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/tasks \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/tasks",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/tasks", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `count` | integer |  |
| `data` | LabelingTaskPublic[] |  |

**Example response**

```json
{
  "count": 0,
  "data": [
    {
      "agreement": 0,
      "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "campaign_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "claim_expires_at": "2026-06-01T12:00:00Z",
      "claimed_at": "2026-06-01T12:00:00Z",
      "claimed_by_annotator_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "claimed_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "consensus_value": null,
      "consensus_verdict": "string",
      "created_at": "2026-06-01T12:00:00Z",
      "detail_kind": "string",
      "dfm_issue_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "drawing_bbox": [
        0
      ],
      "face_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "feature_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "field_name": "string",
      "field_path": "string",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "is_gold": true,
      "n_required": 3,
      "part_revision_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "pmi_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "position": [
        0
      ],
      "predicted_confidence": 0,
      "predicted_value": null,
      "prompt": "string",
      "resolved_at": "2026-06-01T12:00:00Z",
      "status": "string",
      "submission_count": 0,
      "target_kind": "string"
    }
  ]
}
```

## Create Labeling Tasks

`POST /api/v1/parts/labeling/campaigns/{campaign_id}/tasks`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `campaign_id` | path | string | yes | Identifier of the campaign. |

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `tasks` | LabelingTaskCreate[] | yes |  |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/tasks \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "tasks": [
      {
        "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "detail_kind": "string",
        "dfm_issue_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "drawing_bbox": [
          0
        ],
        "face_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "feature_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "field_name": "string",
        "field_path": "string",
        "gold_answer": "string",
        "is_gold": false,
        "n_required": 3,
        "part_revision_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "pmi_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "position": [
          0
        ],
        "predicted_confidence": 0,
        "predicted_value": null,
        "prompt": "string",
        "target_kind": "string"
      }
    ]
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/tasks",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "tasks": [
            {
                "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "detail_kind": "string",
                "dfm_issue_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "drawing_bbox": [
                    0
                ],
                "face_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "feature_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "field_name": "string",
                "field_path": "string",
                "gold_answer": "string",
                "is_gold": False,
                "n_required": 3,
                "part_revision_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "pmi_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
                "position": [
                    0
                ],
                "predicted_confidence": 0,
                "predicted_value": None,
                "prompt": "string",
                "target_kind": "string"
            }
        ]
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/campaigns/{campaign_id}/tasks", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "tasks": [
      {
        "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "detail_kind": "string",
        "dfm_issue_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "drawing_bbox": [
          0
        ],
        "face_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "feature_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "field_name": "string",
        "field_path": "string",
        "gold_answer": "string",
        "is_gold": false,
        "n_required": 3,
        "part_revision_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "pmi_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
        "position": [
          0
        ],
        "predicted_confidence": 0,
        "predicted_value": null,
        "prompt": "string",
        "target_kind": "string"
      }
    ]
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `201` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `201`

| Field | Type | Description |
| --- | --- | --- |
| `count` | integer |  |
| `data` | LabelingTaskPublic[] |  |

**Example response**

```json
{
  "count": 0,
  "data": [
    {
      "agreement": 0,
      "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "campaign_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "claim_expires_at": "2026-06-01T12:00:00Z",
      "claimed_at": "2026-06-01T12:00:00Z",
      "claimed_by_annotator_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "claimed_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "consensus_value": null,
      "consensus_verdict": "string",
      "created_at": "2026-06-01T12:00:00Z",
      "detail_kind": "string",
      "dfm_issue_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "drawing_bbox": [
        0
      ],
      "face_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "feature_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "field_name": "string",
      "field_path": "string",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "is_gold": true,
      "n_required": 3,
      "part_revision_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "pmi_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "position": [
        0
      ],
      "predicted_confidence": 0,
      "predicted_value": null,
      "prompt": "string",
      "resolved_at": "2026-06-01T12:00:00Z",
      "status": "string",
      "submission_count": 0,
      "target_kind": "string"
    }
  ]
}
```

## List Labeling Projects

`GET /api/v1/parts/labeling/projects`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `limit` | query | integer | no | Maximum number of results to return. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/labeling/projects \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/labeling/projects",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/projects", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `count` | integer |  |
| `data` | LabelingProjectPublic[] |  |

**Example response**

```json
{
  "count": 0,
  "data": [
    {
      "campaign_count": 0,
      "created_at": "2026-06-01T12:00:00Z",
      "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "description": "string",
      "guideline_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "name": "string",
      "ontology_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
      "selection_policy": {},
      "status": "string",
      "target_kinds": [
        "string"
      ],
      "uses_platform_pool": false
    }
  ]
}
```

## Create Labeling Project

`POST /api/v1/parts/labeling/projects`

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `description` | string | no |  |
| `guideline_id` | string | no |  |
| `name` | string | yes |  |
| `ontology_id` | string | no |  |
| `selection_policy` | object | no |  |
| `target_kinds` | string[] | no |  |
| `uses_platform_pool` | boolean | no |  |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/projects \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "string"
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/projects",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "name": "string"
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/projects", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "name": "string"
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `201` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `201`

| Field | Type | Description |
| --- | --- | --- |
| `campaign_count` | integer |  |
| `created_at` | string |  |
| `created_by_user_id` | string |  |
| `description` | string |  |
| `guideline_id` | string |  |
| `id` | string |  |
| `name` | string |  |
| `ontology_id` | string |  |
| `org_id` | string |  |
| `selection_policy` | object |  |
| `status` | string |  |
| `target_kinds` | string[] |  |
| `uses_platform_pool` | boolean |  |

**Example response**

```json
{
  "campaign_count": 0,
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "description": "string",
  "guideline_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "ontology_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "selection_policy": {},
  "status": "string",
  "target_kinds": [
    "string"
  ],
  "uses_platform_pool": false
}
```

## Get Labeling Project

`GET /api/v1/parts/labeling/projects/{project_id}`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `project_id` | path | string | yes | Identifier of the project. |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X GET https://api.arcnm.io/api/v1/parts/labeling/projects/{project_id} \
  -H "X-API-Key: $ARCNM_API_KEY"
```

```python title="Python"
import requests

resp = requests.get(
    "https://api.arcnm.io/api/v1/parts/labeling/projects/{project_id}",
    headers={"X-API-Key": "YOUR_API_KEY"},
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/projects/{project_id}", {
  method: "GET",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
  },
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `campaign_count` | integer |  |
| `created_at` | string |  |
| `created_by_user_id` | string |  |
| `description` | string |  |
| `guideline_id` | string |  |
| `id` | string |  |
| `name` | string |  |
| `ontology_id` | string |  |
| `org_id` | string |  |
| `selection_policy` | object |  |
| `status` | string |  |
| `target_kinds` | string[] |  |
| `uses_platform_pool` | boolean |  |

**Example response**

```json
{
  "campaign_count": 0,
  "created_at": "2026-06-01T12:00:00Z",
  "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "description": "string",
  "guideline_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "name": "string",
  "ontology_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "selection_policy": {},
  "status": "string",
  "target_kinds": [
    "string"
  ],
  "uses_platform_pool": false
}
```

## Generate Project Tasks

`POST /api/v1/parts/labeling/projects/{project_id}/generate-tasks`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `project_id` | path | string | yes | Identifier of the project. |

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `calculation_ids` | string[] | yes |  |
| `campaign` | LabelingCampaignCreate | no |  |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/projects/{project_id}/generate-tasks \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "calculation_ids": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ]
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/projects/{project_id}/generate-tasks",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "calculation_ids": [
            "3fa85f64-5717-4562-b3fc-2c963f66afa6"
        ]
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/projects/{project_id}/generate-tasks", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "calculation_ids": [
      "3fa85f64-5717-4562-b3fc-2c963f66afa6"
    ]
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `201` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `201`

| Field | Type | Description |
| --- | --- | --- |
| `campaign` | LabelingCampaignPublic |  |
| `n_candidates` | integer |  |
| `n_eligible` | integer |  |
| `n_honeypots` | integer |  |
| `n_skipped` | integer |  |
| `n_tasks` | integer |  |

**Example response**

```json
{
  "campaign": {
    "acceptance_alpha": 0.8,
    "closed_at": "2026-06-01T12:00:00Z",
    "consensus_method": "dawid_skene",
    "created_at": "2026-06-01T12:00:00Z",
    "created_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "description": "string",
    "gold_fraction": 0.1,
    "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "name": "string",
    "org_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "project_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "resolved_count": 0,
    "status": "string",
    "target_redundancy": 3,
    "task_count": 0
  },
  "n_candidates": 0,
  "n_eligible": 0,
  "n_honeypots": 0,
  "n_skipped": 0,
  "n_tasks": 0
}
```

## Adjudicate Task

`POST /api/v1/parts/labeling/tasks/{task_id}/adjudicate`

Expert override: set the final consensus verdict/value and resolve.

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `task_id` | path | string | yes | Identifier of the task. |

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `corrected_value` | object | no |  |
| `verdict` | string | yes |  |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/tasks/{task_id}/adjudicate \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "verdict": "string"
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/tasks/{task_id}/adjudicate",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "verdict": "string"
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/tasks/{task_id}/adjudicate", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "verdict": "string"
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `200` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `200`

| Field | Type | Description |
| --- | --- | --- |
| `agreement` | number |  |
| `calculation_id` | string |  |
| `campaign_id` | string |  |
| `claim_expires_at` | string |  |
| `claimed_at` | string |  |
| `claimed_by_annotator_account_id` | string |  |
| `claimed_by_user_id` | string |  |
| `consensus_value` | object |  |
| `consensus_verdict` | string |  |
| `created_at` | string |  |
| `detail_kind` | string |  |
| `dfm_issue_id` | string |  |
| `drawing_bbox` | number[] |  |
| `face_uuid` | string |  |
| `feature_id` | string |  |
| `field_name` | string |  |
| `field_path` | string |  |
| `id` | string |  |
| `is_gold` | boolean |  |
| `n_required` | integer |  |
| `part_revision_id` | string |  |
| `pmi_id` | string |  |
| `position` | number[] |  |
| `predicted_confidence` | number |  |
| `predicted_value` | object |  |
| `prompt` | string |  |
| `resolved_at` | string |  |
| `status` | string |  |
| `submission_count` | integer |  |
| `target_kind` | string |  |

**Example response**

```json
{
  "agreement": 0,
  "calculation_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "campaign_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "claim_expires_at": "2026-06-01T12:00:00Z",
  "claimed_at": "2026-06-01T12:00:00Z",
  "claimed_by_annotator_account_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "claimed_by_user_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "consensus_value": null,
  "consensus_verdict": "string",
  "created_at": "2026-06-01T12:00:00Z",
  "detail_kind": "string",
  "dfm_issue_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "drawing_bbox": [
    0
  ],
  "face_uuid": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "feature_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "field_name": "string",
  "field_path": "string",
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "is_gold": true,
  "n_required": 3,
  "part_revision_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "pmi_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "position": [
    0
  ],
  "predicted_confidence": 0,
  "predicted_value": null,
  "prompt": "string",
  "resolved_at": "2026-06-01T12:00:00Z",
  "status": "string",
  "submission_count": 0,
  "target_kind": "string"
}
```

## Submit Label

`POST /api/v1/parts/labeling/tasks/{task_id}/submit`

**Parameters**

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `task_id` | path | string | yes | Identifier of the task. |

**Request body** (`application/json`)

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `confidence` | number | no |  |
| `corrected_value` | object | no |  |
| `duration_ms` | integer | no |  |
| `verdict` | string | yes |  |

**Request**

<CodeTabs>

```bash title="cURL"
curl -X POST https://api.arcnm.io/api/v1/parts/labeling/tasks/{task_id}/submit \
  -H "X-API-Key: $ARCNM_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "verdict": "string"
  }'
```

```python title="Python"
import requests

resp = requests.post(
    "https://api.arcnm.io/api/v1/parts/labeling/tasks/{task_id}/submit",
    headers={"X-API-Key": "YOUR_API_KEY"},
    json={
        "verdict": "string"
    },
)
resp.raise_for_status()
print(resp.json())
```

```typescript title="TypeScript"
const resp = await fetch("https://api.arcnm.io/api/v1/parts/labeling/tasks/{task_id}/submit", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.ARCNM_API_KEY!,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "verdict": "string"
  }),
})
const data = await resp.json()
```

</CodeTabs>

**Responses**

| Status | Description |
| --- | --- |
| `201` | Successful Response |
| `422` | Validation Error |

**Errors**

Standard error responses — see the [Errors catalog](../errors.md) for the full envelope, `request_id`, and retry-safety table.

| Status | Code | When |
| --- | --- | --- |
| `401` | `invalid_api_key` | Missing, malformed, or revoked API key. |
| `403` | `insufficient_scope` | The key is valid but lacks a scope this endpoint requires. |
| `404` | `not_found` | A referenced resource doesn't exist or isn't visible to your organisation. |
| `409` | `conflict` | A conflicting change, or an `Idempotency-Key` reused with a different body. |
| `429` | `rate_limited` | Per-key or per-org rate limit exceeded — back off with jitter and retry. |


**Response body** `201`

| Field | Type | Description |
| --- | --- | --- |
| `confidence` | number |  |
| `corrected_value` | object |  |
| `created_at` | string |  |
| `duration_ms` | integer |  |
| `id` | string |  |
| `task_id` | string |  |
| `verdict` | string |  |

**Example response**

```json
{
  "confidence": 0,
  "corrected_value": null,
  "created_at": "2026-06-01T12:00:00Z",
  "duration_ms": 0,
  "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "task_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
  "verdict": "string"
}
```
