DDroomwork Developers

Version 1.0.0

Droomwork ANCHOR PRO

Identity resolution for Nigeria. One real person, not several accounts.

Base URLhttps://sandbox.droomwork.io
AuthenticationDroomwork-Api-Key: dw_test_… or Authorization: Bearer dw_test_…
Events it sends8 webhooks →
Signed in: requests you run on this page use a key made for your account. Your keys →

ANCHOR answers one question for you: is this a real person, and is it the same person you saw before.

What this API gives you, and what it will not

You get decisions, never raw personal data. You learn the assurance level reached, whether a disqualifying flag exists, and what evidence was consulted. You don't receive the identity number, the biometric template or the underlying government record. There is no setting that changes this.

Identity numbers are never returned in full. Where a number has to be shown at all, it's masked. If you need to show a subject something, show them the mask.

No consent, no query. Before any source is touched, you need a verifiable consent token bound to the subject, your organisation, the purpose and the specific checks. This holds however your organisation is configured and whatever anyone has attested to. It's data protection law, not vetting policy.

A source that doesn't answer returns unresolved, naming the source. Never a rejection and never a silent pass. Silence isn't evidence.

A probable duplicate goes to a person. A strong identifier match merges on its own. Anything weaker is raised for you to adjudicate.

Assurance levels

An identity carries the level it reached and how. This release delivers up to DAL-2.

LevelMeans
DAL-0Claimed. Someone said so
DAL-1Contactable. A channel was proved
DAL-2Matched against a government identifier on name and date of birth
DAL-3Biometric binding. Not in this release
DAL-4Adverse screening cleared. Not in this release

Getting started

Collect consent. Submit a verification. Read the Passport. Everything downstream of identity, in every module, checks that the Passport is live before it acts.

Every operation below has two samples: Direct HTTP, with nothing but your language's own client, and Client library, with ours. Same request, same answer; the switch above each sample picks one and remembers it. Which should I use?

GET/v1/identity/consent_tokens#

List consent tokens

identity.consent_tokens.list

Every consent your organisation holds, including the withdrawn and the expired. A withdrawn token stays listed: what somebody agreed to and when they took it back is the record an auditor asks for.

Returns

A list of consent tokens.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of ConsentToken required

The records on this page, in the order the list promises. Empty when nothing matched.

12 fields of ConsentToken
id string required

The token's identifier, starting with anchor_pro_consent_. POST /v1/identity/consent_tokens returns it and it never changes; send it as consent_token_id at POST /v1/identity/verifications.

object always "consent_token" required

Always consent_token. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

subject_ref string required

Your opaque reference to the person, exactly as you sent subject_ref at POST /v1/identity/consent_tokens. Not a name and not an identifier.

purpose string required

What the subject agreed their data may be used for, as you stated it, for example employment_verification. This token covers no other purpose.

checks array of CheckKind required

The checks the subject agreed to, from government_identifier, bank_identifier, date_of_birth_match, name_match and contactability. A check not listed here is not authorised by this token.

status string required

Whether the token still authorises anything: active does, withdrawn means you or the subject took it back, expired means expires_at has passed. Only an active token authorises a check.

activewithdrawnexpired
wording_version string optional

The exact wording the subject saw. What someone agreed to is answered from the record, not from whatever the current page says.

collected_channel string optional

How the consent was collected, as you sent it at POST /v1/identity/consent_tokens: api through your integration, self_serve by the subject themselves, assisted by someone enrolling them, or whatsapp over WhatsApp.

apiself_serveassistedwhatsapp
collected_at string · date-time optional

When the subject gave this consent, as an RFC 3339 timestamp in UTC.

expires_at string · date-time required

When this consent lapses, as an RFC 3339 timestamp in UTC. After that moment the token's status is expired and it authorises nothing.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/consent_tokens" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityConsentTokensList({});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/consent_tokens', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_consent_tokens_list()
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/consent_tokens',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityConsentTokensList();
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/consent_tokens');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityConsentTokensList();
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/consent_tokens"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityConsentTokensList();
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/consent_tokens");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityConsentTokensList(ctx).Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/consent_tokens", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "list",
  "data": [
    {
      "id": "anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "consent_token",
      "livemode": true,
      "mocked": true,
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "purpose": "employment_verification",
      "checks": [
        "government_identifier"
      ],
      "status": "active",
      "expires_at": "2026-09-01T09:00:00Z",
      "wording_version": "2026.08.1",
      "collected_channel": "api",
      "collected_at": "2026-09-01T09:00:00Z"
    }
  ],
  "has_more": true
}
POST/v1/identity/consent_tokens#

Record consent before anything is checked

identity.consent_tokens.create

Send the subject, the purpose and the specific checks, and you get one verifiable token binding them to your organisation. Nothing can be queried without it.

Scope it narrowly. A token for a government identifier check doesn't authorise a bank identifier check, and asking for more than you need is the first thing a regulator looks at.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

subject_ref string required

Your opaque reference to the person whose consent you are recording. Choose it yourself and send the same value as subject_ref at POST /v1/identity/verifications; not a name and not an identifier.

purpose string required

What you will use the subject's data for, as they were told, for example employment_verification. The token covers this purpose and no other, so state it exactly.

checks array of CheckKind required

The checks this consent covers, at least one, from government_identifier, bank_identifier, date_of_birth_match, name_match and contactability. Ask for the ones you need and no more.

wording_version string required

The version of the consent wording the subject saw, for example 2026.08.1. Keep it exact: it's how you later show what they agreed to.

collected_channel string optional

How you collected the consent: api through your integration, self_serve by the subject themselves, assisted by someone enrolling them, or whatsapp over WhatsApp. It comes back unchanged on the token.

apiself_serveassistedwhatsapp
expires_at string · date-time optional

When this consent should lapse, as an RFC 3339 timestamp in UTC. After that moment the token authorises nothing.

Returns

The consent token.

id string required

The token's identifier, starting with anchor_pro_consent_. POST /v1/identity/consent_tokens returns it and it never changes; send it as consent_token_id at POST /v1/identity/verifications.

object always "consent_token" required

Always consent_token. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

subject_ref string required

Your opaque reference to the person, exactly as you sent subject_ref at POST /v1/identity/consent_tokens. Not a name and not an identifier.

purpose string required

What the subject agreed their data may be used for, as you stated it, for example employment_verification. This token covers no other purpose.

checks array of CheckKind required

The checks the subject agreed to, from government_identifier, bank_identifier, date_of_birth_match, name_match and contactability. A check not listed here is not authorised by this token.

status string required

Whether the token still authorises anything: active does, withdrawn means you or the subject took it back, expired means expires_at has passed. Only an active token authorises a check.

activewithdrawnexpired
wording_version string optional

The exact wording the subject saw. What someone agreed to is answered from the record, not from whatever the current page says.

collected_channel string optional

How the consent was collected, as you sent it at POST /v1/identity/consent_tokens: api through your integration, self_serve by the subject themselves, assisted by someone enrolling them, or whatsapp over WhatsApp.

apiself_serveassistedwhatsapp
collected_at string · date-time optional

When the subject gave this consent, as an RFC 3339 timestamp in UTC.

expires_at string · date-time required

When this consent lapses, as an RFC 3339 timestamp in UTC. After that moment the token's status is expired and it authorises nothing.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/consent_tokens" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","purpose":"employment_verification","checks":["government_identifier"],"wording_version":"2026.08.1","collected_channel":"api","expires_at":"2026-09-01T09:00:00Z"}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityConsentTokensCreate({
  idempotencyKey: crypto.randomUUID(),
  anchorConsentTokenCreateRequest: {"subjectRef":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","purpose":"employment_verification","checks":["government_identifier"],"wordingVersion":"2026.08.1","collectedChannel":"api","expiresAt":"2026-09-01T09:00:00Z"},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/consent_tokens', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "purpose": "employment_verification",
    "checks": [
      "government_identifier"
    ],
    "wording_version": "2026.08.1",
    "collected_channel": "api",
    "expires_at": "2026-09-01T09:00:00Z"
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_consent_tokens_create(body={"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "purpose": "employment_verification", "checks": ["government_identifier"], "wording_version": "2026.08.1", "collected_channel": "api", "expires_at": "2026-09-01T09:00:00Z"})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/consent_tokens',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "purpose": "employment_verification", "checks": ["government_identifier"], "wording_version": "2026.08.1", "collected_channel": "api", "expires_at": "2026-09-01T09:00:00Z"},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityConsentTokensCreate($idempotencyKey, json_decode('{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","purpose":"employment_verification","checks":["government_identifier"],"wording_version":"2026.08.1","collected_channel":"api","expires_at":"2026-09-01T09:00:00Z"}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/consent_tokens');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","purpose":"employment_verification","checks":["government_identifier"],"wording_version":"2026.08.1","collected_channel":"api","expires_at":"2026-09-01T09:00:00Z"}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityConsentTokensCreate(idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/consent_tokens"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "purpose": "employment_verification",
          "checks": [
            "government_identifier"
          ],
          "wording_version": "2026.08.1",
          "collected_channel": "api",
          "expires_at": "2026-09-01T09:00:00Z"
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityConsentTokensCreate(idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/consent_tokens");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "purpose": "employment_verification",
      "checks": [
        "government_identifier"
      ],
      "wording_version": "2026.08.1",
      "collected_channel": "api",
      "expires_at": "2026-09-01T09:00:00Z"
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityConsentTokensCreate(ctx).IdempotencyKey(key).AnchorConsentTokenCreateRequest(body).Execute()
body := strings.NewReader(`{
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "purpose": "employment_verification",
  "checks": [
    "government_identifier"
  ],
  "wording_version": "2026.08.1",
  "collected_channel": "api",
  "expires_at": "2026-09-01T09:00:00Z"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/consent_tokens", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "consent_token",
  "livemode": true,
  "mocked": true,
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "purpose": "employment_verification",
  "checks": [
    "government_identifier"
  ],
  "status": "active",
  "expires_at": "2026-09-01T09:00:00Z",
  "wording_version": "2026.08.1",
  "collected_channel": "api",
  "collected_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/consent_tokens/{consent_token_id}#

Retrieve a consent token

identity.consent_tokens.retrieve

You get what was consented to, by whom, when and in what wording.

Path parameters

consent_token_id string required

The consent token's identifier, starting with anchor_pro_consent_: the id returned by POST /v1/identity/consent_tokens, or of any token listed by GET /v1/identity/consent_tokens.

Returns

The consent token.

id string required

The token's identifier, starting with anchor_pro_consent_. POST /v1/identity/consent_tokens returns it and it never changes; send it as consent_token_id at POST /v1/identity/verifications.

object always "consent_token" required

Always consent_token. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

subject_ref string required

Your opaque reference to the person, exactly as you sent subject_ref at POST /v1/identity/consent_tokens. Not a name and not an identifier.

purpose string required

What the subject agreed their data may be used for, as you stated it, for example employment_verification. This token covers no other purpose.

checks array of CheckKind required

The checks the subject agreed to, from government_identifier, bank_identifier, date_of_birth_match, name_match and contactability. A check not listed here is not authorised by this token.

status string required

Whether the token still authorises anything: active does, withdrawn means you or the subject took it back, expired means expires_at has passed. Only an active token authorises a check.

activewithdrawnexpired
wording_version string optional

The exact wording the subject saw. What someone agreed to is answered from the record, not from whatever the current page says.

collected_channel string optional

How the consent was collected, as you sent it at POST /v1/identity/consent_tokens: api through your integration, self_serve by the subject themselves, assisted by someone enrolling them, or whatsapp over WhatsApp.

apiself_serveassistedwhatsapp
collected_at string · date-time optional

When the subject gave this consent, as an RFC 3339 timestamp in UTC.

expires_at string · date-time required

When this consent lapses, as an RFC 3339 timestamp in UTC. After that moment the token's status is expired and it authorises nothing.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityConsentTokensRetrieve({ consentTokenId: 'anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_consent_tokens_retrieve(consent_token_id='anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityConsentTokensRetrieve(consent_token_id: 'anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityConsentTokensRetrieve("anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityConsentTokensRetrieve(consentTokenId: "anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityConsentTokensRetrieve(ctx, "anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "consent_token",
  "livemode": true,
  "mocked": true,
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "purpose": "employment_verification",
  "checks": [
    "government_identifier"
  ],
  "status": "active",
  "expires_at": "2026-09-01T09:00:00Z",
  "wording_version": "2026.08.1",
  "collected_channel": "api",
  "collected_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/consent_tokens/{consent_token_id}/revoke#

Withdraw consent

identity.consent_tokens.revoke

Every active disclosure resting on this token is suspended within 24 hours, and each organisation holding one is notified. The subject can do this themselves.

Path parameters

consent_token_id string required

The consent token's identifier, starting with anchor_pro_consent_: the id returned by POST /v1/identity/consent_tokens, or of any token listed by GET /v1/identity/consent_tokens.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Returns

The revoked token.

id string required

The token's identifier, starting with anchor_pro_consent_. POST /v1/identity/consent_tokens returns it and it never changes; send it as consent_token_id at POST /v1/identity/verifications.

object always "consent_token" required

Always consent_token. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

subject_ref string required

Your opaque reference to the person, exactly as you sent subject_ref at POST /v1/identity/consent_tokens. Not a name and not an identifier.

purpose string required

What the subject agreed their data may be used for, as you stated it, for example employment_verification. This token covers no other purpose.

checks array of CheckKind required

The checks the subject agreed to, from government_identifier, bank_identifier, date_of_birth_match, name_match and contactability. A check not listed here is not authorised by this token.

status string required

Whether the token still authorises anything: active does, withdrawn means you or the subject took it back, expired means expires_at has passed. Only an active token authorises a check.

activewithdrawnexpired
wording_version string optional

The exact wording the subject saw. What someone agreed to is answered from the record, not from whatever the current page says.

collected_channel string optional

How the consent was collected, as you sent it at POST /v1/identity/consent_tokens: api through your integration, self_serve by the subject themselves, assisted by someone enrolling them, or whatsapp over WhatsApp.

apiself_serveassistedwhatsapp
collected_at string · date-time optional

When the subject gave this consent, as an RFC 3339 timestamp in UTC.

expires_at string · date-time required

When this consent lapses, as an RFC 3339 timestamp in UTC. After that moment the token's status is expired and it authorises nothing.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityConsentTokensRevoke({ consentTokenId: 'anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Idempotency-Key': crypto.randomUUID(),
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_consent_tokens_revoke(consent_token_id='anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityConsentTokensRevoke(consent_token_id: 'anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityConsentTokensRevoke("anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityConsentTokensRevoke(consentTokenId: "anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityConsentTokensRevoke(ctx, "anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/consent_tokens/anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_consent_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "consent_token",
  "livemode": true,
  "mocked": true,
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "purpose": "employment_verification",
  "checks": [
    "government_identifier"
  ],
  "status": "active",
  "expires_at": "2026-09-01T09:00:00Z",
  "wording_version": "2026.08.1",
  "collected_channel": "api",
  "collected_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/verifications#

List verifications

identity.verifications.list

Your organisation's verifications, newest first.

Query parameters

limit integer optional

How many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.

starting_after string optional

The id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.

outcome string optional

Return only verifications whose outcome is this value: pending (in progress), resolved (subject identified), unresolved (a source didn't answer), blocked (consent or the blocklist stopped it). Leave it out to get every outcome.

pendingresolvedunresolvedblocked

Returns

A page of verifications.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Verification required

The records on this page, in the order the list promises. Empty when nothing matched.

16 fields of Verification
id string required

The verification's identifier, starting with anchor_pro_verification_. POST /v1/identity/verifications returns it and it never changes; pass it as verification_id wherever a call names this verification.

object always "identity_verification" required

Always identity_verification. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

outcome string required

unresolved is a real outcome and never a rejection. A source that did not answer proves nothing either way. Don't treat silence as a pass.

pendingresolvedunresolvedblocked
origin string required

How the claim arrived. The behaviour is the same whichever way it came in.

partner_apiself_serveassisted_enrolment
subject_ref string required

Your opaque reference to the person being verified, exactly as you sent subject_ref at POST /v1/identity/verifications. Not a name and not an identifier.

consent_token_id string optional

The consent token this verification ran under, as you sent it at POST /v1/identity/verifications: the id starting with anchor_pro_consent_ that POST /v1/identity/consent_tokens returned for this subject, purpose and checks.

target_assurance string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
assurance_reached one of optional

The level the evidence actually established, which can be lower than target_assurance. null when nothing has been established yet.

AssuranceLevelor
passport_id string · nullable optional

The id of the Passport this verification resolved to, starting with anchor_pro_passport_: what every module checks before it acts. Read it at GET /v1/identity/passports/{passport_id}; null until outcome is resolved.

evidence_bundle_id string · nullable optional

The id of the bundle listing every source consulted and what each said. Read it at GET /v1/identity/verifications/{verification_id}/evidence_bundle using this verification's id; null while there is nothing to show yet.

unresolved_source string · nullable optional

Named when the outcome is unresolved. Silence always names its source.

retry_after string · date-time · nullable optional

When to try again, as an RFC 3339 timestamp in UTC. Set when the outcome is unresolved; null otherwise.

blocked_because string · nullable optional

Why outcome is blocked: no_consent (no active token), consent_scope_insufficient (the token doesn't cover what was asked) or subject_blocklisted. The subject is entitled to know which; null for any other outcome.

no_consentconsent_scope_insufficientsubject_blocklistednull
created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# query parameters: limit (optional), starting_after (optional), outcome (optional)
curl -X GET "https://sandbox.droomwork.io/v1/identity/verifications?limit=25&outcome=pending" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

// query parameters: limit (optional), starting_after (optional), outcome (optional)
const result = await api.identityVerificationsList({ limit: 25, outcome: 'pending' });
// query parameters: limit (optional), starting_after (optional), outcome (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/identity/verifications?limit=25&outcome=pending', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

# query parameters: limit (optional), starting_after (optional), outcome (optional)
result = api.identity_verifications_list(limit=25, outcome='pending')
import os

import requests

# query parameters: limit (optional), starting_after (optional), outcome (optional)
response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/verifications?limit=25&outcome=pending',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

# query parameters: limit (optional), starting_after (optional), outcome (optional)
$result = $api->identityVerificationsList(limit: 25, outcome: 'pending');
<?php
// query parameters: limit (optional), starting_after (optional), outcome (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/verifications?limit=25&outcome=pending');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;
import com.droomwork.sdk.model.*;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

// query parameters: limit (optional), starting_after (optional), outcome (optional)
var result = api.identityVerificationsList(25, null, AnchorVerificationOutcome.fromValue("pending"));
// query parameters: limit (optional), starting_after (optional), outcome (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/verifications?limit=25&outcome=pending"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

// query parameters: limit (optional), starting_after (optional), outcome (optional)
var result = api.IdentityVerificationsList(limit: 25, outcome: AnchorVerificationOutcome.Pending);
// query parameters: limit (optional), starting_after (optional), outcome (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/verifications?limit=25&outcome=pending");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

// query parameters: limit (optional), starting_after (optional), outcome (optional)
result, _, err := client.ANCHORAPI.IdentityVerificationsList(ctx).Limit(25).Outcome(droomwork.AnchorVerificationOutcome("pending")).Execute()
// query parameters: limit (optional), starting_after (optional), outcome (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/verifications?limit=25&outcome=pending", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "list",
  "data": [
    {
      "id": "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "identity_verification",
      "livemode": true,
      "mocked": true,
      "outcome": "pending",
      "origin": "partner_api",
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "target_assurance": "dal_0",
      "assurance_reached": "dal_0",
      "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "evidence_bundle_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "unresolved_source": "example",
      "retry_after": "2026-09-01T09:00:00Z",
      "blocked_because": "no_consent",
      "created_at": "2026-09-01T09:00:00Z"
    }
  ],
  "has_more": true
}
POST/v1/identity/verifications#

Verify an identity

identity.verifications.create

One request, whether the claim arrived through your integration, a self serve form or an assisted enrolment. The behaviour is the same whichever way it came in.

State the assurance level you need, or leave it out and the minimum sufficient level is taken from your policy pack. Asking for more than the purpose requires costs you money and collects data you didn't need.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

subject_ref string required

Your opaque reference to the person: the same subject_ref you chose and sent at POST /v1/identity/consent_tokens when you recorded their consent. Not a name and not an identifier.

consent_token_id string required

The id of an active consent token for this subject, starting with anchor_pro_consent_, as returned by POST /v1/identity/consent_tokens. Its purpose and checks must cover what you are asking; without one, nothing is queried.

origin string optional

How the claim arrived. The behaviour is the same whichever way it came in.

partner_apiself_serveassisted_enrolment
target_assurance string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
claims object required

What the person says about themselves. Identifiers you submit here never come back in full.

5 fields
full_name string optional

The person's full name as they give it. For dal_2 it's matched on name against the government identifier, so send it as it appears on their record.

date_of_birth string · date optional

The person's date of birth as they give it, as YYYY-MM-DD. For dal_2 it's matched against the government identifier alongside the name.

phone string optional

The phone number the person says is theirs. Proving it reaches them is the contactability check, and reaching dal_1 means it did.

government_identifier string · write only optional

Write only. Accepted here, never returned anywhere.

bank_identifier string · write only optional

Write only. Accepted here, never returned anywhere.

Returns

The verification, resolved or pending.

id string required

The verification's identifier, starting with anchor_pro_verification_. POST /v1/identity/verifications returns it and it never changes; pass it as verification_id wherever a call names this verification.

object always "identity_verification" required

Always identity_verification. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

outcome string required

unresolved is a real outcome and never a rejection. A source that did not answer proves nothing either way. Don't treat silence as a pass.

pendingresolvedunresolvedblocked
origin string required

How the claim arrived. The behaviour is the same whichever way it came in.

partner_apiself_serveassisted_enrolment
subject_ref string required

Your opaque reference to the person being verified, exactly as you sent subject_ref at POST /v1/identity/verifications. Not a name and not an identifier.

consent_token_id string optional

The consent token this verification ran under, as you sent it at POST /v1/identity/verifications: the id starting with anchor_pro_consent_ that POST /v1/identity/consent_tokens returned for this subject, purpose and checks.

target_assurance string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
assurance_reached one of optional

The level the evidence actually established, which can be lower than target_assurance. null when nothing has been established yet.

AssuranceLevelor
passport_id string · nullable optional

The id of the Passport this verification resolved to, starting with anchor_pro_passport_: what every module checks before it acts. Read it at GET /v1/identity/passports/{passport_id}; null until outcome is resolved.

evidence_bundle_id string · nullable optional

The id of the bundle listing every source consulted and what each said. Read it at GET /v1/identity/verifications/{verification_id}/evidence_bundle using this verification's id; null while there is nothing to show yet.

unresolved_source string · nullable optional

Named when the outcome is unresolved. Silence always names its source.

retry_after string · date-time · nullable optional

When to try again, as an RFC 3339 timestamp in UTC. Set when the outcome is unresolved; null otherwise.

blocked_because string · nullable optional

Why outcome is blocked: no_consent (no active token), consent_scope_insufficient (the token doesn't cover what was asked) or subject_blocklisted. The subject is entitled to know which; null for any other outcome.

no_consentconsent_scope_insufficientsubject_blocklistednull
created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/verifications" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","consent_token_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","claims":{"full_name":"Rivers State Internal Revenue Service","date_of_birth":"2026-09-01","phone":"example","government_identifier":"example","bank_identifier":"example"},"origin":"partner_api","target_assurance":"dal_0"}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityVerificationsCreate({
  idempotencyKey: crypto.randomUUID(),
  anchorVerificationCreateRequest: {"subjectRef":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","consentTokenId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","claims":{"fullName":"Rivers State Internal Revenue Service","dateOfBirth":"2026-09-01","phone":"example","governmentIdentifier":"example","bankIdentifier":"example"},"origin":"partner_api","targetAssurance":"dal_0"},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/verifications', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "claims": {
      "full_name": "Rivers State Internal Revenue Service",
      "date_of_birth": "2026-09-01",
      "phone": "example",
      "government_identifier": "example",
      "bank_identifier": "example"
    },
    "origin": "partner_api",
    "target_assurance": "dal_0"
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_verifications_create(body={"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "claims": {"full_name": "Rivers State Internal Revenue Service", "date_of_birth": "2026-09-01", "phone": "example", "government_identifier": "example", "bank_identifier": "example"}, "origin": "partner_api", "target_assurance": "dal_0"})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/verifications',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "claims": {"full_name": "Rivers State Internal Revenue Service", "date_of_birth": "2026-09-01", "phone": "example", "government_identifier": "example", "bank_identifier": "example"}, "origin": "partner_api", "target_assurance": "dal_0"},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityVerificationsCreate($idempotencyKey, json_decode('{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","consent_token_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","claims":{"full_name":"Rivers State Internal Revenue Service","date_of_birth":"2026-09-01","phone":"example","government_identifier":"example","bank_identifier":"example"},"origin":"partner_api","target_assurance":"dal_0"}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/verifications');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","consent_token_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","claims":{"full_name":"Rivers State Internal Revenue Service","date_of_birth":"2026-09-01","phone":"example","government_identifier":"example","bank_identifier":"example"},"origin":"partner_api","target_assurance":"dal_0"}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityVerificationsCreate(idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/verifications"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "claims": {
            "full_name": "Rivers State Internal Revenue Service",
            "date_of_birth": "2026-09-01",
            "phone": "example",
            "government_identifier": "example",
            "bank_identifier": "example"
          },
          "origin": "partner_api",
          "target_assurance": "dal_0"
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityVerificationsCreate(idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/verifications");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "claims": {
        "full_name": "Rivers State Internal Revenue Service",
        "date_of_birth": "2026-09-01",
        "phone": "example",
        "government_identifier": "example",
        "bank_identifier": "example"
      },
      "origin": "partner_api",
      "target_assurance": "dal_0"
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityVerificationsCreate(ctx).IdempotencyKey(key).AnchorVerificationCreateRequest(body).Execute()
body := strings.NewReader(`{
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "claims": {
    "full_name": "Rivers State Internal Revenue Service",
    "date_of_birth": "2026-09-01",
    "phone": "example",
    "government_identifier": "example",
    "bank_identifier": "example"
  },
  "origin": "partner_api",
  "target_assurance": "dal_0"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/verifications", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "identity_verification",
  "livemode": true,
  "mocked": true,
  "outcome": "pending",
  "origin": "partner_api",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "target_assurance": "dal_0",
  "assurance_reached": "dal_0",
  "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "evidence_bundle_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "unresolved_source": "example",
  "retry_after": "2026-09-01T09:00:00Z",
  "blocked_because": "no_consent",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/verifications/{verification_id}#

Retrieve a verification

identity.verifications.retrieve

You get the outcome and the assurance level reached. An outcome of unresolved names the source that didn't answer and when to try again.

Path parameters

verification_id string required

The verification's identifier, starting with anchor_pro_verification_: the id returned by POST /v1/identity/verifications or listed by GET /v1/identity/verifications, or a batch result's verification_id.

Returns

The verification.

id string required

The verification's identifier, starting with anchor_pro_verification_. POST /v1/identity/verifications returns it and it never changes; pass it as verification_id wherever a call names this verification.

object always "identity_verification" required

Always identity_verification. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

outcome string required

unresolved is a real outcome and never a rejection. A source that did not answer proves nothing either way. Don't treat silence as a pass.

pendingresolvedunresolvedblocked
origin string required

How the claim arrived. The behaviour is the same whichever way it came in.

partner_apiself_serveassisted_enrolment
subject_ref string required

Your opaque reference to the person being verified, exactly as you sent subject_ref at POST /v1/identity/verifications. Not a name and not an identifier.

consent_token_id string optional

The consent token this verification ran under, as you sent it at POST /v1/identity/verifications: the id starting with anchor_pro_consent_ that POST /v1/identity/consent_tokens returned for this subject, purpose and checks.

target_assurance string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
assurance_reached one of optional

The level the evidence actually established, which can be lower than target_assurance. null when nothing has been established yet.

AssuranceLevelor
passport_id string · nullable optional

The id of the Passport this verification resolved to, starting with anchor_pro_passport_: what every module checks before it acts. Read it at GET /v1/identity/passports/{passport_id}; null until outcome is resolved.

evidence_bundle_id string · nullable optional

The id of the bundle listing every source consulted and what each said. Read it at GET /v1/identity/verifications/{verification_id}/evidence_bundle using this verification's id; null while there is nothing to show yet.

unresolved_source string · nullable optional

Named when the outcome is unresolved. Silence always names its source.

retry_after string · date-time · nullable optional

When to try again, as an RFC 3339 timestamp in UTC. Set when the outcome is unresolved; null otherwise.

blocked_because string · nullable optional

Why outcome is blocked: no_consent (no active token), consent_scope_insufficient (the token doesn't cover what was asked) or subject_blocklisted. The subject is entitled to know which; null for any other outcome.

no_consentconsent_scope_insufficientsubject_blocklistednull
created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityVerificationsRetrieve({ verificationId: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_verifications_retrieve(verification_id='anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityVerificationsRetrieve(verification_id: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityVerificationsRetrieve("anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityVerificationsRetrieve(verificationId: "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityVerificationsRetrieve(ctx, "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "identity_verification",
  "livemode": true,
  "mocked": true,
  "outcome": "pending",
  "origin": "partner_api",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "target_assurance": "dal_0",
  "assurance_reached": "dal_0",
  "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "evidence_bundle_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "unresolved_source": "example",
  "retry_after": "2026-09-01T09:00:00Z",
  "blocked_because": "no_consent",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/verifications/{verification_id}/evidence_bundle#

Retrieve the evidence bundle for a verification

identity.evidence_bundles.retrieve

Every source consulted, what it said, when, which provider, the policy pack version applied and who adjudicated. It never changes once written.

The bundle names sources and outcomes, never the underlying records. Keep it, and hand it to an auditor when asked.

Path parameters

verification_id string required

The verification's identifier, starting with anchor_pro_verification_: the id returned by POST /v1/identity/verifications or listed by GET /v1/identity/verifications, or a batch result's verification_id.

Returns

The evidence bundle.

id string required

The bundle's identifier. It never changes, and it is the value carried as evidence_bundle_id on the verification at GET /v1/identity/verifications/{verification_id} and in evidence_bundle_ids on the Passport.

object always "evidence_bundle" required

Always evidence_bundle. Tells you which kind of record you are looking at, so one handler can read any response.

verification_id string required

The id of the verification this bundle was written for, starting with anchor_pro_verification_, as returned by POST /v1/identity/verifications. One bundle per verification, and it never changes once written.

entries array of object required

One entry per source consulted: which source, what it answered, when, through which provider, and whether evidence still inside its validity period was reused. Never the record behind the answer.

5 fields
source string required

Which source was consulted, for example national_identity_register. Names the source, never what it holds.

result string required

What the source answered: match, no_match, partial_match when only part of the claim matched, or unresolved when it didn't answer. unresolved proves nothing either way.

matchno_matchpartial_matchunresolved
queried_at string · date-time required

When the source was consulted, as an RFC 3339 timestamp in UTC.

provider string required

Which provider answered for this source. You can show an auditor who said what, not only which source was asked.

cached boolean optional

True when evidence inside its validity period was reused rather than re-charged.

policy_pack_version string required

The version of your policy pack in force when this verification was judged, for example 2026.08.1. Read the bundle against that version, not the current one.

adjudicator string · nullable optional

Named where a person decided rather than a rule.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/evidence_bundle" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityEvidenceBundlesRetrieve({ verificationId: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/evidence_bundle', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_evidence_bundles_retrieve(verification_id='anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/evidence_bundle',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityEvidenceBundlesRetrieve(verification_id: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/evidence_bundle');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityEvidenceBundlesRetrieve("anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/evidence_bundle"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityEvidenceBundlesRetrieve(verificationId: "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/evidence_bundle");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityEvidenceBundlesRetrieve(ctx, "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/evidence_bundle", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "evidence_bundle",
  "verification_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "entries": [
    {
      "source": "national_identity_register",
      "result": "match",
      "queried_at": "2026-09-01T09:00:00Z",
      "provider": "example",
      "cached": true
    }
  ],
  "policy_pack_version": "2026.08.1",
  "adjudicator": "example",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/verification_batches#

Verify many identities at once

identity.verification_batches.create

Each subject resolves on its own. One subject blocked on missing consent never stalls the rest: send five hundred with three problems and you get four hundred and ninety seven results and three explanations.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

subjects array of VerificationCreateRequest required

The subjects to verify, at least one, each in the shape of a single verification request. Each resolves on its own, so one that can't proceed never holds up the rest.

5 fields of VerificationCreateRequest
subject_ref string required

Your opaque reference to the person: the same subject_ref you chose and sent at POST /v1/identity/consent_tokens when you recorded their consent. Not a name and not an identifier.

consent_token_id string required

The id of an active consent token for this subject, starting with anchor_pro_consent_, as returned by POST /v1/identity/consent_tokens. Its purpose and checks must cover what you are asking; without one, nothing is queried.

origin string optional

How the claim arrived. The behaviour is the same whichever way it came in.

partner_apiself_serveassisted_enrolment
target_assurance string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
claims object required

What the person says about themselves. Identifiers you submit here never come back in full.

5 fields
full_name string optional

The person's full name as they give it. For dal_2 it's matched on name against the government identifier, so send it as it appears on their record.

date_of_birth string · date optional

The person's date of birth as they give it, as YYYY-MM-DD. For dal_2 it's matched against the government identifier alongside the name.

phone string optional

The phone number the person says is theirs. Proving it reaches them is the contactability check, and reaching dal_1 means it did.

government_identifier string · write only optional

Write only. Accepted here, never returned anywhere.

bank_identifier string · write only optional

Write only. Accepted here, never returned anywhere.

Returns

The batch, resolving per subject.

id string required

The batch's identifier, starting with anchor_pro_verification_. POST /v1/identity/verification_batches returns it and it never changes; pass it as batch_id to GET /v1/identity/verification_batches/{batch_id}.

object always "verification_batch" required

Always verification_batch. Tells you which kind of record you are looking at, so one handler can read any response.

status string required

Where the batch stands: running while any subject's outcome is still pending, completed once none is. Read results for each subject's outcome.

runningcompleted
subject_count integer required

How many subjects you sent in this batch. results carries one entry for each of them.

results array of object required

One entry per subject, resolved independently. A subject that could not proceed carries the reason and does not stall the others.

4 fields
subject_ref string required

The subject this entry is for: your opaque reference, exactly as you sent it in subjects[].subject_ref at POST /v1/identity/verification_batches. Not a name and not an identifier.

verification_id string · nullable optional

The id of the verification opened for this subject, starting with anchor_pro_verification_; read it in full at GET /v1/identity/verifications/{verification_id}. null when none was opened.

outcome string required

unresolved is a real outcome and never a rejection. A source that did not answer proves nothing either way. Don't treat silence as a pass.

pendingresolvedunresolvedblocked
blocked_because string · nullable optional

Why this subject could not proceed, such as no_consent, when outcome is blocked. null for a subject that went ahead.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/verification_batches" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"subjects":[{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","consent_token_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","claims":{"full_name":"Rivers State Internal Revenue Service","date_of_birth":"2026-09-01","phone":"example","government_identifier":"example","bank_identifier":"example"},"origin":"partner_api","target_assurance":"dal_0"}]}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityVerificationBatchesCreate({
  idempotencyKey: crypto.randomUUID(),
  anchorVerificationBatchCreateRequest: {"subjects":[{"subjectRef":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","consentTokenId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","claims":{"fullName":"Rivers State Internal Revenue Service","dateOfBirth":"2026-09-01","phone":"example","governmentIdentifier":"example","bankIdentifier":"example"},"origin":"partner_api","targetAssurance":"dal_0"}]},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/verification_batches', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "subjects": [
      {
        "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
        "claims": {
          "full_name": "Rivers State Internal Revenue Service",
          "date_of_birth": "2026-09-01",
          "phone": "example",
          "government_identifier": "example",
          "bank_identifier": "example"
        },
        "origin": "partner_api",
        "target_assurance": "dal_0"
      }
    ]
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_verification_batches_create(body={"subjects": [{"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "claims": {"full_name": "Rivers State Internal Revenue Service", "date_of_birth": "2026-09-01", "phone": "example", "government_identifier": "example", "bank_identifier": "example"}, "origin": "partner_api", "target_assurance": "dal_0"}]})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/verification_batches',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"subjects": [{"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "claims": {"full_name": "Rivers State Internal Revenue Service", "date_of_birth": "2026-09-01", "phone": "example", "government_identifier": "example", "bank_identifier": "example"}, "origin": "partner_api", "target_assurance": "dal_0"}]},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityVerificationBatchesCreate($idempotencyKey, json_decode('{"subjects":[{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","consent_token_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","claims":{"full_name":"Rivers State Internal Revenue Service","date_of_birth":"2026-09-01","phone":"example","government_identifier":"example","bank_identifier":"example"},"origin":"partner_api","target_assurance":"dal_0"}]}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/verification_batches');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"subjects":[{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","consent_token_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","claims":{"full_name":"Rivers State Internal Revenue Service","date_of_birth":"2026-09-01","phone":"example","government_identifier":"example","bank_identifier":"example"},"origin":"partner_api","target_assurance":"dal_0"}]}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityVerificationBatchesCreate(idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/verification_batches"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "subjects": [
            {
              "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
              "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
              "claims": {
                "full_name": "Rivers State Internal Revenue Service",
                "date_of_birth": "2026-09-01",
                "phone": "example",
                "government_identifier": "example",
                "bank_identifier": "example"
              },
              "origin": "partner_api",
              "target_assurance": "dal_0"
            }
          ]
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityVerificationBatchesCreate(idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/verification_batches");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "subjects": [
        {
          "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "claims": {
            "full_name": "Rivers State Internal Revenue Service",
            "date_of_birth": "2026-09-01",
            "phone": "example",
            "government_identifier": "example",
            "bank_identifier": "example"
          },
          "origin": "partner_api",
          "target_assurance": "dal_0"
        }
      ]
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityVerificationBatchesCreate(ctx).IdempotencyKey(key).AnchorVerificationBatchCreateRequest(body).Execute()
body := strings.NewReader(`{
  "subjects": [
    {
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "claims": {
        "full_name": "Rivers State Internal Revenue Service",
        "date_of_birth": "2026-09-01",
        "phone": "example",
        "government_identifier": "example",
        "bank_identifier": "example"
      },
      "origin": "partner_api",
      "target_assurance": "dal_0"
    }
  ]
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/verification_batches", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "verification_batch",
  "status": "running",
  "subject_count": 1,
  "results": [
    {
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "outcome": "pending",
      "verification_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "blocked_because": "example"
    }
  ]
}
GET/v1/identity/verification_batches/{batch_id}#

Retrieve a verification batch

identity.verification_batches.retrieve

You get an outcome per subject, including the ones that couldn't proceed and why.

Path parameters

batch_id string required

The batch's identifier, starting with anchor_pro_verification_: the id returned by POST /v1/identity/verification_batches when you created the batch.

Returns

The batch.

id string required

The batch's identifier, starting with anchor_pro_verification_. POST /v1/identity/verification_batches returns it and it never changes; pass it as batch_id to GET /v1/identity/verification_batches/{batch_id}.

object always "verification_batch" required

Always verification_batch. Tells you which kind of record you are looking at, so one handler can read any response.

status string required

Where the batch stands: running while any subject's outcome is still pending, completed once none is. Read results for each subject's outcome.

runningcompleted
subject_count integer required

How many subjects you sent in this batch. results carries one entry for each of them.

results array of object required

One entry per subject, resolved independently. A subject that could not proceed carries the reason and does not stall the others.

4 fields
subject_ref string required

The subject this entry is for: your opaque reference, exactly as you sent it in subjects[].subject_ref at POST /v1/identity/verification_batches. Not a name and not an identifier.

verification_id string · nullable optional

The id of the verification opened for this subject, starting with anchor_pro_verification_; read it in full at GET /v1/identity/verifications/{verification_id}. null when none was opened.

outcome string required

unresolved is a real outcome and never a rejection. A source that did not answer proves nothing either way. Don't treat silence as a pass.

pendingresolvedunresolvedblocked
blocked_because string · nullable optional

Why this subject could not proceed, such as no_consent, when outcome is blocked. null for a subject that went ahead.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/verification_batches/%7Bbatch_id%7D" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityVerificationBatchesRetrieve({ batchId: '{batch_id}' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/verification_batches/%7Bbatch_id%7D', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_verification_batches_retrieve(batch_id='{batch_id}')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/verification_batches/%7Bbatch_id%7D',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityVerificationBatchesRetrieve(batch_id: '{batch_id}');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/verification_batches/%7Bbatch_id%7D');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityVerificationBatchesRetrieve("{batch_id}");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/verification_batches/%7Bbatch_id%7D"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityVerificationBatchesRetrieve(batchId: "{batch_id}");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/verification_batches/%7Bbatch_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityVerificationBatchesRetrieve(ctx, "{batch_id}").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/verification_batches/%7Bbatch_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "verification_batch",
  "status": "running",
  "subject_count": 1,
  "results": [
    {
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "outcome": "pending",
      "verification_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "blocked_because": "example"
    }
  ]
}
GET/v1/identity/sources#

List the sources ANCHOR can consult

identity.sources.list

Each source tells you what it can establish, its current health and how long its evidence stays valid.

You don't choose the source; we do. We pick the cheapest healthy source sufficient for the level, reuse evidence still inside its validity period rather than querying and charging you again, and fail over to an alternate on our own.

Query parameters

limit integer optional

How many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.

Returns

A page of sources.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Source required

The records on this page, in the order the list promises. Empty when nothing matched.

7 fields of Source
id string required

The source's identifier, starting with anchor_pro_verification_. It never changes, and GET /v1/identity/sources is the only call that returns it; you never send it, because we pick the source for each check.

object always "identity_source" required

Always identity_source. Tells you which kind of record you are looking at, so one handler can read any response.

name string required

The source's name, for people to read. You never choose a source by name; we pick one for each check.

establishes array of CheckKind required

The checks this source can establish, such as government_identifier or contactability. One source may establish several.

max_assurance string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
health string required

Whether the source is answering right now: healthy, degraded (answering, but not reliably) or unavailable (not answering). A source that doesn't answer never fails a verification; the outcome is unresolved, naming it.

healthydegradedunavailable
evidence_validity_days integer optional

How long evidence from this source stays usable before it must be re-queried.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# query parameters: limit (optional)
curl -X GET "https://sandbox.droomwork.io/v1/identity/sources?limit=25" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

// query parameters: limit (optional)
const result = await api.identitySourcesList({ limit: 25 });
// query parameters: limit (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/identity/sources?limit=25', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

# query parameters: limit (optional)
result = api.identity_sources_list(limit=25)
import os

import requests

# query parameters: limit (optional)
response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/sources?limit=25',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

# query parameters: limit (optional)
$result = $api->identitySourcesList(limit: 25);
<?php
// query parameters: limit (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/sources?limit=25');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

// query parameters: limit (optional)
var result = api.identitySourcesList(25);
// query parameters: limit (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/sources?limit=25"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

// query parameters: limit (optional)
var result = api.IdentitySourcesList(limit: 25);
// query parameters: limit (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/sources?limit=25");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

// query parameters: limit (optional)
result, _, err := client.ANCHORAPI.IdentitySourcesList(ctx).Limit(25).Execute()
// query parameters: limit (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/sources?limit=25", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "list",
  "data": [
    {
      "id": "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "identity_source",
      "name": "Rivers State Internal Revenue Service",
      "establishes": [
        "government_identifier"
      ],
      "health": "healthy",
      "max_assurance": "dal_0",
      "evidence_validity_days": 1
    }
  ],
  "has_more": true
}
GET/v1/identity/passports#

List Passports

identity.passports.list

The Passports your organisation holds a live disclosure for.

Query parameters

limit integer optional

How many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.

starting_after string optional

The id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.

assurance_level string optional

Return only Passports whose assurance_level is this value: dal_0 claimed, dal_1 contactable, dal_2 matched against a government identifier, dal_3 and dal_4 not in this release. Leave it out to list every level.

dal_0dal_1dal_2dal_3dal_4

Returns

A page of Passports.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Passport required

The records on this page, in the order the list promises. Empty when nothing matched.

14 fields of Passport
id string required

The Passport's identifier, starting with anchor_pro_passport_. It never changes: it's the passport_id on a resolved verification or the id POST /v1/identity/passports returns; pass it to GET /v1/identity/passports/{passport_id}.

object always "passport" required

Always passport. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

subject_ref string required

Your opaque reference to the person this Passport belongs to: the subject_ref you sent at POST /v1/identity/verifications on the verification that resolved into it. Not a name and not an identifier.

assurance_level string required

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
assurance string optional

How a fact was established. Recorded on the fact rather than in configuration, so an attested identity and a verified one stay distinguishable a year later, which is the distinction that matters when something is disputed.

attestedverified
status string required
livedowngradedrevoked
identifiers_held array of object optional

Which identifiers are on file, masked. Enough to tell a subject what you hold, never enough to use it.

2 fields
kind string required

What a consent token may authorise. Ask for what you need and no more.

government_identifierbank_identifierdate_of_birth_matchname_matchcontactability
masked string required

An identity number, masked. This is the only form in which any identifier leaves ANCHOR. The full value is never returned to you, on any endpoint, at any assurance level, to any credential. There is no parameter that widens this and no scope that reveals it. If you need to show a subject which of their identifiers you hold, show them this.

disqualifying_flag boolean optional

Whether something disqualifying exists. Whether, not what. The detail is not yours to see.

evidence_bundle_ids array of string optional

The evidence bundles behind this level, one per verification that contributed. Each names the sources consulted and what they returned, never the records behind them.

monitoring string optional

Whether this subject is still watched after verification: active means yes, paused means watching has stopped. A change that lowers or revokes the Passport reaches you as a passport.downgraded or passport.revoked event.

activepaused
valid_until string · date-time required

When the supporting evidence lapses and the level falls on its own.

issued_at string · date-time optional

When the Passport was first issued, as an RFC 3339 timestamp in UTC. Normally the moment the first verification resolved.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# query parameters: limit (optional), starting_after (optional), assurance_level (optional)
curl -X GET "https://sandbox.droomwork.io/v1/identity/passports?limit=25&assurance_level=dal_0" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

// query parameters: limit (optional), starting_after (optional), assurance_level (optional)
const result = await api.identityPassportsList({ limit: 25, assuranceLevel: 'dal_0' });
// query parameters: limit (optional), starting_after (optional), assurance_level (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/identity/passports?limit=25&assurance_level=dal_0', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

# query parameters: limit (optional), starting_after (optional), assurance_level (optional)
result = api.identity_passports_list(limit=25, assurance_level='dal_0')
import os

import requests

# query parameters: limit (optional), starting_after (optional), assurance_level (optional)
response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/passports?limit=25&assurance_level=dal_0',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

# query parameters: limit (optional), starting_after (optional), assurance_level (optional)
$result = $api->identityPassportsList(limit: 25, assurance_level: 'dal_0');
<?php
// query parameters: limit (optional), starting_after (optional), assurance_level (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/passports?limit=25&assurance_level=dal_0');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;
import com.droomwork.sdk.model.*;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

// query parameters: limit (optional), starting_after (optional), assurance_level (optional)
var result = api.identityPassportsList(25, null, AnchorAssuranceLevel.fromValue("dal_0"));
// query parameters: limit (optional), starting_after (optional), assurance_level (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/passports?limit=25&assurance_level=dal_0"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

// query parameters: limit (optional), starting_after (optional), assurance_level (optional)
var result = api.IdentityPassportsList(limit: 25, assuranceLevel: AnchorAssuranceLevel.Dal_0);
// query parameters: limit (optional), starting_after (optional), assurance_level (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/passports?limit=25&assurance_level=dal_0");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

// query parameters: limit (optional), starting_after (optional), assurance_level (optional)
result, _, err := client.ANCHORAPI.IdentityPassportsList(ctx).Limit(25).AssuranceLevel(droomwork.AnchorAssuranceLevel("dal_0")).Execute()
// query parameters: limit (optional), starting_after (optional), assurance_level (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/passports?limit=25&assurance_level=dal_0", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "list",
  "data": [
    {
      "id": "anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "passport",
      "livemode": true,
      "mocked": true,
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "assurance_level": "dal_0",
      "status": "live",
      "valid_until": "2026-09-01T09:00:00Z",
      "assurance": "attested",
      "identifiers_held": [
        {
          "kind": "government_identifier",
          "masked": "*******4821"
        }
      ],
      "disqualifying_flag": true,
      "evidence_bundle_ids": [
        "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
      ],
      "monitoring": "active",
      "issued_at": "2026-09-01T09:00:00Z"
    }
  ],
  "has_more": true
}
POST/v1/identity/passports#

Create an identity passport

identity.passports.create

A Passport normally appears when a verification resolves. Create one directly to bring in a subject you verified before Droomwork, at the assurance level your evidence supports. State the level; it isn't assumed.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body optional

assurance_level string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4

Returns

The passport.

id string required

The Passport's identifier, starting with anchor_pro_passport_. It never changes: it's the passport_id on a resolved verification or the id POST /v1/identity/passports returns; pass it to GET /v1/identity/passports/{passport_id}.

object always "passport" required

Always passport. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

subject_ref string required

Your opaque reference to the person this Passport belongs to: the subject_ref you sent at POST /v1/identity/verifications on the verification that resolved into it. Not a name and not an identifier.

assurance_level string required

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
assurance string optional

How a fact was established. Recorded on the fact rather than in configuration, so an attested identity and a verified one stay distinguishable a year later, which is the distinction that matters when something is disputed.

attestedverified
status string required
livedowngradedrevoked
identifiers_held array of object optional

Which identifiers are on file, masked. Enough to tell a subject what you hold, never enough to use it.

2 fields
kind string required

What a consent token may authorise. Ask for what you need and no more.

government_identifierbank_identifierdate_of_birth_matchname_matchcontactability
masked string required

An identity number, masked. This is the only form in which any identifier leaves ANCHOR. The full value is never returned to you, on any endpoint, at any assurance level, to any credential. There is no parameter that widens this and no scope that reveals it. If you need to show a subject which of their identifiers you hold, show them this.

disqualifying_flag boolean optional

Whether something disqualifying exists. Whether, not what. The detail is not yours to see.

evidence_bundle_ids array of string optional

The evidence bundles behind this level, one per verification that contributed. Each names the sources consulted and what they returned, never the records behind them.

monitoring string optional

Whether this subject is still watched after verification: active means yes, paused means watching has stopped. A change that lowers or revokes the Passport reaches you as a passport.downgraded or passport.revoked event.

activepaused
valid_until string · date-time required

When the supporting evidence lapses and the level falls on its own.

issued_at string · date-time optional

When the Passport was first issued, as an RFC 3339 timestamp in UTC. Normally the moment the first verification resolved.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/passports" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"assurance_level":"dal_0"}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityPassportsCreate({});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/passports', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "assurance_level": "dal_0"
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_passports_create()
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/passports',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"assurance_level": "dal_0"},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityPassportsCreate();
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/passports');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"assurance_level":"dal_0"}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityPassportsCreate();
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/passports"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "assurance_level": "dal_0"
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityPassportsCreate();
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/passports");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "assurance_level": "dal_0"
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityPassportsCreate(ctx).Execute()
body := strings.NewReader(`{
  "assurance_level": "dal_0"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/passports", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "passport",
  "livemode": true,
  "mocked": true,
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "assurance_level": "dal_0",
  "status": "live",
  "valid_until": "2026-09-01T09:00:00Z",
  "assurance": "attested",
  "identifiers_held": [
    {
      "kind": "government_identifier",
      "masked": "*******4821"
    }
  ],
  "disqualifying_flag": true,
  "evidence_bundle_ids": [
    "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  ],
  "monitoring": "active",
  "issued_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/passports/{passport_id}#

Retrieve a Passport

identity.passports.retrieve

The Passport is what every other module checks before it acts. It carries the assurance level, references to the evidence behind it, its monitoring state and how long it's good for.

The level comes from evidence that is still valid, never from a value somebody set. When evidence lapses, the level falls on its own.

Path parameters

passport_id string required

The id of the Passport, from passport_id on a resolved verification at GET /v1/identity/verifications/{verification_id} or from the response to POST /v1/identity/passports. It starts with anchor_pro_passport_.

Returns

The Passport.

id string required

The Passport's identifier, starting with anchor_pro_passport_. It never changes: it's the passport_id on a resolved verification or the id POST /v1/identity/passports returns; pass it to GET /v1/identity/passports/{passport_id}.

object always "passport" required

Always passport. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

subject_ref string required

Your opaque reference to the person this Passport belongs to: the subject_ref you sent at POST /v1/identity/verifications on the verification that resolved into it. Not a name and not an identifier.

assurance_level string required

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
assurance string optional

How a fact was established. Recorded on the fact rather than in configuration, so an attested identity and a verified one stay distinguishable a year later, which is the distinction that matters when something is disputed.

attestedverified
status string required
livedowngradedrevoked
identifiers_held array of object optional

Which identifiers are on file, masked. Enough to tell a subject what you hold, never enough to use it.

2 fields
kind string required

What a consent token may authorise. Ask for what you need and no more.

government_identifierbank_identifierdate_of_birth_matchname_matchcontactability
masked string required

An identity number, masked. This is the only form in which any identifier leaves ANCHOR. The full value is never returned to you, on any endpoint, at any assurance level, to any credential. There is no parameter that widens this and no scope that reveals it. If you need to show a subject which of their identifiers you hold, show them this.

disqualifying_flag boolean optional

Whether something disqualifying exists. Whether, not what. The detail is not yours to see.

evidence_bundle_ids array of string optional

The evidence bundles behind this level, one per verification that contributed. Each names the sources consulted and what they returned, never the records behind them.

monitoring string optional

Whether this subject is still watched after verification: active means yes, paused means watching has stopped. A change that lowers or revokes the Passport reaches you as a passport.downgraded or passport.revoked event.

activepaused
valid_until string · date-time required

When the supporting evidence lapses and the level falls on its own.

issued_at string · date-time optional

When the Passport was first issued, as an RFC 3339 timestamp in UTC. Normally the moment the first verification resolved.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/passports/anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityPassportsRetrieve({ passportId: 'anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/passports/anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_passports_retrieve(passport_id='anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/passports/anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityPassportsRetrieve(passport_id: 'anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/passports/anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityPassportsRetrieve("anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/passports/anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityPassportsRetrieve(passportId: "anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/passports/anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityPassportsRetrieve(ctx, "anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/passports/anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_passport_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "passport",
  "livemode": true,
  "mocked": true,
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "assurance_level": "dal_0",
  "status": "live",
  "valid_until": "2026-09-01T09:00:00Z",
  "assurance": "attested",
  "identifiers_held": [
    {
      "kind": "government_identifier",
      "masked": "*******4821"
    }
  ],
  "disqualifying_flag": true,
  "evidence_bundle_ids": [
    "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  ],
  "monitoring": "active",
  "issued_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/merge_candidates#

List probable duplicates awaiting adjudication

identity.merge_candidates.list

A strong identifier match merges on its own. Everything weaker lands here for you to decide.

Query parameters

limit integer optional

How many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.

starting_after string optional

The id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.

Returns

A page of candidates.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of MergeCandidate required

The records on this page, in the order the list promises. Empty when nothing matched.

8 fields of MergeCandidate
id string required

The candidate's identifier. It starts with sub_ and never changes; pass it as merge_candidate_id at GET /v1/identity/merge_candidates/{merge_candidate_id} or on POST /v1/identity/merges when you decide.

object always "merge_candidate" required

Always merge_candidate. Tells you which kind of record you are looking at, so one handler can read any response.

left_ref string required

One of the two subject_ref values that may belong to the same person, as you first sent them at POST /v1/identity/consent_tokens. Pass it as surviving_ref or merged_ref on POST /v1/identity/merges when you decide.

right_ref string required

The other subject_ref that may belong to the same person, as you first sent it at POST /v1/identity/consent_tokens. Pass it as surviving_ref or merged_ref on POST /v1/identity/merges when you decide.

strength string required

Only a strong match merges automatically. Probable is raised for you to decide.

strongprobableweak
signals array of object required

What matched and what did not. Both, so you see the case against as well as the case for.

3 fields
signal string required

Which attribute was compared, such as date_of_birth. One entry per attribute, whichever way it came out.

agrees boolean required

true when this attribute matched across the two records, false when it didn't. Read the false entries as carefully as the true ones.

detail string optional

A plain-words note on how this attribute compared, when there's more to say than agrees. Left out otherwise.

status string optional

Where the candidate stands: open awaits your decision, merged means you merged the two records at POST /v1/identity/merges, rejected means they were judged to be different people.

openmergedrejected
created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# query parameters: limit (optional), starting_after (optional)
curl -X GET "https://sandbox.droomwork.io/v1/identity/merge_candidates?limit=25" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

// query parameters: limit (optional), starting_after (optional)
const result = await api.identityMergeCandidatesList({ limit: 25 });
// query parameters: limit (optional), starting_after (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/identity/merge_candidates?limit=25', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

# query parameters: limit (optional), starting_after (optional)
result = api.identity_merge_candidates_list(limit=25)
import os

import requests

# query parameters: limit (optional), starting_after (optional)
response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/merge_candidates?limit=25',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

# query parameters: limit (optional), starting_after (optional)
$result = $api->identityMergeCandidatesList(limit: 25);
<?php
// query parameters: limit (optional), starting_after (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/merge_candidates?limit=25');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

// query parameters: limit (optional), starting_after (optional)
var result = api.identityMergeCandidatesList(25, null);
// query parameters: limit (optional), starting_after (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/merge_candidates?limit=25"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

// query parameters: limit (optional), starting_after (optional)
var result = api.IdentityMergeCandidatesList(limit: 25);
// query parameters: limit (optional), starting_after (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/merge_candidates?limit=25");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

// query parameters: limit (optional), starting_after (optional)
result, _, err := client.ANCHORAPI.IdentityMergeCandidatesList(ctx).Limit(25).Execute()
// query parameters: limit (optional), starting_after (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/merge_candidates?limit=25", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "list",
  "data": [
    {
      "id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "merge_candidate",
      "left_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "right_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "strength": "strong",
      "signals": [
        {
          "signal": "date_of_birth",
          "agrees": true,
          "detail": "The payee has no verified destination, so this line cannot be paid."
        }
      ],
      "status": "open",
      "created_at": "2026-09-01T09:00:00Z"
    }
  ],
  "has_more": true
}
GET/v1/identity/merge_candidates/{merge_candidate_id}#

Retrieve a merge candidate

identity.merge_candidates.retrieve

You get the two records with the signals that matched and the signals that didn't, so you see the case against as well as the case for.

Path parameters

merge_candidate_id string required

The id of the candidate, from an entry in GET /v1/identity/merge_candidates or from data.id on the merge_candidate.raised event that raised it. It starts with sub_.

Returns

The candidate.

id string required

The candidate's identifier. It starts with sub_ and never changes; pass it as merge_candidate_id at GET /v1/identity/merge_candidates/{merge_candidate_id} or on POST /v1/identity/merges when you decide.

object always "merge_candidate" required

Always merge_candidate. Tells you which kind of record you are looking at, so one handler can read any response.

left_ref string required

One of the two subject_ref values that may belong to the same person, as you first sent them at POST /v1/identity/consent_tokens. Pass it as surviving_ref or merged_ref on POST /v1/identity/merges when you decide.

right_ref string required

The other subject_ref that may belong to the same person, as you first sent it at POST /v1/identity/consent_tokens. Pass it as surviving_ref or merged_ref on POST /v1/identity/merges when you decide.

strength string required

Only a strong match merges automatically. Probable is raised for you to decide.

strongprobableweak
signals array of object required

What matched and what did not. Both, so you see the case against as well as the case for.

3 fields
signal string required

Which attribute was compared, such as date_of_birth. One entry per attribute, whichever way it came out.

agrees boolean required

true when this attribute matched across the two records, false when it didn't. Read the false entries as carefully as the true ones.

detail string optional

A plain-words note on how this attribute compared, when there's more to say than agrees. Left out otherwise.

status string optional

Where the candidate stands: open awaits your decision, merged means you merged the two records at POST /v1/identity/merges, rejected means they were judged to be different people.

openmergedrejected
created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/merge_candidates/%7Bmerge_candidate_id%7D" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityMergeCandidatesRetrieve({ mergeCandidateId: '{merge_candidate_id}' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/merge_candidates/%7Bmerge_candidate_id%7D', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_merge_candidates_retrieve(merge_candidate_id='{merge_candidate_id}')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/merge_candidates/%7Bmerge_candidate_id%7D',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityMergeCandidatesRetrieve(merge_candidate_id: '{merge_candidate_id}');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/merge_candidates/%7Bmerge_candidate_id%7D');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityMergeCandidatesRetrieve("{merge_candidate_id}");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/merge_candidates/%7Bmerge_candidate_id%7D"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityMergeCandidatesRetrieve(mergeCandidateId: "{merge_candidate_id}");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/merge_candidates/%7Bmerge_candidate_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityMergeCandidatesRetrieve(ctx, "{merge_candidate_id}").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/merge_candidates/%7Bmerge_candidate_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "merge_candidate",
  "left_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "right_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "strength": "strong",
  "signals": [
    {
      "signal": "date_of_birth",
      "agrees": true,
      "detail": "The payee has no verified destination, so this line cannot be paid."
    }
  ],
  "status": "open",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/merges#

Merge two identity records

identity.merges.create

On a probable match this is an adjudication decision, and it needs four eyes: two distinct actors, and never the same credential twice.

Every merge can be reversed, with a complete before and after record.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

surviving_ref string required

The subject_ref that remains after the merge: the candidate's left_ref or right_ref, or a reference you first sent at POST /v1/identity/consent_tokens. Use it for the person from then on.

merged_ref string required

The subject_ref absorbed into surviving_ref: the other of the candidate's left_ref and right_ref, or a reference you first sent at POST /v1/identity/consent_tokens. Reversing the merge brings it back as it was.

merge_candidate_id string optional

The candidate this merge answers: its id, from an entry in GET /v1/identity/merge_candidates or from data.id on the merge_candidate.raised event; it starts with sub_. Leave it out when no candidate was raised for these two records.

reason string required

Why you're satisfied the two records are one person, in plain words. It stays on the merge for whoever later asks why.

approved_by string required

A second actor, distinct from the caller.

Returns

The merge.

id string required

The merge's identifier, returned by POST /v1/identity/merges. It never changes; pass it as merge_id at POST /v1/identity/merges/{merge_id}/reverse to reverse the merge.

object always "identity_merge" required

Always identity_merge. Tells you which kind of record you are looking at, so one handler can read any response.

surviving_ref string required

The subject_ref that remains after the merge, as you sent it in surviving_ref on POST /v1/identity/merges. Use it for the person from then on.

merged_ref string required

The subject_ref absorbed into surviving_ref, as you sent it in merged_ref on POST /v1/identity/merges. After a reversal it stands on its own again.

merge_candidate_id string · nullable optional

The candidate this merge answered, as you sent it in merge_candidate_id on POST /v1/identity/merges: the id of a merge candidate, starting with sub_. null when the merge was made without a raised candidate.

four_eyes FourEyes required

Two distinct actors. The same credential twice is refused.

2 fields of FourEyes
requested_by string required

The actor who requested the action: the credential that made the call. Never the same as approved_by.

approved_by string required

The second actor who approved the action, as you named them in approved_by on the request. Never the same credential as requested_by.

reason string optional

Why the two records were merged, as you stated it on the request. It stays on the record so the decision can be explained later.

reversible always true required

Always true. Every merge can be reversed at POST /v1/identity/merges/{merge_id}/reverse, and both records go back to their state before it.

before_state_ref string optional

A reference to the complete state of both records before the merge, kept so the merge can be undone at POST /v1/identity/merges/{merge_id}/reverse.

reversed_at string · date-time · nullable optional

When the merge was reversed, as an RFC 3339 timestamp in UTC. null while the merge still stands.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/merges" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"surviving_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","merged_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","merge_candidate_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityMergesCreate({
  idempotencyKey: crypto.randomUUID(),
  anchorMergeCreateRequest: {"survivingRef":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","mergedRef":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","approvedBy":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","mergeCandidateId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/merges', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "surviving_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "merged_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "reason": "The requester confirmed the work in person.",
    "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "merge_candidate_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_merges_create(body={"surviving_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "merged_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "reason": "The requester confirmed the work in person.", "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "merge_candidate_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/merges',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"surviving_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "merged_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "reason": "The requester confirmed the work in person.", "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "merge_candidate_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityMergesCreate($idempotencyKey, json_decode('{"surviving_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","merged_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","merge_candidate_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/merges');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"surviving_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","merged_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","merge_candidate_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityMergesCreate(idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/merges"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "surviving_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "merged_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "reason": "The requester confirmed the work in person.",
          "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "merge_candidate_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityMergesCreate(idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/merges");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "surviving_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "merged_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "reason": "The requester confirmed the work in person.",
      "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "merge_candidate_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityMergesCreate(ctx).IdempotencyKey(key).AnchorMergeCreateRequest(body).Execute()
body := strings.NewReader(`{
  "surviving_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "merged_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reason": "The requester confirmed the work in person.",
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "merge_candidate_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/merges", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "identity_merge",
  "surviving_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "merged_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "four_eyes": {
    "requested_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  },
  "reversible": true,
  "merge_candidate_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reason": "The requester confirmed the work in person.",
  "before_state_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reversed_at": "2026-09-01T09:00:00Z",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/merges/{merge_id}/reverse#

Reverse a merge

identity.merges.reverse

Both records go back to their state before the merge, from the record kept at the time. Undoing a mistake is as much a decision as making one, so it takes a reason and a second approver.

Path parameters

merge_id string required

The id of the merge you want to reverse, from the response to POST /v1/identity/merges.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

reason string required

Why you are undoing this, in your words. It is recorded with the reversal, so write what a reviewer would need to read.

approved_by string required

A second actor who approved the reversal, distinct from you. The same credential twice is refused.

Returns

The reversed merge.

id string required

The merge's identifier, returned by POST /v1/identity/merges. It never changes; pass it as merge_id at POST /v1/identity/merges/{merge_id}/reverse to reverse the merge.

object always "identity_merge" required

Always identity_merge. Tells you which kind of record you are looking at, so one handler can read any response.

surviving_ref string required

The subject_ref that remains after the merge, as you sent it in surviving_ref on POST /v1/identity/merges. Use it for the person from then on.

merged_ref string required

The subject_ref absorbed into surviving_ref, as you sent it in merged_ref on POST /v1/identity/merges. After a reversal it stands on its own again.

merge_candidate_id string · nullable optional

The candidate this merge answered, as you sent it in merge_candidate_id on POST /v1/identity/merges: the id of a merge candidate, starting with sub_. null when the merge was made without a raised candidate.

four_eyes FourEyes required

Two distinct actors. The same credential twice is refused.

2 fields of FourEyes
requested_by string required

The actor who requested the action: the credential that made the call. Never the same as approved_by.

approved_by string required

The second actor who approved the action, as you named them in approved_by on the request. Never the same credential as requested_by.

reason string optional

Why the two records were merged, as you stated it on the request. It stays on the record so the decision can be explained later.

reversible always true required

Always true. Every merge can be reversed at POST /v1/identity/merges/{merge_id}/reverse, and both records go back to their state before it.

before_state_ref string optional

A reference to the complete state of both records before the merge, kept so the merge can be undone at POST /v1/identity/merges/{merge_id}/reverse.

reversed_at string · date-time · nullable optional

When the merge was reversed, as an RFC 3339 timestamp in UTC. null while the merge still stands.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/merges/%7Bmerge_id%7D/reverse" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityMergesReverse({
  mergeId: '{merge_id}',
  idempotencyKey: crypto.randomUUID(),
  anchorReversalRequest: {"reason":"The requester confirmed the work in person.","approvedBy":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/merges/%7Bmerge_id%7D/reverse', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "reason": "The requester confirmed the work in person.",
    "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_merges_reverse(merge_id='{merge_id}', body={"reason": "The requester confirmed the work in person.", "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/merges/%7Bmerge_id%7D/reverse',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"reason": "The requester confirmed the work in person.", "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityMergesReverse($idempotencyKey, json_decode('{"reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/merges/%7Bmerge_id%7D/reverse');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityMergesReverse("{merge_id}", idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/merges/%7Bmerge_id%7D/reverse"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "reason": "The requester confirmed the work in person.",
          "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityMergesReverse(mergeId: "{merge_id}", idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/merges/%7Bmerge_id%7D/reverse");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "reason": "The requester confirmed the work in person.",
      "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityMergesReverse(ctx, "{merge_id}").IdempotencyKey(key).AnchorReversalRequest(body).Execute()
body := strings.NewReader(`{
  "reason": "The requester confirmed the work in person.",
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/merges/%7Bmerge_id%7D/reverse", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "identity_merge",
  "surviving_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "merged_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "four_eyes": {
    "requested_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  },
  "reversible": true,
  "merge_candidate_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reason": "The requester confirmed the work in person.",
  "before_state_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reversed_at": "2026-09-01T09:00:00Z",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/blocklist_entries#

Blocklist an identity

identity.blocklist_entries.create

Needs four eyes, the same as a merge. A blocklisting stops a person transacting anywhere on Droomwork, so one credential isn't enough to impose it.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

subject_ref string required

Your opaque reference to the person you are blocklisting: the same subject_ref you first sent at POST /v1/identity/consent_tokens and again at POST /v1/identity/verifications. Not a name and not an identifier.

reason string required

Why this person is being blocklisted, in your words. It stays on the entry, so write what a reviewer would need to read.

approved_by string required

A second actor, distinct from the caller.

Returns

The blocklist entry.

id string required

The entry's identifier, returned by POST /v1/identity/blocklist_entries. It never changes; pass it as blocklist_entry_id at POST /v1/identity/blocklist_entries/{blocklist_entry_id}/reverse to lift the blocklisting.

object always "blocklist_entry" required

Always blocklist_entry. Tells you which kind of record you are looking at, so one handler can read any response.

subject_ref string required

Your opaque reference to the blocklisted person, as you sent it in subject_ref on POST /v1/identity/blocklist_entries and first at POST /v1/identity/consent_tokens. Not a name and not an identifier.

reason string required

Why this person was blocklisted, as you stated it on the request.

four_eyes FourEyes required

Two distinct actors. The same credential twice is refused.

2 fields of FourEyes
requested_by string required

The actor who requested the action: the credential that made the call. Never the same as approved_by.

approved_by string required

The second actor who approved the action, as you named them in approved_by on the request. Never the same credential as requested_by.

status string required

active while the person is stopped from transacting anywhere on Droomwork; lifted once you reversed the blocklisting at POST /v1/identity/blocklist_entries/{blocklist_entry_id}/reverse.

activelifted
before_state_ref string optional

A reference to the person's standing before the blocklisting, kept so it can be restored when you lift the entry at POST /v1/identity/blocklist_entries/{blocklist_entry_id}/reverse.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/blocklist_entries" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityBlocklistEntriesCreate({
  idempotencyKey: crypto.randomUUID(),
  anchorBlocklistCreateRequest: {"subjectRef":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","approvedBy":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/blocklist_entries', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "reason": "The requester confirmed the work in person.",
    "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_blocklist_entries_create(body={"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "reason": "The requester confirmed the work in person.", "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/blocklist_entries',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "reason": "The requester confirmed the work in person.", "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityBlocklistEntriesCreate($idempotencyKey, json_decode('{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/blocklist_entries');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityBlocklistEntriesCreate(idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/blocklist_entries"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "reason": "The requester confirmed the work in person.",
          "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityBlocklistEntriesCreate(idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/blocklist_entries");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "reason": "The requester confirmed the work in person.",
      "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityBlocklistEntriesCreate(ctx).IdempotencyKey(key).AnchorBlocklistCreateRequest(body).Execute()
body := strings.NewReader(`{
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reason": "The requester confirmed the work in person.",
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/blocklist_entries", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "blocklist_entry",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reason": "The requester confirmed the work in person.",
  "four_eyes": {
    "requested_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  },
  "status": "active",
  "before_state_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/blocklist_entries/{blocklist_entry_id}/reverse#

Lift a blocklisting

identity.blocklist_entries.reverse

Standing is restored, with the before and after state recorded.

Path parameters

blocklist_entry_id string required

The id of the entry you want to lift, from the response to POST /v1/identity/blocklist_entries.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

reason string required

Why you are undoing this, in your words. It is recorded with the reversal, so write what a reviewer would need to read.

approved_by string required

A second actor who approved the reversal, distinct from you. The same credential twice is refused.

Returns

The lifted entry.

id string required

The entry's identifier, returned by POST /v1/identity/blocklist_entries. It never changes; pass it as blocklist_entry_id at POST /v1/identity/blocklist_entries/{blocklist_entry_id}/reverse to lift the blocklisting.

object always "blocklist_entry" required

Always blocklist_entry. Tells you which kind of record you are looking at, so one handler can read any response.

subject_ref string required

Your opaque reference to the blocklisted person, as you sent it in subject_ref on POST /v1/identity/blocklist_entries and first at POST /v1/identity/consent_tokens. Not a name and not an identifier.

reason string required

Why this person was blocklisted, as you stated it on the request.

four_eyes FourEyes required

Two distinct actors. The same credential twice is refused.

2 fields of FourEyes
requested_by string required

The actor who requested the action: the credential that made the call. Never the same as approved_by.

approved_by string required

The second actor who approved the action, as you named them in approved_by on the request. Never the same credential as requested_by.

status string required

active while the person is stopped from transacting anywhere on Droomwork; lifted once you reversed the blocklisting at POST /v1/identity/blocklist_entries/{blocklist_entry_id}/reverse.

activelifted
before_state_ref string optional

A reference to the person's standing before the blocklisting, kept so it can be restored when you lift the entry at POST /v1/identity/blocklist_entries/{blocklist_entry_id}/reverse.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/blocklist_entries/%7Bblocklist_entry_id%7D/reverse" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityBlocklistEntriesReverse({
  blocklistEntryId: '{blocklist_entry_id}',
  idempotencyKey: crypto.randomUUID(),
  anchorReversalRequest: {"reason":"The requester confirmed the work in person.","approvedBy":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/blocklist_entries/%7Bblocklist_entry_id%7D/reverse', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "reason": "The requester confirmed the work in person.",
    "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_blocklist_entries_reverse(blocklist_entry_id='{blocklist_entry_id}', body={"reason": "The requester confirmed the work in person.", "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/blocklist_entries/%7Bblocklist_entry_id%7D/reverse',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"reason": "The requester confirmed the work in person.", "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityBlocklistEntriesReverse($idempotencyKey, json_decode('{"reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/blocklist_entries/%7Bblocklist_entry_id%7D/reverse');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"reason":"The requester confirmed the work in person.","approved_by":"usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityBlocklistEntriesReverse("{blocklist_entry_id}", idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/blocklist_entries/%7Bblocklist_entry_id%7D/reverse"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "reason": "The requester confirmed the work in person.",
          "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityBlocklistEntriesReverse(blocklistEntryId: "{blocklist_entry_id}", idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/blocklist_entries/%7Bblocklist_entry_id%7D/reverse");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "reason": "The requester confirmed the work in person.",
      "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityBlocklistEntriesReverse(ctx, "{blocklist_entry_id}").IdempotencyKey(key).AnchorReversalRequest(body).Execute()
body := strings.NewReader(`{
  "reason": "The requester confirmed the work in person.",
  "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/blocklist_entries/%7Bblocklist_entry_id%7D/reverse", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "blocklist_entry",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reason": "The requester confirmed the work in person.",
  "four_eyes": {
    "requested_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "approved_by": "usr_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
  },
  "status": "active",
  "before_state_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/disclosures#

List disclosures

identity.disclosures.list

What your organisation may currently see, about whom, for what purpose and until when.

Query parameters

limit integer optional

How many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.

starting_after string optional

The id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.

status string optional

Returns only disclosures in one standing: active (you may still see the fields), revoked (you or the subject ended it), expired (past expires_at) or suspended (consent or the Passport fell away). Leave it out to get every standing.

activerevokedexpiredsuspended

Returns

A page of disclosures.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of Disclosure required

The records on this page, in the order the list promises. Empty when nothing matched.

13 fields of Disclosure
id string required

The disclosure's identifier, returned by POST /v1/identity/disclosures. It starts with anchor_pro_disclosure_ and never changes; pass it as disclosure_id to retrieve or revoke the disclosure.

object always "disclosure" required

Always disclosure. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

passport_id string required

The Passport this disclosure is drawn from, as you sent it in passport_id on POST /v1/identity/disclosures. It is the id of a Passport and starts with anchor_pro_passport_.

subject_ref string optional

Your opaque reference to the person the Passport belongs to: the subject_ref you first sent at POST /v1/identity/consent_tokens. Not a name and not an identifier.

purpose string required

The purpose you gave on the request, such as employment_verification. What you may see is scoped to it.

consent_token_id string optional

The consent token this disclosure rests on: the id of a token from POST /v1/identity/consent_tokens, starting with anchor_pro_consent_, as you sent it on the request. If the subject withdraws that consent, the disclosure suspends within 24 hours.

fields_disclosed array of string optional

What you may see. Identifiers appear masked and never in full.

status string required
activerevokedexpiredsuspended
suspended_because string · nullable optional

Why the disclosure is suspended: consent_withdrawn when the subject withdrew consent, passport_revoked when the Passport was revoked, passport_downgraded when its level fell. null unless status is suspended.

consent_withdrawnpassport_revokedpassport_downgradednull
expires_at string · date-time required

Time boxed. There is no open ended disclosure.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# query parameters: limit (optional), starting_after (optional), status (optional)
curl -X GET "https://sandbox.droomwork.io/v1/identity/disclosures?limit=25&status=active" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

// query parameters: limit (optional), starting_after (optional), status (optional)
const result = await api.identityDisclosuresList({ limit: 25, status: 'active' });
// query parameters: limit (optional), starting_after (optional), status (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/identity/disclosures?limit=25&status=active', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

# query parameters: limit (optional), starting_after (optional), status (optional)
result = api.identity_disclosures_list(limit=25, status='active')
import os

import requests

# query parameters: limit (optional), starting_after (optional), status (optional)
response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/disclosures?limit=25&status=active',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

# query parameters: limit (optional), starting_after (optional), status (optional)
$result = $api->identityDisclosuresList(limit: 25, status: 'active');
<?php
// query parameters: limit (optional), starting_after (optional), status (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/disclosures?limit=25&status=active');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;
import com.droomwork.sdk.model.*;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

// query parameters: limit (optional), starting_after (optional), status (optional)
var result = api.identityDisclosuresList(25, null, AnchorDisclosureStatus.fromValue("active"));
// query parameters: limit (optional), starting_after (optional), status (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/disclosures?limit=25&status=active"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

// query parameters: limit (optional), starting_after (optional), status (optional)
var result = api.IdentityDisclosuresList(limit: 25, status: AnchorDisclosureStatus.Active);
// query parameters: limit (optional), starting_after (optional), status (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/disclosures?limit=25&status=active");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

// query parameters: limit (optional), starting_after (optional), status (optional)
result, _, err := client.ANCHORAPI.IdentityDisclosuresList(ctx).Limit(25).Status(droomwork.AnchorDisclosureStatus("active")).Execute()
// query parameters: limit (optional), starting_after (optional), status (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/disclosures?limit=25&status=active", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "list",
  "data": [
    {
      "id": "anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "disclosure",
      "livemode": true,
      "mocked": true,
      "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "purpose": "employment_verification",
      "status": "active",
      "expires_at": "2026-09-01T09:00:00Z",
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "fields_disclosed": [
        "example"
      ],
      "suspended_because": "consent_withdrawn",
      "created_at": "2026-09-01T09:00:00Z"
    }
  ],
  "has_more": true
}
POST/v1/identity/disclosures#

Request a disclosure

identity.disclosures.create

Consented, purpose scoped and time boxed. All three, every time. You can't get an open ended disclosure, and you can't get one without a purpose on the record.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

passport_id string required

The Passport you want a disclosure from: its id, from passport_id on a resolved verification at GET /v1/identity/verifications/{verification_id} or from the response to POST /v1/identity/passports. It starts with anchor_pro_passport_.

purpose string required

What you'll use the disclosure for, such as employment_verification. It scopes what you may see, and there is no disclosure without one.

consent_token_id string required

The id of a consent token from POST /v1/identity/consent_tokens or GET /v1/identity/consent_tokens that covers this subject and purpose; it starts with anchor_pro_consent_. One that doesn't is refused with consent_token_missing.

fields_requested array of string optional

The fields you want to see, by name. What you actually get is listed in fields_disclosed on the response, and identifiers appear masked and never in full.

expires_at string · date-time required

When the disclosure ends, as an RFC 3339 timestamp in UTC. Required: there is no open ended disclosure.

Returns

The disclosure.

id string required

The disclosure's identifier, returned by POST /v1/identity/disclosures. It starts with anchor_pro_disclosure_ and never changes; pass it as disclosure_id to retrieve or revoke the disclosure.

object always "disclosure" required

Always disclosure. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

passport_id string required

The Passport this disclosure is drawn from, as you sent it in passport_id on POST /v1/identity/disclosures. It is the id of a Passport and starts with anchor_pro_passport_.

subject_ref string optional

Your opaque reference to the person the Passport belongs to: the subject_ref you first sent at POST /v1/identity/consent_tokens. Not a name and not an identifier.

purpose string required

The purpose you gave on the request, such as employment_verification. What you may see is scoped to it.

consent_token_id string optional

The consent token this disclosure rests on: the id of a token from POST /v1/identity/consent_tokens, starting with anchor_pro_consent_, as you sent it on the request. If the subject withdraws that consent, the disclosure suspends within 24 hours.

fields_disclosed array of string optional

What you may see. Identifiers appear masked and never in full.

status string required
activerevokedexpiredsuspended
suspended_because string · nullable optional

Why the disclosure is suspended: consent_withdrawn when the subject withdrew consent, passport_revoked when the Passport was revoked, passport_downgraded when its level fell. null unless status is suspended.

consent_withdrawnpassport_revokedpassport_downgradednull
expires_at string · date-time required

Time boxed. There is no open ended disclosure.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/disclosures" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"passport_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","purpose":"employment_verification","consent_token_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","expires_at":"2026-09-01T09:00:00Z","fields_requested":["example"]}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityDisclosuresCreate({
  idempotencyKey: crypto.randomUUID(),
  anchorDisclosureCreateRequest: {"passportId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","purpose":"employment_verification","consentTokenId":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","expiresAt":"2026-09-01T09:00:00Z","fieldsRequested":["example"]},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/disclosures', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "purpose": "employment_verification",
    "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "expires_at": "2026-09-01T09:00:00Z",
    "fields_requested": [
      "example"
    ]
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_disclosures_create(body={"passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "purpose": "employment_verification", "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "expires_at": "2026-09-01T09:00:00Z", "fields_requested": ["example"]})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/disclosures',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "purpose": "employment_verification", "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "expires_at": "2026-09-01T09:00:00Z", "fields_requested": ["example"]},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityDisclosuresCreate($idempotencyKey, json_decode('{"passport_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","purpose":"employment_verification","consent_token_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","expires_at":"2026-09-01T09:00:00Z","fields_requested":["example"]}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/disclosures');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"passport_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","purpose":"employment_verification","consent_token_id":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","expires_at":"2026-09-01T09:00:00Z","fields_requested":["example"]}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityDisclosuresCreate(idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/disclosures"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "purpose": "employment_verification",
          "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "expires_at": "2026-09-01T09:00:00Z",
          "fields_requested": [
            "example"
          ]
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityDisclosuresCreate(idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/disclosures");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "purpose": "employment_verification",
      "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "expires_at": "2026-09-01T09:00:00Z",
      "fields_requested": [
        "example"
      ]
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityDisclosuresCreate(ctx).IdempotencyKey(key).AnchorDisclosureCreateRequest(body).Execute()
body := strings.NewReader(`{
  "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "purpose": "employment_verification",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "expires_at": "2026-09-01T09:00:00Z",
  "fields_requested": [
    "example"
  ]
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/disclosures", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "disclosure",
  "livemode": true,
  "mocked": true,
  "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "purpose": "employment_verification",
  "status": "active",
  "expires_at": "2026-09-01T09:00:00Z",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "fields_disclosed": [
    "example"
  ],
  "suspended_because": "consent_withdrawn",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/disclosures/reconcile#

Recover from missed revocation events

identity.disclosures.reconcile

You get the current standing of every disclosure your organisation holds, each with a sequence number.

Call this if you dropped a webhook or your consumer was down. A revocation reaches every holder within 15 minutes, and this is how you find the one you missed before you carry on against a Passport that is no longer live.

Query parameters

since_sequence integer optional

The as_of_sequence from your last reconcile response. You get only the disclosures that changed after it; leave it out to get the current standing of every disclosure you hold.

Returns

The current standing of every disclosure you hold.

object always "disclosure_reconciliation" required

Always disclosure_reconciliation. Tells you which kind of record you are looking at, so one handler can read any response.

as_of_sequence integer · minimum 0 required

The sequence number this report is current to. Keep it and pass it as since_sequence next time to get only what changed after it.

generated_at string · date-time optional

When this report was produced, as an RFC 3339 timestamp in UTC.

disclosures array of object required

One row per disclosure your organisation holds, giving its current standing and the sequence number of its latest change. Only the changes after since_sequence when you passed one.

5 fields
disclosure_id string required

The id of the disclosure this row is about, as POST /v1/identity/disclosures returned it or GET /v1/identity/disclosures lists it; it starts with anchor_pro_disclosure_. Pass it as disclosure_id to retrieve or revoke the disclosure.

passport_id string optional

The id of the Passport the disclosure is drawn from, as GET /v1/identity/passports lists it; it starts with anchor_pro_passport_ and is absent when there is none. Use it to find what you hold against a Passport that is no longer live.

status string required
activerevokedexpiredsuspended
sequence integer required

The sequence number of this disclosure's latest change. Higher means later; compare it with the last event you handled to see what you missed.

changed_at string · date-time optional

When the disclosure last changed standing, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# query parameters: since_sequence (optional)
curl -X GET "https://sandbox.droomwork.io/v1/identity/disclosures/reconcile?since_sequence=0" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

// query parameters: since_sequence (optional)
const result = await api.identityDisclosuresReconcile({ sinceSequence: 0 });
// query parameters: since_sequence (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/identity/disclosures/reconcile?since_sequence=0', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

# query parameters: since_sequence (optional)
result = api.identity_disclosures_reconcile(since_sequence=0)
import os

import requests

# query parameters: since_sequence (optional)
response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/disclosures/reconcile?since_sequence=0',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

# query parameters: since_sequence (optional)
$result = $api->identityDisclosuresReconcile(since_sequence: 0);
<?php
// query parameters: since_sequence (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/disclosures/reconcile?since_sequence=0');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

// query parameters: since_sequence (optional)
var result = api.identityDisclosuresReconcile(0);
// query parameters: since_sequence (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/disclosures/reconcile?since_sequence=0"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

// query parameters: since_sequence (optional)
var result = api.IdentityDisclosuresReconcile(sinceSequence: 0);
// query parameters: since_sequence (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/disclosures/reconcile?since_sequence=0");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

// query parameters: since_sequence (optional)
result, _, err := client.ANCHORAPI.IdentityDisclosuresReconcile(ctx).SinceSequence(0).Execute()
// query parameters: since_sequence (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/disclosures/reconcile?since_sequence=0", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "disclosure_reconciliation",
  "as_of_sequence": 0,
  "disclosures": [
    {
      "disclosure_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "status": "active",
      "sequence": 1,
      "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "changed_at": "2026-09-01T09:00:00Z"
    }
  ],
  "generated_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/disclosures/{disclosure_id}#

Retrieve a disclosure

identity.disclosures.retrieve

You get what was disclosed, under which consent and until when. Any identity number here is masked.

Path parameters

disclosure_id string required

The disclosure's id, as POST /v1/identity/disclosures returned it when you created it or as GET /v1/identity/disclosures lists it. It starts with anchor_pro_disclosure_.

Returns

The disclosure.

id string required

The disclosure's identifier, returned by POST /v1/identity/disclosures. It starts with anchor_pro_disclosure_ and never changes; pass it as disclosure_id to retrieve or revoke the disclosure.

object always "disclosure" required

Always disclosure. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

passport_id string required

The Passport this disclosure is drawn from, as you sent it in passport_id on POST /v1/identity/disclosures. It is the id of a Passport and starts with anchor_pro_passport_.

subject_ref string optional

Your opaque reference to the person the Passport belongs to: the subject_ref you first sent at POST /v1/identity/consent_tokens. Not a name and not an identifier.

purpose string required

The purpose you gave on the request, such as employment_verification. What you may see is scoped to it.

consent_token_id string optional

The consent token this disclosure rests on: the id of a token from POST /v1/identity/consent_tokens, starting with anchor_pro_consent_, as you sent it on the request. If the subject withdraws that consent, the disclosure suspends within 24 hours.

fields_disclosed array of string optional

What you may see. Identifiers appear masked and never in full.

status string required
activerevokedexpiredsuspended
suspended_because string · nullable optional

Why the disclosure is suspended: consent_withdrawn when the subject withdrew consent, passport_revoked when the Passport was revoked, passport_downgraded when its level fell. null unless status is suspended.

consent_withdrawnpassport_revokedpassport_downgradednull
expires_at string · date-time required

Time boxed. There is no open ended disclosure.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityDisclosuresRetrieve({ disclosureId: 'anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_disclosures_retrieve(disclosure_id='anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityDisclosuresRetrieve(disclosure_id: 'anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityDisclosuresRetrieve("anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityDisclosuresRetrieve(disclosureId: "anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityDisclosuresRetrieve(ctx, "anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "disclosure",
  "livemode": true,
  "mocked": true,
  "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "purpose": "employment_verification",
  "status": "active",
  "expires_at": "2026-09-01T09:00:00Z",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "fields_disclosed": [
    "example"
  ],
  "suspended_because": "consent_withdrawn",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/disclosures/{disclosure_id}/revoke#

Revoke a disclosure

identity.disclosures.revoke

Access ends immediately. The subject can do this themselves, and every holder is notified within 15 minutes.

Path parameters

disclosure_id string required

The disclosure's id, as POST /v1/identity/disclosures returned it when you created it or as GET /v1/identity/disclosures lists it. It starts with anchor_pro_disclosure_.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Returns

The revoked disclosure.

id string required

The disclosure's identifier, returned by POST /v1/identity/disclosures. It starts with anchor_pro_disclosure_ and never changes; pass it as disclosure_id to retrieve or revoke the disclosure.

object always "disclosure" required

Always disclosure. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

passport_id string required

The Passport this disclosure is drawn from, as you sent it in passport_id on POST /v1/identity/disclosures. It is the id of a Passport and starts with anchor_pro_passport_.

subject_ref string optional

Your opaque reference to the person the Passport belongs to: the subject_ref you first sent at POST /v1/identity/consent_tokens. Not a name and not an identifier.

purpose string required

The purpose you gave on the request, such as employment_verification. What you may see is scoped to it.

consent_token_id string optional

The consent token this disclosure rests on: the id of a token from POST /v1/identity/consent_tokens, starting with anchor_pro_consent_, as you sent it on the request. If the subject withdraws that consent, the disclosure suspends within 24 hours.

fields_disclosed array of string optional

What you may see. Identifiers appear masked and never in full.

status string required
activerevokedexpiredsuspended
suspended_because string · nullable optional

Why the disclosure is suspended: consent_withdrawn when the subject withdrew consent, passport_revoked when the Passport was revoked, passport_downgraded when its level fell. null unless status is suspended.

consent_withdrawnpassport_revokedpassport_downgradednull
expires_at string · date-time required

Time boxed. There is no open ended disclosure.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityDisclosuresRevoke({ disclosureId: 'anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Idempotency-Key': crypto.randomUUID(),
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_disclosures_revoke(disclosure_id='anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityDisclosuresRevoke(disclosure_id: 'anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityDisclosuresRevoke("anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityDisclosuresRevoke(disclosureId: "anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityDisclosuresRevoke(ctx, "anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/disclosures/anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/revoke", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_disclosure_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "disclosure",
  "livemode": true,
  "mocked": true,
  "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "purpose": "employment_verification",
  "status": "active",
  "expires_at": "2026-09-01T09:00:00Z",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "fields_disclosed": [
    "example"
  ],
  "suspended_because": "consent_withdrawn",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/subject_requests#

Exercise a subject data right

identity.subject_requests.create

Raise an access, correction, erasure or restriction on processing request here, as an operation you call rather than a support process.

Erasure removes personal data while keeping signed records verifiable and honouring statutory retention. You get an answer, with what was kept and why, rather than a refusal because records exist.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

kind string required
accesscorrectionerasurerestrict_processingportability
subject_ref string required

The opaque reference you chose for the person exercising the right: the same subject_ref you sent when you recorded their consent at POST /v1/identity/consent_tokens and verified them. Not a name and not an identifier.

note string optional

Free text you attach to the request, such as what the subject asked for and how they asked. Optional.

Returns

The request, with the date it is due.

id string required

The record's identifier, returned by POST /v1/identity/subject_requests when you raise the request. It starts with sub_ and never changes; pass it as subject_request_id to GET /v1/identity/subject_requests/{subject_request_id}.

object always "subject_request" required

Always subject_request. Tells you which kind of record you are looking at, so one handler can read any response.

kind string required
accesscorrectionerasurerestrict_processingportability
subject_ref string required

The opaque reference to the person exercising the right, exactly as you sent it in subject_ref at POST /v1/identity/subject_requests. Not a name and not an identifier.

status string required

Where the request stands: received when you raise it, in_progress while it's handled, completed once done with completed_at set, or refused when it's turned down. Kept records never make it refused: they're listed in retained.

receivedin_progresscompletedrefused
due_by string · date required

The date the request is due to be answered by, as a calendar date in YYYY-MM-DD. Set when you raise it, so you can chase before it passes.

retained array of object optional

What was kept and under which obligation. Erasure removes personal data while keeping signed records verifiable and honouring statutory retention.

3 fields
category string required

The kind of record that was kept, in words you can pass on to the subject. Read it with lawful_basis to say what remains and why.

lawful_basis string required

Why this category was kept: the obligation that stops it being erased, in words you can quote to the subject when you answer them.

until string · date optional

The date the retention ends, as a calendar date in YYYY-MM-DD. Absent when no end date applies.

completed_at string · date-time · nullable optional

When the request was completed, as an RFC 3339 timestamp in UTC. null while the request is still open.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/subject_requests" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"kind":"access","subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","note":"example"}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identitySubjectRequestsCreate({
  idempotencyKey: crypto.randomUUID(),
  anchorSubjectRequestCreateRequest: {"kind":"access","subjectRef":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","note":"example"},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/subject_requests', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "kind": "access",
    "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "note": "example"
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_subject_requests_create(body={"kind": "access", "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "note": "example"})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/subject_requests',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"kind": "access", "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "note": "example"},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identitySubjectRequestsCreate($idempotencyKey, json_decode('{"kind":"access","subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","note":"example"}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/subject_requests');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"kind":"access","subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","note":"example"}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identitySubjectRequestsCreate(idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/subject_requests"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "kind": "access",
          "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "note": "example"
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentitySubjectRequestsCreate(idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/subject_requests");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "kind": "access",
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "note": "example"
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentitySubjectRequestsCreate(ctx).IdempotencyKey(key).AnchorSubjectRequestCreateRequest(body).Execute()
body := strings.NewReader(`{
  "kind": "access",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "note": "example"
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/subject_requests", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "subject_request",
  "kind": "access",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "status": "received",
  "due_by": "2026-09-01",
  "retained": [
    {
      "category": "example",
      "lawful_basis": "example",
      "until": "2026-09-01"
    }
  ],
  "completed_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/subject_requests/{subject_request_id}#

Retrieve a subject request

identity.subject_requests.retrieve

You get its progress, what was done, and what was retained and why.

Path parameters

subject_request_id string required

The subject request's id, as POST /v1/identity/subject_requests returned it when you raised the request. It starts with sub_.

Returns

The subject request.

id string required

The record's identifier, returned by POST /v1/identity/subject_requests when you raise the request. It starts with sub_ and never changes; pass it as subject_request_id to GET /v1/identity/subject_requests/{subject_request_id}.

object always "subject_request" required

Always subject_request. Tells you which kind of record you are looking at, so one handler can read any response.

kind string required
accesscorrectionerasurerestrict_processingportability
subject_ref string required

The opaque reference to the person exercising the right, exactly as you sent it in subject_ref at POST /v1/identity/subject_requests. Not a name and not an identifier.

status string required

Where the request stands: received when you raise it, in_progress while it's handled, completed once done with completed_at set, or refused when it's turned down. Kept records never make it refused: they're listed in retained.

receivedin_progresscompletedrefused
due_by string · date required

The date the request is due to be answered by, as a calendar date in YYYY-MM-DD. Set when you raise it, so you can chase before it passes.

retained array of object optional

What was kept and under which obligation. Erasure removes personal data while keeping signed records verifiable and honouring statutory retention.

3 fields
category string required

The kind of record that was kept, in words you can pass on to the subject. Read it with lawful_basis to say what remains and why.

lawful_basis string required

Why this category was kept: the obligation that stops it being erased, in words you can quote to the subject when you answer them.

until string · date optional

The date the retention ends, as a calendar date in YYYY-MM-DD. Absent when no end date applies.

completed_at string · date-time · nullable optional

When the request was completed, as an RFC 3339 timestamp in UTC. null while the request is still open.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/subject_requests/%7Bsubject_request_id%7D" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identitySubjectRequestsRetrieve({ subjectRequestId: '{subject_request_id}' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/subject_requests/%7Bsubject_request_id%7D', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_subject_requests_retrieve(subject_request_id='{subject_request_id}')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/subject_requests/%7Bsubject_request_id%7D',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identitySubjectRequestsRetrieve(subject_request_id: '{subject_request_id}');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/subject_requests/%7Bsubject_request_id%7D');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identitySubjectRequestsRetrieve("{subject_request_id}");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/subject_requests/%7Bsubject_request_id%7D"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentitySubjectRequestsRetrieve(subjectRequestId: "{subject_request_id}");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/subject_requests/%7Bsubject_request_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentitySubjectRequestsRetrieve(ctx, "{subject_request_id}").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/subject_requests/%7Bsubject_request_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "subject_request",
  "kind": "access",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "status": "received",
  "due_by": "2026-09-01",
  "retained": [
    {
      "category": "example",
      "lawful_basis": "example",
      "until": "2026-09-01"
    }
  ],
  "completed_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/access_grants#

Record a reason before viewing unmasked personal data

identity.access_grants.create

State why before you see anything unmasked. The view is logged to the field. Access is a grant you create and we record, never a permission somebody holds quietly.

The grant is short lived and scoped to one subject. It doesn't widen what your organisation may see; it records that a named person looked.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Body

subject_ref string required

The opaque reference you chose for the person whose data you're about to view unmasked: the same subject_ref you sent when you recorded their consent at POST /v1/identity/consent_tokens and verified them. Not a name and not an identifier.

reason string required

Why you need to see the data unmasked, in your words. It's recorded before anything is shown and logged to each field, so write what a reviewer would need to read.

fields array of string required

The fields you'll view unmasked, by name, such as gross.amount. At least one, and each view is logged to the field, so name only what you need.

Returns

The access grant.

id string required

The record's identifier, returned by POST /v1/identity/access_grants when you create the grant. It never changes and no other call takes it, so keep it if you may need to cite this look later.

object always "access_grant" required

Always access_grant. Tells you which kind of record you are looking at, so one handler can read any response.

subject_ref string required

The opaque reference to the person whose data the grant covers, exactly as you sent it in subject_ref at POST /v1/identity/access_grants. Not a name and not an identifier.

reason string required

Stated before anything is seen, and logged to the field.

granted_to string required

Who the grant names, by their identifier: the one person recorded as looking. It covers that person alone and doesn't widen what your organisation may see.

fields array of string optional

The fields the grant covers, as you named them on the request, such as gross.amount. Each view is logged to the field.

expires_at string · date-time required

When the grant lapses, as an RFC 3339 timestamp in UTC. Grants are short lived; after this, state a reason again before viewing anything unmasked.

created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/access_grants" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","fields":["gross.amount"]}'
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityAccessGrantsCreate({
  idempotencyKey: crypto.randomUUID(),
  anchorAccessGrantCreateRequest: {"subjectRef":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","fields":["gross.amount"]},
});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/access_grants', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Content-Type': 'application/json',
    'Idempotency-Key': crypto.randomUUID(),
  },
  body: JSON.stringify({
    "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
    "reason": "The requester confirmed the work in person.",
    "fields": [
      "gross.amount"
    ]
  }),
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_access_grants_create(body={"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "reason": "The requester confirmed the work in person.", "fields": ["gross.amount"]})
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/access_grants',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
    json={"subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "reason": "The requester confirmed the work in person.", "fields": ["gross.amount"]},
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityAccessGrantsCreate($idempotencyKey, json_decode('{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","fields":["gross.amount"]}', true));
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/access_grants');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Content-Type: application/json',
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
  CURLOPT_POSTFIELDS => '{"subject_ref":"sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z","reason":"The requester confirmed the work in person.","fields":["gross.amount"]}',
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityAccessGrantsCreate(idempotencyKey, body);
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/access_grants"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Content-Type", "application/json")
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.ofString("""
        {
          "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
          "reason": "The requester confirmed the work in person.",
          "fields": [
            "gross.amount"
          ]
        }
        """))
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityAccessGrantsCreate(idempotencyKey, body);
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/access_grants");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
request.Content = new StringContent("""
    {
      "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "reason": "The requester confirmed the work in person.",
      "fields": [
        "gross.amount"
      ]
    }
    """, Encoding.UTF8, "application/json");
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityAccessGrantsCreate(ctx).IdempotencyKey(key).AnchorAccessGrantCreateRequest(body).Execute()
body := strings.NewReader(`{
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reason": "The requester confirmed the work in person.",
  "fields": [
    "gross.amount"
  ]
}`)
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/access_grants", body)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "access_grant",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "reason": "The requester confirmed the work in person.",
  "granted_to": "example",
  "expires_at": "2026-09-01T09:00:00Z",
  "fields": [
    "gross.amount"
  ],
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/gating_contract#

What every module requires of an identity before it will act

identity.gating_contract.retrieve

No module transacts against an unanchored or revoked subject, and this states exactly what each one demands of an identity.

Read it before you build, so you know what PROOF, RAIL, MATCH and the payroll modules will each insist on.

Returns

The gating contract.

object always "gating_contract" required

Always gating_contract. Tells you which kind of record you are looking at, so one handler can read any response.

version string required

Which edition of the contract you're reading, such as 2026.08.1. Build against one and compare it on each read: a new version means a requirement changed.

modules array of object required

One entry per module, stating what it requires of an identity before it will act: the conditions, and the lowest assurance it accepts for each.

2 fields
module string required

Which module these requirements are for: proof (credentials), rail (working relationships), flow (sourcing), match (work allocation), run (payroll), remit (statutory remittance) or route (payouts).

proofrailflowmatchrunremitroute
requires array of object required

What this module demands of an identity before it acts. Every condition listed must hold at its minimum_assurance or higher, or the module refuses.

3 fields
condition string required

The fact that must hold, in words, such as live unrevoked Passport.

minimum_assurance string required

How a fact was established. Recorded on the fact rather than in configuration, so an attested identity and a verified one stay distinguishable a year later, which is the distinction that matters when something is disputed.

attestedverified
contract_row string optional

The row of the contract this requirement is taken from, such as 6.1.13, so you can cite it. Absent when no row states it.

never_attestable array of string optional

Gates that hold in every configuration, whatever anyone has attested to.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/gating_contract" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityGatingContractRetrieve({});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/gating_contract', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_gating_contract_retrieve()
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/gating_contract',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityGatingContractRetrieve();
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/gating_contract');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityGatingContractRetrieve();
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/gating_contract"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityGatingContractRetrieve();
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/gating_contract");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityGatingContractRetrieve(ctx).Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/gating_contract", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "gating_contract",
  "version": "2026.08.1",
  "modules": [
    {
      "module": "proof",
      "requires": [
        {
          "condition": "live unrevoked Passport",
          "minimum_assurance": "attested",
          "contract_row": "6.1.13"
        }
      ]
    }
  ],
  "never_attestable": [
    "example"
  ]
}
GET/v1/identity/readiness#

What ANCHOR needs, what you have, and what is missing

identity.readiness.retrieve

This reports the source credentials you hold and the consent coverage you have.

Returns

The readiness report.

object always "readiness_report" required

Always readiness_report. Tells you which kind of record you are looking at, so one handler can read any response.

module string required

The module whose readiness endpoint you called, such as GET /v1/payroll/readiness: anchor (identity), proof (credentials), rail (engagements), flow (sourcing), match (allocation), run (payroll), remit (remittance) or route (payouts).

anchorproofrailflowmatchrunremitroute
mode string required

integrated means a required fact comes from the Droomwork module that owns it; standalone means you supply it yourself under an attestation. The checks are the same in both, and what each fact is worth is recorded on its row as held.

integratedstandalone
ready boolean required

true when every row is satisfied and the module has what it needs from you. false when a required fact is missing or held at too low an assurance; rows says which.

rows array of ReadinessRow required

One row per fact the module requires: who owns it, the assurance it needs, what you hold and whether that satisfies it. The rows that are not satisfied are what to bring.

8 fields of ReadinessRow
fact string required

Named for what it is, not for who supplies it.

owner string required

The sibling module that owns this fact when running integrated.

contract_row string optional
required string required

How a fact was established. Recorded on the fact rather than in configuration, so an attested identity and a verified one stay distinguishable a year later, which is the distinction that matters when something is disputed.

attestedverified
held one of required
Assuranceor
source string · nullable optional
integratedstandalonenull
satisfied boolean required
missing_because string · nullable optional
not_suppliedassurance_too_lownull
always_enforced array of string optional

Gates that hold in every mode and cannot be attested away. Consent before any source is queried, bank account validation, the tax identifiers returns are filed under, and duplicate detection within the organisation's own population.

sources_without_credentials array of string optional

The sources you hold no credentials for, by name. No check that needs one of them can run until you supply them.

subjects_without_consent integer optional

How many subjects on file have no active consent covering the checks you use.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/readiness" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityReadinessRetrieve({});
const response = await fetch('https://sandbox.droomwork.io/v1/identity/readiness', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_readiness_retrieve()
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/readiness',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityReadinessRetrieve();
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/readiness');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityReadinessRetrieve();
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/readiness"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityReadinessRetrieve();
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/readiness");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityReadinessRetrieve(ctx).Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/readiness", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "readiness_report",
  "module": "anchor",
  "mode": "integrated",
  "ready": true,
  "rows": [
    {
      "fact": "anchored_subject",
      "owner": "anchor",
      "required": "attested",
      "held": "attested",
      "satisfied": true,
      "contract_row": "6.1.13",
      "source": "integrated",
      "missing_because": "not_supplied"
    }
  ],
  "always_enforced": [
    "example"
  ],
  "sources_without_credentials": [
    "example"
  ],
  "subjects_without_consent": 1
}
POST/v1/identity/verifications/{verification_id}/resolve#

Resolve a verification

identity.verifications.resolve

The subject was identified. A Passport is issued at the assurance level the evidence reached, which may be lower than the level you asked for.

Path parameters

verification_id string required

The verification's identifier, starting with anchor_pro_verification_: the id returned by POST /v1/identity/verifications or listed by GET /v1/identity/verifications, or a batch result's verification_id.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Returns

The verification in its new state.

id string required

The verification's identifier, starting with anchor_pro_verification_. POST /v1/identity/verifications returns it and it never changes; pass it as verification_id wherever a call names this verification.

object always "identity_verification" required

Always identity_verification. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

outcome string required

unresolved is a real outcome and never a rejection. A source that did not answer proves nothing either way. Don't treat silence as a pass.

pendingresolvedunresolvedblocked
origin string required

How the claim arrived. The behaviour is the same whichever way it came in.

partner_apiself_serveassisted_enrolment
subject_ref string required

Your opaque reference to the person being verified, exactly as you sent subject_ref at POST /v1/identity/verifications. Not a name and not an identifier.

consent_token_id string optional

The consent token this verification ran under, as you sent it at POST /v1/identity/verifications: the id starting with anchor_pro_consent_ that POST /v1/identity/consent_tokens returned for this subject, purpose and checks.

target_assurance string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
assurance_reached one of optional

The level the evidence actually established, which can be lower than target_assurance. null when nothing has been established yet.

AssuranceLevelor
passport_id string · nullable optional

The id of the Passport this verification resolved to, starting with anchor_pro_passport_: what every module checks before it acts. Read it at GET /v1/identity/passports/{passport_id}; null until outcome is resolved.

evidence_bundle_id string · nullable optional

The id of the bundle listing every source consulted and what each said. Read it at GET /v1/identity/verifications/{verification_id}/evidence_bundle using this verification's id; null while there is nothing to show yet.

unresolved_source string · nullable optional

Named when the outcome is unresolved. Silence always names its source.

retry_after string · date-time · nullable optional

When to try again, as an RFC 3339 timestamp in UTC. Set when the outcome is unresolved; null otherwise.

blocked_because string · nullable optional

Why outcome is blocked: no_consent (no active token), consent_scope_insufficient (the token doesn't cover what was asked) or subject_blocklisted. The subject is entitled to know which; null for any other outcome.

no_consentconsent_scope_insufficientsubject_blocklistednull
created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/resolve" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityVerificationsResolve({ verificationId: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/resolve', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Idempotency-Key': crypto.randomUUID(),
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_verifications_resolve(verification_id='anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/resolve',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityVerificationsResolve(verification_id: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/resolve');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityVerificationsResolve("anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/resolve"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityVerificationsResolve(verificationId: "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/resolve");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityVerificationsResolve(ctx, "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/resolve", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "identity_verification",
  "livemode": true,
  "mocked": true,
  "outcome": "pending",
  "origin": "partner_api",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "target_assurance": "dal_0",
  "assurance_reached": "dal_0",
  "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "evidence_bundle_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "unresolved_source": "example",
  "retry_after": "2026-09-01T09:00:00Z",
  "blocked_because": "no_consent",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/verifications/{verification_id}/mark_unresolved#

Mark a verification unresolved

identity.verifications.mark_unresolved

Unresolved is a real outcome, and it names the source that couldn't answer. It is never a rejection and never a silent pass: a subject who can't be verified today is not a subject who failed.

Path parameters

verification_id string required

The verification's identifier, starting with anchor_pro_verification_: the id returned by POST /v1/identity/verifications or listed by GET /v1/identity/verifications, or a batch result's verification_id.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Returns

The verification in its new state.

id string required

The verification's identifier, starting with anchor_pro_verification_. POST /v1/identity/verifications returns it and it never changes; pass it as verification_id wherever a call names this verification.

object always "identity_verification" required

Always identity_verification. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

outcome string required

unresolved is a real outcome and never a rejection. A source that did not answer proves nothing either way. Don't treat silence as a pass.

pendingresolvedunresolvedblocked
origin string required

How the claim arrived. The behaviour is the same whichever way it came in.

partner_apiself_serveassisted_enrolment
subject_ref string required

Your opaque reference to the person being verified, exactly as you sent subject_ref at POST /v1/identity/verifications. Not a name and not an identifier.

consent_token_id string optional

The consent token this verification ran under, as you sent it at POST /v1/identity/verifications: the id starting with anchor_pro_consent_ that POST /v1/identity/consent_tokens returned for this subject, purpose and checks.

target_assurance string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
assurance_reached one of optional

The level the evidence actually established, which can be lower than target_assurance. null when nothing has been established yet.

AssuranceLevelor
passport_id string · nullable optional

The id of the Passport this verification resolved to, starting with anchor_pro_passport_: what every module checks before it acts. Read it at GET /v1/identity/passports/{passport_id}; null until outcome is resolved.

evidence_bundle_id string · nullable optional

The id of the bundle listing every source consulted and what each said. Read it at GET /v1/identity/verifications/{verification_id}/evidence_bundle using this verification's id; null while there is nothing to show yet.

unresolved_source string · nullable optional

Named when the outcome is unresolved. Silence always names its source.

retry_after string · date-time · nullable optional

When to try again, as an RFC 3339 timestamp in UTC. Set when the outcome is unresolved; null otherwise.

blocked_because string · nullable optional

Why outcome is blocked: no_consent (no active token), consent_scope_insufficient (the token doesn't cover what was asked) or subject_blocklisted. The subject is entitled to know which; null for any other outcome.

no_consentconsent_scope_insufficientsubject_blocklistednull
created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/mark_unresolved" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityVerificationsMarkUnresolved({ verificationId: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/mark_unresolved', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Idempotency-Key': crypto.randomUUID(),
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_verifications_mark_unresolved(verification_id='anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/mark_unresolved',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityVerificationsMarkUnresolved(verification_id: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/mark_unresolved');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityVerificationsMarkUnresolved("anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/mark_unresolved"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityVerificationsMarkUnresolved(verificationId: "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/mark_unresolved");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityVerificationsMarkUnresolved(ctx, "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/mark_unresolved", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "identity_verification",
  "livemode": true,
  "mocked": true,
  "outcome": "pending",
  "origin": "partner_api",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "target_assurance": "dal_0",
  "assurance_reached": "dal_0",
  "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "evidence_bundle_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "unresolved_source": "example",
  "retry_after": "2026-09-01T09:00:00Z",
  "blocked_because": "no_consent",
  "created_at": "2026-09-01T09:00:00Z"
}
POST/v1/identity/verifications/{verification_id}/block#

Block a verification

identity.verifications.block

For a subject on the blocklist, or a consent that doesn't cover what was asked. The reason is recorded; a blocked subject is entitled to know which.

Path parameters

verification_id string required

The verification's identifier, starting with anchor_pro_verification_: the id returned by POST /v1/identity/verifications or listed by GET /v1/identity/verifications, or a batch result's verification_id.

Headers

Idempotency-Key string required

A key you make up for this request, such as a UUID, up to 255 characters. Sending the same key with the same body returns the original response, marked Droomwork-Idempotent-Replay: true; sending it with a different body is refused with idempotency_key_reused.

Returns

The verification in its new state.

id string required

The verification's identifier, starting with anchor_pro_verification_. POST /v1/identity/verifications returns it and it never changes; pass it as verification_id wherever a call names this verification.

object always "identity_verification" required

Always identity_verification. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm this record is in: false is the sandbox, true is live. Read it before you act on anything.

mocked boolean required

Where these figures came from: true when they were mocked, false when they were computed for real. Not the inverse of livemode: each record carries the answer that was true for it.

outcome string required

unresolved is a real outcome and never a rejection. A source that did not answer proves nothing either way. Don't treat silence as a pass.

pendingresolvedunresolvedblocked
origin string required

How the claim arrived. The behaviour is the same whichever way it came in.

partner_apiself_serveassisted_enrolment
subject_ref string required

Your opaque reference to the person being verified, exactly as you sent subject_ref at POST /v1/identity/verifications. Not a name and not an identifier.

consent_token_id string optional

The consent token this verification ran under, as you sent it at POST /v1/identity/verifications: the id starting with anchor_pro_consent_ that POST /v1/identity/consent_tokens returned for this subject, purpose and checks.

target_assurance string optional

What was actually established. DAL-3 and DAL-4 are documented and not delivered in this release.

dal_0dal_1dal_2dal_3dal_4
assurance_reached one of optional

The level the evidence actually established, which can be lower than target_assurance. null when nothing has been established yet.

AssuranceLevelor
passport_id string · nullable optional

The id of the Passport this verification resolved to, starting with anchor_pro_passport_: what every module checks before it acts. Read it at GET /v1/identity/passports/{passport_id}; null until outcome is resolved.

evidence_bundle_id string · nullable optional

The id of the bundle listing every source consulted and what each said. Read it at GET /v1/identity/verifications/{verification_id}/evidence_bundle using this verification's id; null while there is nothing to show yet.

unresolved_source string · nullable optional

Named when the outcome is unresolved. Silence always names its source.

retry_after string · date-time · nullable optional

When to try again, as an RFC 3339 timestamp in UTC. Set when the outcome is unresolved; null otherwise.

blocked_because string · nullable optional

Why outcome is blocked: no_consent (no active token), consent_scope_insufficient (the token doesn't cover what was asked) or subject_blocklisted. The subject is entitled to know which; null for any other outcome.

no_consentconsent_scope_insufficientsubject_blocklistednull
created_at string · date-time optional

When the record was created, as an RFC 3339 timestamp in UTC.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.
409The record is not in a state that allows this.
422A required fact is missing. Call the readiness endpoint to see what.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X POST "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/block" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityVerificationsBlock({ verificationId: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/block', {
  method: 'POST',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
    'Idempotency-Key': crypto.randomUUID(),
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_verifications_block(verification_id='anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z')
import os
import uuid

import requests

response = requests.request(
    'POST',
    'https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/block',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
        'Idempotency-Key': str(uuid.uuid4()),
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityVerificationsBlock(verification_id: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/block');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
    'Idempotency-Key: ' . bin2hex(random_bytes(16)),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityVerificationsBlock("anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/block"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .header("Idempotency-Key", UUID.randomUUID().toString())
    .method("POST", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityVerificationsBlock(verificationId: "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/block");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
request.Headers.Add("Idempotency-Key", Guid.NewGuid().ToString());
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityVerificationsBlock(ctx, "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Execute()
req, _ := http.NewRequest("POST", "https://sandbox.droomwork.io/v1/identity/verifications/anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z/block", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
req.Header.Set("Idempotency-Key", uuid.NewString())
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "identity_verification",
  "livemode": true,
  "mocked": true,
  "outcome": "pending",
  "origin": "partner_api",
  "subject_ref": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "consent_token_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "target_assurance": "dal_0",
  "assurance_reached": "dal_0",
  "passport_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "evidence_bundle_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "unresolved_source": "example",
  "retry_after": "2026-09-01T09:00:00Z",
  "blocked_because": "no_consent",
  "created_at": "2026-09-01T09:00:00Z"
}
GET/v1/identity/events#

List events

identity.events.list

Every identity event, oldest first, and nothing is ever removed. Every event here is one the webhook catalogue declares, so the code that handles a delivery handles a replay too.

Two ways to read it. Pass stream with after to replay one stream from the sequence you last handled; that is exact and needs no cursor. The sequence counts per organisation and per stream, so it's the only ordering you can rely on. Without stream, you get events across streams in the order they were recorded, paged with starting_after.

Query parameters

stream string optional

The id of the record whose events you want, such as a verification's (anchor_pro_verification_…) from POST /v1/identity/verifications; a Passport, consent token or disclosure works the same. Leave it out to get events across every record.

after integer optional

The sequence of the last event you handled on that stream, read off an event in this list or a webhook delivery; you get the events after it. 0 reads from the start, and it needs stream beside it.

limit integer optional

How many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.

starting_after string optional

The id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.

Returns

A page of events.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of StoredEvent required

The records on this page, in the order the list promises. Empty when nothing matched.

13 fields of StoredEvent
id string required

The event's identifier, starting with evt_, the same on a webhook delivery and on the module's events list, such as GET /v1/payroll/events. It never changes: a redelivery carries the same id, so you can recognise an event you have already handled.

type string required

What happened, as module.resource.past_tense_verb, for example run.payslip.calculated. Pick your handler on it; data takes the shape this type promises.

schema_version integer · minimum 1 required

The version of the shape data takes for this type, starting at 1. A change to the shape raises it, so check it before you read data.

org_id string required

The organisation the event belongs to, by its id, which starts with org_: the one POST /v1/registrations gave you and GET /v1/me returns. You only ever receive events for your own organisation.

sequence integer · minimum 0 required

Per organisation and per stream. It is how a consumer tells a replay from a new event, and it is what the delivery guarantee rests on.

occurred_at string · date-time required

When the event happened, as an RFC 3339 timestamp in UTC. Not when it was delivered: a redelivery carries the original value.

request_id string optional

The request that caused this event, where one did: the Droomwork-Request-Id that request returned, starting with req_. Absent for an event a schedule raised, such as an engagement lapsing on its end date.

livemode boolean required

Which realm the event happened in. False is the sandbox.

mocked boolean required

Whether a mock produced this fact, rather than an engine computing it. Recorded on the event when it was appended and never worked out afterwards from the realm: the two answers agree while every module is on its mock and part on the day the first engine ships. See ADR-0011.

source string required

Which part of Droomwork is the authority for this fact: anchor (identity), proof (credentials), rail (engagements), flow (sourcing), match (allocation), run (payroll), remit (remittance), route (payouts), gateway (the API's front door), iam (accounts and API keys), ledger (the books), registry (rule packs), delivery (webhooks and messages), documents (rendered payslips and instruments) or intelligence (AI decisions). Read the fact from there when it matters; your own copy is never the authority.

anchorproofrailflowmatchrunremitroutegatewayiamledgerregistrydeliverydocumentsintelligence
object always "event" required

Always event. Tells you which kind of record you are looking at, so one handler can read any response.

stream string required

The id of the record this event is about, such as a verification's anchor_pro_verification_…. sequence counts per organisation and per stream, so it means nothing without this; pass it as stream to GET /v1/identity/events to replay.

data object required

The record the event is about, as it stood when the event happened. Its shape follows type: a verification event carries the verification, a Passport event the Passport.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
curl -X GET "https://sandbox.droomwork.io/v1/identity/events?stream=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
const result = await api.identityEventsList({ stream: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', after: 0, limit: 25 });
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/identity/events?stream=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

# query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
result = api.identity_events_list(stream='anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', after=0, limit=25)
import os

import requests

# query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/events?stream=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

# query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
$result = $api->identityEventsList(stream: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', after: 0, limit: 25);
<?php
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/events?stream=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
var result = api.identityEventsList("anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", 0, 25, null);
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/events?stream=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
var result = api.IdentityEventsList(stream: "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", after: 0, limit: 25);
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/events?stream=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
result, _, err := client.ANCHORAPI.IdentityEventsList(ctx).Stream("anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").After(0).Limit(25).Execute()
// query parameters: stream (optional), after (optional), limit (optional), starting_after (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/events?stream=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&after=0&limit=25", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "list",
  "data": [
    {
      "id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "type": "run.payslip.calculated",
      "schema_version": 1,
      "org_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "sequence": 0,
      "occurred_at": "2026-09-01T09:00:00Z",
      "livemode": true,
      "mocked": true,
      "source": "anchor",
      "request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "event",
      "stream": "example",
      "data": {}
    }
  ],
  "has_more": true
}
GET/v1/identity/events/{event_id}#

Retrieve an event

identity.events.retrieve

You get one event. An identifier belonging to another organisation comes back not found rather than refused; a refusal would confirm it exists.

Path parameters

event_id string required

The event's id, as GET /v1/identity/events lists it or as a webhook delivery carries it. It starts with evt_.

Returns

The event.

id string required

The event's identifier, starting with evt_, the same on a webhook delivery and on the module's events list, such as GET /v1/payroll/events. It never changes: a redelivery carries the same id, so you can recognise an event you have already handled.

type string required

What happened, as module.resource.past_tense_verb, for example run.payslip.calculated. Pick your handler on it; data takes the shape this type promises.

schema_version integer · minimum 1 required

The version of the shape data takes for this type, starting at 1. A change to the shape raises it, so check it before you read data.

org_id string required

The organisation the event belongs to, by its id, which starts with org_: the one POST /v1/registrations gave you and GET /v1/me returns. You only ever receive events for your own organisation.

sequence integer · minimum 0 required

Per organisation and per stream. It is how a consumer tells a replay from a new event, and it is what the delivery guarantee rests on.

occurred_at string · date-time required

When the event happened, as an RFC 3339 timestamp in UTC. Not when it was delivered: a redelivery carries the original value.

request_id string optional

The request that caused this event, where one did: the Droomwork-Request-Id that request returned, starting with req_. Absent for an event a schedule raised, such as an engagement lapsing on its end date.

livemode boolean required

Which realm the event happened in. False is the sandbox.

mocked boolean required

Whether a mock produced this fact, rather than an engine computing it. Recorded on the event when it was appended and never worked out afterwards from the realm: the two answers agree while every module is on its mock and part on the day the first engine ships. See ADR-0011.

source string required

Which part of Droomwork is the authority for this fact: anchor (identity), proof (credentials), rail (engagements), flow (sourcing), match (allocation), run (payroll), remit (remittance), route (payouts), gateway (the API's front door), iam (accounts and API keys), ledger (the books), registry (rule packs), delivery (webhooks and messages), documents (rendered payslips and instruments) or intelligence (AI decisions). Read the fact from there when it matters; your own copy is never the authority.

anchorproofrailflowmatchrunremitroutegatewayiamledgerregistrydeliverydocumentsintelligence
object always "event" required

Always event. Tells you which kind of record you are looking at, so one handler can read any response.

stream string required

The id of the record this event is about, such as a verification's anchor_pro_verification_…. sequence counts per organisation and per stream, so it means nothing without this; pass it as stream to GET /v1/identity/events to replay.

data object required

The record the event is about, as it stood when the event happened. Its shape follows type: a verification event carries the verification, a Passport event the Passport.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/events/%7Bevent_id%7D" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityEventsRetrieve({ eventId: '{event_id}' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/events/%7Bevent_id%7D', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_events_retrieve(event_id='{event_id}')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/events/%7Bevent_id%7D',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityEventsRetrieve(event_id: '{event_id}');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/events/%7Bevent_id%7D');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityEventsRetrieve("{event_id}");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/events/%7Bevent_id%7D"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityEventsRetrieve(eventId: "{event_id}");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/events/%7Bevent_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityEventsRetrieve(ctx, "{event_id}").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/events/%7Bevent_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "evt_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "type": "run.payslip.calculated",
  "schema_version": 1,
  "org_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "sequence": 0,
  "occurred_at": "2026-09-01T09:00:00Z",
  "livemode": true,
  "mocked": true,
  "source": "anchor",
  "request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "event",
  "stream": "example",
  "data": {}
}
GET/v1/identity/audit_entries#

List audit entries

identity.audit_entries.list

Who did what, newest first. One row per attempt, not per success: refusals are recorded too, and repeated forbidden answers on one credential is what an attack looks like from the inside.

A read that succeeded isn't recorded.

Query parameters

action string optional

Only attempts at one action, matched exactly on action as it reads on each entry: the method and route pattern, such as POST /v1/identity/verifications. Leave it out to get every action.

actor_id string optional

Only one credential's attempts, matched exactly on actor_id as it reads on each entry: your API key's id (api_key_…), your OAuth client_id or a staff member's. Leave it out for every actor; add outcome=refused to watch one key.

resource string optional

Only attempts on one kind of record, matched exactly on resource as it reads on each entry: the collection segment of the route, such as verifications or passports. Leave it out to get every kind.

resource_id string optional

Only attempts on one record, matched exactly on resource_id as it reads on each entry: the record's id as it appeared in the route, such as a verification's anchor_pro_verification_…. Pair it with resource; leave it out to get every record.

outcome string optional

Only entries with one outcome: succeeded (it went through), refused (turned away with a 4xx status) or failed (it broke on our side with a 5xx). Leave it out to get all three.

succeededrefusedfailed
recorded_after string optional

Only entries whose at is after this moment, as an RFC 3339 timestamp in UTC. Exclusive: an entry at exactly this instant is left out; leave it out to start from the oldest entry.

recorded_before string optional

Only entries whose at is before this moment, as an RFC 3339 timestamp in UTC; exclusive, like recorded_after. Pair the two to bound a window; leave it out to run to the newest entry.

limit integer optional

How many records to return on one page, from 1 to 100, and 25 if you leave it out. When has_more is true, pass the last record's id as starting_after to get the next page.

starting_after string optional

The id of the last record on the previous page of this same list. Leave it out to get the first page; when a page comes back with has_more true, send its last record's id here to get the page after it.

Returns

A page of audit entries.

object always "list" required

Always list. Tells you which kind of record you are looking at, so one handler can read any response.

data array of AuditEntry required

The records on this page, in the order the list promises. Empty when nothing matched.

13 fields of AuditEntry
id string required

The record's identifier, as GET /v1/identity/audit_entries lists it. It starts with audit_entry_ and never changes; pass it as audit_entry_id to GET /v1/identity/audit_entries/{audit_entry_id}.

object always "audit_entry" required

Always audit_entry. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm the action happened in. False is the sandbox.

mocked boolean required

Whether the route this attempt was aimed at is served by a mock. It describes the route, not the answer: a refused request and a replayed idempotent request against a mocked route both say true.

at string · date-time required

When the attempt was made, as an RFC 3339 timestamp in UTC. The list orders entries newest first by it.

request_id string required

The request that made this attempt. It's the same request_id an error response carries, so a refusal you were shown can be matched to its entry here.

actor_type string required

What kind of credential acted: client for one of your API keys or OAuth clients, staff for a Droomwork staff member acting under a grant. actor_id says which one.

actor_id string required

The id of the credential that made the attempt: your API key's (api_key_…) or the client_id you send to POST /v1/oauth/token when actor_type is client, a staff member's when it is staff. Filter the list on it to follow one.

action string required

What was attempted, as the method and the route pattern.

resource string · nullable optional

The kind of record acted on, as the collection name in the route, such as verifications. null when the route named none.

resource_id string · nullable optional

The id of the record the attempt named in its path, exactly as it appeared there, such as a Passport's anchor_pro_passport_…. null when the attempt was against a collection rather than one record.

outcome string required

How the attempt ended: succeeded means it went through, refused that it was turned away with a 4xx status, failed that it broke on our side with a 5xx. Filter the list on it with outcome.

succeededrefusedfailed
status integer required

The HTTP status code the attempt was answered with, such as 201 or 403. outcome groups it into three words; this is the exact number.

has_more boolean required

true when there are more records after this page. Pass the last record's id as starting_after to get the next page.

Other responses

400The request could not be read, or a value was refused.
401No valid credential was presented.
403The credential does not carry the required scope.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
# query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
curl -X GET "https://sandbox.droomwork.io/v1/identity/audit_entries?action=POST%20%2Fv1%2Fidentity%2Fverifications&actor_id=api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=verifications&resource_id=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
const result = await api.identityAuditEntriesList({ action: 'POST /v1/identity/verifications', actorId: 'api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', resource: 'verifications', resourceId: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', outcome: 'succeeded', recordedAfter: '2026-01-01T00:00:00Z', recordedBefore: '2027-01-01T00:00:00Z', limit: 25 });
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
const response = await fetch('https://sandbox.droomwork.io/v1/identity/audit_entries?action=POST%20%2Fv1%2Fidentity%2Fverifications&actor_id=api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=verifications&resource_id=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

# query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
result = api.identity_audit_entries_list(action='POST /v1/identity/verifications', actor_id='api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', resource='verifications', resource_id='anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', outcome='succeeded', recorded_after='2026-01-01T00:00:00Z', recorded_before='2027-01-01T00:00:00Z', limit=25)
import os

import requests

# query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/audit_entries?action=POST%20%2Fv1%2Fidentity%2Fverifications&actor_id=api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=verifications&resource_id=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

# query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
$result = $api->identityAuditEntriesList(action: 'POST /v1/identity/verifications', actor_id: 'api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', resource: 'verifications', resource_id: 'anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z', outcome: 'succeeded', recorded_after: '2026-01-01T00:00:00Z', recorded_before: '2027-01-01T00:00:00Z', limit: 25);
<?php
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/audit_entries?action=POST%20%2Fv1%2Fidentity%2Fverifications&actor_id=api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=verifications&resource_id=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
var result = api.identityAuditEntriesList("POST /v1/identity/verifications", "api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "verifications", "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", "succeeded", "2026-01-01T00:00:00Z", "2027-01-01T00:00:00Z", 25, null);
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/audit_entries?action=POST%20%2Fv1%2Fidentity%2Fverifications&actor_id=api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=verifications&resource_id=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
var result = api.IdentityAuditEntriesList(action: "POST /v1/identity/verifications", actorId: "api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", resource: "verifications", resourceId: "anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z", outcome: "succeeded", recordedAfter: "2026-01-01T00:00:00Z", recordedBefore: "2027-01-01T00:00:00Z", limit: 25);
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/audit_entries?action=POST%20%2Fv1%2Fidentity%2Fverifications&actor_id=api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=verifications&resource_id=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
result, _, err := client.ANCHORAPI.IdentityAuditEntriesList(ctx).Action("POST /v1/identity/verifications").ActorId("api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Resource("verifications").ResourceId("anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z").Outcome("succeeded").RecordedAfter("2026-01-01T00:00:00Z").RecordedBefore("2027-01-01T00:00:00Z").Limit(25).Execute()
// query parameters: action (optional), actor_id (optional), resource (optional), resource_id (optional), outcome (optional), recorded_after (optional), recorded_before (optional), limit (optional), starting_after (optional)
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/audit_entries?action=POST%20%2Fv1%2Fidentity%2Fverifications&actor_id=api_key_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&resource=verifications&resource_id=anchor_pro_verification_01J8XQ4M7K2N9P3R5T7V9W1Y3Z&outcome=succeeded&recorded_after=2026-01-01T00%3A00%3A00Z&recorded_before=2027-01-01T00%3A00%3A00Z&limit=25", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "object": "list",
  "data": [
    {
      "id": "audit_entry_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "object": "audit_entry",
      "livemode": true,
      "mocked": true,
      "at": "2026-09-01T09:00:00Z",
      "request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "actor_type": "example",
      "actor_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
      "action": "example",
      "outcome": "succeeded",
      "status": 1,
      "resource": "example",
      "resource_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
    }
  ],
  "has_more": true
}
GET/v1/identity/audit_entries/{audit_entry_id}#

Retrieve an audit entry

identity.audit_entries.retrieve

You get one entry. An identifier belonging to another organisation comes back not found rather than refused; a refusal would confirm it exists.

Path parameters

audit_entry_id string required

The entry's id, as GET /v1/identity/audit_entries lists it. It starts with audit_entry_.

Returns

The audit entry.

id string required

The record's identifier, as GET /v1/identity/audit_entries lists it. It starts with audit_entry_ and never changes; pass it as audit_entry_id to GET /v1/identity/audit_entries/{audit_entry_id}.

object always "audit_entry" required

Always audit_entry. Tells you which kind of record you are looking at, so one handler can read any response.

livemode boolean required

Which realm the action happened in. False is the sandbox.

mocked boolean required

Whether the route this attempt was aimed at is served by a mock. It describes the route, not the answer: a refused request and a replayed idempotent request against a mocked route both say true.

at string · date-time required

When the attempt was made, as an RFC 3339 timestamp in UTC. The list orders entries newest first by it.

request_id string required

The request that made this attempt. It's the same request_id an error response carries, so a refusal you were shown can be matched to its entry here.

actor_type string required

What kind of credential acted: client for one of your API keys or OAuth clients, staff for a Droomwork staff member acting under a grant. actor_id says which one.

actor_id string required

The id of the credential that made the attempt: your API key's (api_key_…) or the client_id you send to POST /v1/oauth/token when actor_type is client, a staff member's when it is staff. Filter the list on it to follow one.

action string required

What was attempted, as the method and the route pattern.

resource string · nullable optional

The kind of record acted on, as the collection name in the route, such as verifications. null when the route named none.

resource_id string · nullable optional

The id of the record the attempt named in its path, exactly as it appeared there, such as a Passport's anchor_pro_passport_…. null when the attempt was against a collection rather than one record.

outcome string required

How the attempt ended: succeeded means it went through, refused that it was turned away with a 4xx status, failed that it broke on our side with a 5xx. Filter the list on it with outcome.

succeededrefusedfailed
status integer required

The HTTP status code the attempt was answered with, such as 201 or 403. outcome groups it into three words; this is the exact number.

Other responses

401No valid credential was presented.
403The credential does not carry the required scope.
404No record with that identifier.

Errors it can return

Sends against https://sandbox.droomwork.io
Request
which?
curl -X GET "https://sandbox.droomwork.io/v1/identity/audit_entries/%7Baudit_entry_id%7D" \
  -H "Droomwork-Api-Key: $DROOMWORK_API_KEY"
import { Configuration, ANCHORApi } from '@droomwork/sdk';

const api = new ANCHORApi(new Configuration({ basePath: 'https://sandbox.droomwork.io', accessToken: process.env.DROOMWORK_API_KEY }));

const result = await api.identityAuditEntriesRetrieve({ auditEntryId: '{audit_entry_id}' });
const response = await fetch('https://sandbox.droomwork.io/v1/identity/audit_entries/%7Baudit_entry_id%7D', {
  method: 'GET',
  headers: {
    'Droomwork-Api-Key': process.env.DROOMWORK_API_KEY,
  },
});
const result = await response.json();
import os

import droomwork

config = droomwork.Configuration(access_token=os.environ['DROOMWORK_API_KEY'])
config.host = 'https://sandbox.droomwork.io'
client = droomwork.ApiClient(config)
api = droomwork.ANCHORApi(client)

result = api.identity_audit_entries_retrieve(audit_entry_id='{audit_entry_id}')
import os

import requests

response = requests.request(
    'GET',
    'https://sandbox.droomwork.io/v1/identity/audit_entries/%7Baudit_entry_id%7D',
    headers={
        'Droomwork-Api-Key': os.environ['DROOMWORK_API_KEY'],
    },
)
result = response.json()
<?php
require_once __DIR__ . '/vendor/autoload.php';

$config = DroomworkSdk\Configuration::getDefaultConfiguration()
  ->setHost('https://sandbox.droomwork.io')
  ->setAccessToken(getenv('DROOMWORK_API_KEY'));
$api = new DroomworkSdk\Api\ANCHORApi(new GuzzleHttp\Client(), $config);

$result = $api->identityAuditEntriesRetrieve(audit_entry_id: '{audit_entry_id}');
<?php
$ch = curl_init('https://sandbox.droomwork.io/v1/identity/audit_entries/%7Baudit_entry_id%7D');
curl_setopt_array($ch, [
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_HTTPHEADER => [
    'Droomwork-Api-Key: ' . getenv('DROOMWORK_API_KEY'),
  ],
]);
$result = json_decode(curl_exec($ch), true);
import com.droomwork.sdk.ApiClient;
import com.droomwork.sdk.Configuration;
import com.droomwork.sdk.api.AnchorApi;

ApiClient client = Configuration.getDefaultApiClient();
client.setBasePath("https://sandbox.droomwork.io");
client.setAccessToken(System.getenv("DROOMWORK_API_KEY"));
AnchorApi api = new AnchorApi(client);

var result = api.identityAuditEntriesRetrieve("{audit_entry_id}");
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create("https://sandbox.droomwork.io/v1/identity/audit_entries/%7Baudit_entry_id%7D"))
    .header("Droomwork-Api-Key", System.getenv("DROOMWORK_API_KEY"))
    .method("GET", HttpRequest.BodyPublishers.noBody())
    .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
String result = response.body();
using Droomwork.Sdk.Api;
using Droomwork.Sdk.Client;

var config = new Configuration { BasePath = "https://sandbox.droomwork.io" };
config.AccessToken = Environment.GetEnvironmentVariable("DROOMWORK_API_KEY");
var api = new ANCHORApi(config);

var result = api.IdentityAuditEntriesRetrieve(auditEntryId: "{audit_entry_id}");
using var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Get, "https://sandbox.droomwork.io/v1/identity/audit_entries/%7Baudit_entry_id%7D");
request.Headers.Add("Droomwork-Api-Key", Environment.GetEnvironmentVariable("DROOMWORK_API_KEY"));
var response = await client.SendAsync(request);
var result = await response.Content.ReadAsStringAsync();
import droomwork "github.com/fenibofubara/droomwork-sdk-go"

ctx := context.WithValue(context.Background(), droomwork.ContextAPIKeys, map[string]droomwork.APIKey{
	"apiKey": {Key: os.Getenv("DROOMWORK_API_KEY")},
})
cfg := droomwork.NewConfiguration()
cfg.Servers = droomwork.ServerConfigurations{{URL: "https://sandbox.droomwork.io"}}
client := droomwork.NewAPIClient(cfg)

result, _, err := client.ANCHORAPI.IdentityAuditEntriesRetrieve(ctx, "{audit_entry_id}").Execute()
req, _ := http.NewRequest("GET", "https://sandbox.droomwork.io/v1/identity/audit_entries/%7Baudit_entry_id%7D", nil)
req.Header.Set("Droomwork-Api-Key", os.Getenv("DROOMWORK_API_KEY"))
res, err := http.DefaultClient.Do(req)
if err != nil {
	return err
}
defer res.Body.Close()
result, _ := io.ReadAll(res.Body)
Response
{
  "id": "audit_entry_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "object": "audit_entry",
  "livemode": true,
  "mocked": true,
  "at": "2026-09-01T09:00:00Z",
  "request_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "actor_type": "example",
  "actor_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z",
  "action": "example",
  "outcome": "succeeded",
  "status": 1,
  "resource": "example",
  "resource_id": "sub_01J8XQ4M7K2N9P3R5T7V9W1Y3Z"
}