> Toden documentation. For the full index fetch /llms.txt. Every page is available as Markdown by appending .md to its URL. Identity verification uses /api/kyc, Risk Intelligence uses /api/v1; they are separate contracts with different error shapes. Never invent an endpoint, field or enum value: read the API reference page for the operation first.

# Retrieve a triage job

GET https://sandbox-api.toden.co/api/identity/address-triage/{jobId}

Returns the job and the distribution of its rows across the grades, with shared addresses and the progress of any remediation links. Read only, and not billed. Individual rows are not returned here.

**Error codes**

| `error` | Status | Meaning |
|---|---|---|
| `triage_job_not_found` | 404 | No triage job has this identifier in this organisation and environment. |
| `secret_key_required` | 403 | A publishable key was used. This API accepts secret keys only. |
| `environment_mismatch` | 403 | The key belongs to an environment this host does not serve. |
| `rate_limited` | 429 | The request rate limit for this key was reached. Retry after a short wait. |
| `rate_limit_store_unavailable` | 503 | Rate limiting is temporarily unavailable. Retry shortly. |

A missing or unknown key returns `401` with a plain sentence in `error` rather than a code.

Requires a secret (`sk_`) key. A publishable key receives `403 secret_key_required`.

Reference: https://docs.toden.co/api-reference/verification/address-triage/get-address-triage

## Authentication

- `Authorization` header (bearer token, required) — Send the API key as a Bearer token. Each operation states whether a publishable key is enough or a secret key is required.

## Servers

- `https://sandbox-api.toden.co` (Sandbox, default)
- `https://api.toden.co` (Production)

## Request

### Path parameters

- `jobId` (string, required) — The `jobId` returned when the triage job was accepted.

## Response

### 200

Success

- `job` (AddressTriageJob, required)
- `distribution` (AddressTriageDistribution, required)

## Errors

### 401 Unauthorized Error

The Authorization header is missing, or the API key is unknown or revoked.

- `error` (string, required) — A stable machine-readable code such as `invalid_input`. Authentication failures (401) carry a short sentence here instead of a code.
- `message` (string, optional) — A human-readable explanation, safe to log. The wording may change.

### 403 Forbidden Error

The key may not call this endpoint, or the organisation may not use this feature.

- `error` (string, required) — A stable machine-readable code such as `invalid_input`. Authentication failures (401) carry a short sentence here instead of a code.
- `message` (string, optional) — A human-readable explanation, safe to log. The wording may change.

### 404 Not Found Error

The resource does not exist for this organisation and environment.

- `error` (string, required) — A stable machine-readable code such as `invalid_input`. Authentication failures (401) carry a short sentence here instead of a code.
- `message` (string, optional) — A human-readable explanation, safe to log. The wording may change.

### 429 Too Many Requests Error

A rate limit was reached. Retry after a short wait.

- `error` (string, required) — A stable machine-readable code such as `invalid_input`. Authentication failures (401) carry a short sentence here instead of a code.
- `message` (string, optional) — A human-readable explanation, safe to log. The wording may change.

### 503 Service Unavailable Error

The service is temporarily unavailable.

- `error` (string, required) — A stable machine-readable code such as `invalid_input`. Authentication failures (401) carry a short sentence here instead of a code.
- `message` (string, optional) — A human-readable explanation, safe to log. The wording may change.

## Types

### AddressTriageJob

- `id` (string, required) — The identifier of the triage job.
- `status` (enum, required) — The state of the job.
  - Allowed values: `PENDING`, `PROCESSING`, `COMPLETED`, `FAILED`
- `totalCount` (integer, required) — How many rows the job holds.
- `succeededCount` (integer, required) — How many rows have been graded.
- `failedCount` (integer, required) — How many rows could not be graded.
- `createdAt` (datetime, required) — When the job was accepted.
- `meta` (AddressTriageJobMeta, optional, nullable) — Facts about the run.
- `scrubbedAt` (datetime, optional, nullable) — When the addresses and names were removed from the job at the end of its retention period.
- `completedAt` (datetime, optional, nullable) — When the last row was graded.

### AddressTriageDistribution

- `graded` (integer, required) — How many rows have a grade.
- `pending` (integer, required) — How many rows are still waiting to be graded.
- `failed` (integer, required) — How many rows could not be graded.
- `byGrade` (AddressTriageDistributionByGrade, required) — The count of rows in each grade.
- `strong` (integer, required) — Of the graded rows, how many agreed on a street or a verified presence rather than a locality alone.
- `reachable` (integer, required) — Of the `confirmable_in_app` rows, how many have an email address or phone number on file.
- `unusable` (integer, required) — Of the `confirmable_in_app` rows, how many belong to a closed, suspended or rejected customer.
- `duplicates` (AddressTriageDistributionDuplicates, required) — Addresses shared by more than one row. A shared address is reported, never graded against anyone.
- `remediation` (AddressTriageDistributionRemediation, required) — How far the remediation links for this job have got, read live.

### AddressTriageJobMeta

Facts about the run.

- `preview` (boolean, optional) — True when the job graded a free sample.
- `country` (string, optional, nullable) — The default country applied to rows without one.
- `fileName` (string, optional, nullable) — The uploaded file name. Always `null` for jobs created through this API.
- `uploadedRows` (integer, optional) — How many rows were submitted, including any a sample left ungraded.
- `quotedRows` (integer, optional) — For a sample, how many rows were left ungraded.
- `quotedAmount` (string, optional) — For a sample, the quoted cost of the remaining rows as a decimal string.
- `remediatedAt` (datetime, optional) — When remediation links were last created for the job.
- `remediationWorkflowId` (string, optional) — The workflow the most recent remediation links run.

### AddressTriageDistributionByGrade

The count of rows in each grade.

- `corroborated` (integer, required) — Rows where evidence already held agrees with the address in the book.
- `confirmable_in_app` (integer, required) — Rows where an entity exists, so a short re-capture flow can confirm the address.
- `needs_presence` (integer, required) — Rows with no existing relationship to lean on, where a presence check is the route to evidence.
- `unresolvable` (integer, required) — Rows whose address text names no place that could be resolved.

### AddressTriageDistributionDuplicates

Addresses shared by more than one row. A shared address is reported, never graded against anyone.

- `affectedRows` (integer, required) — How many rows sit on an address that more than one row shares.
- `clusters` (integer, required) — How many distinct addresses are shared.
- `top` (list of AddressTriageDistributionDuplicatesTopItems, required) — The largest shared addresses, biggest first.

### AddressTriageDistributionRemediation

How far the remediation links for this job have got, read live.

- `minted` (integer, required) — How many remediation links have been created.
- `opened` (integer, required) — How many links have been opened but not finished.
- `submitted` (integer, required) — How many links were completed.
- `expired` (integer, required) — How many links expired unopened.

### AddressTriageDistributionDuplicatesTopItems

- `address` (string, required) — The address as first written in the book.
- `locality` (string, required, nullable) — The locality the address resolved to.
- `count` (integer, required) — How many rows share the address.
- `sample` (list of string, required) — Up to five of the customer references sharing it.

## Examples

**Response**

```json
{
  "job": {
    "id": "cm9x2k4m80006",
    "status": "COMPLETED",
    "totalCount": 2,
    "succeededCount": 2,
    "failedCount": 0,
    "createdAt": "2026-09-04T09:00:00.000Z",
    "meta": {
      "preview": false,
      "country": "NG",
      "fileName": null,
      "uploadedRows": 2
    },
    "scrubbedAt": null,
    "completedAt": "2026-09-04T09:00:04.000Z"
  },
  "distribution": {
    "graded": 2,
    "pending": 0,
    "failed": 0,
    "byGrade": {
      "corroborated": 1,
      "confirmable_in_app": 1,
      "needs_presence": 0,
      "unresolvable": 0
    },
    "strong": 1,
    "reachable": 1,
    "unusable": 0,
    "duplicates": {
      "affectedRows": 0,
      "clusters": 0,
      "top": []
    },
    "remediation": {
      "minted": 0,
      "opened": 0,
      "submitted": 0,
      "expired": 0
    }
  }
}
```

**SDK Code**

```python
import requests

url = "https://sandbox-api.toden.co/api/identity/address-triage/jobId"

headers = {"Authorization": "Bearer <apiKey>"}

response = requests.get(url, headers=headers)

print(response.json())
```

```javascript
const url = 'https://sandbox-api.toden.co/api/identity/address-triage/jobId';
const options = {method: 'GET', headers: {Authorization: 'Bearer <apiKey>'}};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"net/http"
	"io"
)

func main() {

	url := "https://sandbox-api.toden.co/api/identity/address-triage/jobId"

	req, _ := http.NewRequest("GET", url, nil)

	req.Header.Add("Authorization", "Bearer <apiKey>")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://sandbox-api.toden.co/api/identity/address-triage/jobId")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)
request["Authorization"] = 'Bearer <apiKey>'

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.get("https://sandbox-api.toden.co/api/identity/address-triage/jobId")
  .header("Authorization", "Bearer <apiKey>")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('GET', 'https://sandbox-api.toden.co/api/identity/address-triage/jobId', [
  'headers' => [
    'Authorization' => 'Bearer <apiKey>',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://sandbox-api.toden.co/api/identity/address-triage/jobId");
var request = new RestRequest(Method.GET);
request.AddHeader("Authorization", "Bearer <apiKey>");
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = ["Authorization": "Bearer <apiKey>"]

let request = NSMutableURLRequest(url: NSURL(string: "https://sandbox-api.toden.co/api/identity/address-triage/jobId")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "GET"
request.allHTTPHeaderFields = headers

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```