Download OpenAPI specification:Download
External integrator API for reading and manipulating Customers, their Digital Identities and the Assignments that link them to your own artifacts, in the IDV platform's customer store.
This API is part of the storage tier. Tenants whose personal-data storage
is switched off do not receive the onboarding-service audience in their
access token, so every endpoint in this document is rejected at the gateway
with 403. Contact Innovatrics to enable storage for your tenant.
Integrators authenticate with an OAuth2 client_credentials JWT
(bearerAuth) issued by Keycloak in the integrators realm. The token must
carry the audience onboarding-service — the API gateway rejects tokens
without it before the request reaches the service.
The gateway validates the token and injects the X-Org-Id header that scopes
every request to your tenant — integrators never send X-Org-Id themselves.
The service's internal path is /api/v1/*; the gateway exposes it at
/integrator/v1/* and rewrites to /api/v1/*. All paths in this document
are relative to the server you pick; every operational path begins with
/v1, and the unauthenticated /healthz probe sits outside that lane.
The gateway applies a per-tenant limit of 200 requests/minute to
/integrator/v1/*, alongside a global limit shared across tenants.
Exceeding a limit returns 429 Too Many Requests. A 429 is produced by
the gateway rather than the service, so it does not use the
ErrorResponse envelope. Back off and retry.
While a verification workflow run is authoritative over a Customer, integrator writes that would race it are rejected:
PATCH /v1/customers/{customerId} touching a workflow-managed field →
409 WORKFLOW_RUN_ACTIVE (fails open on a guard outage: the
write proceeds). The guard covers name, given_name, surname,
date_of_birth, date_of_birth_raw, place_of_birth, decision and
primary_digital_identity_id; of those, only name, given_name,
surname, place_of_birth and date_of_birth are writable through
this endpoint at all.POST .../transition and every .../anonymize → 409
WORKFLOW_RUN_ACTIVE, or 503 ACTIVE_RUN_GUARD_UNAVAILABLE if the
guard cannot be reached (fails closed).Anonymization is a GDPR erasure — it cannot be undone through this API.
customer_id with a freshly
generated opaque UUID, because the original identifier may itself carry
personal data. The customer_id returned by the anonymize call is that
NEW id, and the id you called with stops resolving. Record the returned
value if you need to reach the erased record again.PATCH /v1/customers/{customerId} on an anonymized Customer →
409 CUSTOMER_ANONYMIZED.POST .../transition on an anonymized Digital Identity →
409 IDENTITY_ANONYMIZED.Two writes take an Idempotency-Key header, and for those two it is
required — POST /v1/assignments and POST /v1/assignments/transfer.
A request without it is rejected with 400 bad_request.
Replaying a key against the same path returns the original status code and
response body without repeating the work. The key is matched on its own:
the request body is not fingerprinted, so reusing a key with a different
body silently returns the first response rather than reporting a mismatch —
generate a fresh key per logical operation. A second request arriving while
the first is still in flight returns 409 conflict. Failed requests are
not recorded, so retrying after an error re-executes. Keys are retained for
a tenant-configured window, 24 hours by default.
No other endpoint in this document reads Idempotency-Key.
Errors raised by the service share one envelope (ErrorResponse):
{ "success": false, "error": { "message", "code", "details"? } }.
Business/validation failures use 4xx; the per-operation code values are
listed on each response. Gateway-level rejections (401, 403, 429) do not use
this envelope.
Returns the static field descriptors for the Customer model — name, type, label, and whether each field is integrator-writable / searchable. There are no per-tenant custom fields, so this is a fixed list.
{- "fields": [
- {
- "name": "string",
- "type": "string",
- "label": "string",
- "source": "string",
- "writable_by_integrator": true,
- "searchable": true
}
]
}Exact-match search over an allow-list of PII fields. Sent as a POST body so PII stays out of URLs/logs. The body must be a non-empty object whose keys are a subset of the searchable fields; any other key → 400 invalid_search_field. Returns up to 200 results; next_cursor is always null (search is not paginated).
Anonymized Customers have their PII erased (all searchable fields are null), so they never match a PII search. Their customer_id is also replaced at erasure, so only the new id returned by the anonymize call reaches the erased record. null filter values are rejected (a null match would enumerate erased fields).
| customer_id | string |
| name | string |
| given_name | string |
| surname | string |
| place_of_birth | string |
| date_of_birth | string <date> ISO-8601 date (YYYY-MM-DD). |
{- "customer_id": "string",
- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24"
}{- "items": [
- {
- "customer_id": "string",
- "state": "pending",
- "decision": "pending",
- "status": "active",
- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24",
- "date_of_birth_raw": "string",
- "personal_number": "string",
- "primary_identity_id": "string",
- "document_number": "string",
- "issuing_country": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "next_cursor": "string"
}Keyset-paginated list ordered by (created_at desc, customer_id desc). Pass the returned next_cursor back as cursor to fetch the next page; a null next_cursor means the last page.
| customer_id | string Exact match on the Customer's external ID — supports migration-parity lookup by a legacy value (e.g. a |
| state | string Enum: "pending" "accepted" "review" "rejected" "incomplete" Filter by the primary identity's decision. |
| created_after | string <date-time> ISO-8601 datetime lower bound (inclusive) on |
| created_before | string <date-time> ISO-8601 datetime upper bound (inclusive) on |
| cursor | string Opaque pagination cursor from a prior response's |
| limit | string^[1-9][0-9]{0,2}$ Page size as a numeric string, 1–200 (default 50, clamped server-side). Pattern |
{- "items": [
- {
- "customer_id": "string",
- "state": "pending",
- "decision": "pending",
- "status": "active",
- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24",
- "date_of_birth_raw": "string",
- "personal_number": "string",
- "primary_identity_id": "string",
- "document_number": "string",
- "issuing_country": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
], - "next_cursor": "string"
}Supply-on-create — the migration primitive for re-creating an existing customer (e.g. under a legacy {national_id}_{uuid} scheme) with its historical external_id preserved. external_id must match ^[a-zA-Z\d._-]{1,64}$ and be unique per tenant.
| external_id required | string [ 1 .. 64 ] characters ^[a-zA-Z\d._-]{1,64}$ |
| name | string or null |
| given_name | string or null |
| surname | string or null |
| place_of_birth | string or null |
| date_of_birth | string or null <date> ISO-8601 date (YYYY-MM-DD). |
{- "external_id": "string",
- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24"
}{- "customer_id": "string",
- "state": "pending",
- "decision": "pending",
- "status": "active",
- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24",
- "date_of_birth_raw": "string",
- "personal_number": "string",
- "primary_identity_id": "string",
- "document_number": "string",
- "issuing_country": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}| customerId required | string The Customer's external ID (integrator-supplied or generated). |
{- "customer_id": "string",
- "state": "pending",
- "decision": "pending",
- "status": "active",
- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24",
- "date_of_birth_raw": "string",
- "personal_number": "string",
- "primary_identity_id": "string",
- "document_number": "string",
- "issuing_country": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Updates any subset of the writable identity fields. Unknown keys are rejected. Each of these is a workflow-managed field, so if a verification run is active for this Customer the write returns 409 WORKFLOW_RUN_ACTIVE (fail-open on a guard outage). An anonymized Customer is terminal: the write is rejected with 409 CUSTOMER_ANONYMIZED.
| customerId required | string The Customer's external ID (integrator-supplied or generated). |
| name | string or null |
| given_name | string or null |
| surname | string or null |
| place_of_birth | string or null |
| date_of_birth | string or null <date> ISO-8601 date (YYYY-MM-DD). |
{- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24"
}{- "customer_id": "string",
- "state": "pending",
- "decision": "pending",
- "status": "active",
- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24",
- "date_of_birth_raw": "string",
- "personal_number": "string",
- "primary_identity_id": "string",
- "document_number": "string",
- "issuing_country": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Right-to-erasure: wipes the Customer's PII and cascades to every child Digital Identity (flips each to the terminal anonymized decision and clears raw biometric blob refs), then best-effort removes the person from the 1:N face-dedup watchlists. Never a row delete, so assignment history survives. Subject to the fail-closed active-run guard, like every other anonymize.
Not idempotent by path id. Erasure replaces the Customer's customer_id with a freshly generated opaque UUID, so repeating the call with the original id returns 404 not_found — that does not mean the erasure failed. The new id is in the customer_id of the first response; retry with that value if you need a confirmed repeat.
| customerId required | string The Customer's external ID (integrator-supplied or generated). |
{- "customer_id": "string",
- "status": "anonymized"
}Which hands the Customer has a usable palm enrolment for, derived from the primary Digital Identity's palm rows. A hand is reported only while its stored biometric reference still exists, so erased palms never appear and an anonymized Customer reports an empty list.
| customerId required | string The Customer's external ID (integrator-supplied or generated). |
{- "hands": [
- "left"
]
}| customerId required | string The Customer's external ID (integrator-supplied or generated). |
{- "items": [
- {
- "identity_id": "string",
- "customer_id": "string",
- "state": "pending",
- "status": "pending",
- "workflow_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}
]
}| customerId required | string The Customer's external ID (integrator-supplied or generated). |
| identityId required | string The Digital Identity's external ID. |
{- "identity_id": "string",
- "customer_id": "string",
- "state": "pending",
- "status": "pending",
- "workflow_name": "string",
- "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Non-destructive erasure of one Digital Identity: flips it to the terminal anonymized decision, wipes its PII/biometric blob refs, and removes it from the watchlists. If it is the Customer's only identity the erasure cascades to the parent Customer (cascaded_to_customer: true). Refused (409 ANONYMIZE_PRIMARY_DI_BLOCKED, carrying customer_id in details) when it is the primary identity of a Customer that has other identities — anonymize the Customer instead. Idempotent on an already-anonymized identity, except after a cascade: cascading replaces the parent Customer's customer_id, so repeating the call on the original {customerId} returns 404. Use POST /v1/identities/{identityId}/anonymize for a retry-safe repeat. Subject to the fail-closed active-run guard.
| customerId required | string The Customer's external ID (integrator-supplied or generated). |
| identityId required | string The Digital Identity's external ID. |
{- "cascaded_to_customer": true,
- "identity_id": "string",
- "status": "anonymized"
}Manually overrides the identity's decision (marks it as a manual decision) and re-syncs the parent Customer's denormalized decision. Guarded unconditionally by the fail-closed active-run guard: forcing a decision while a workflow run is live is exactly the race the guard prevents. An anonymized identity is terminal — the transition is rejected with 409 IDENTITY_ANONYMIZED. Returns an empty object on success.
| customerId required | string The Customer's external ID (integrator-supplied or generated). |
| identityId required | string The Digital Identity's external ID. |
| decision required | string Enum: "ACCEPT" "REJECT" "REVIEW" "INCOMPLETE" Target terminal decision to force (uppercase verb). |
| trust_evaluation_id | string non-empty Optional trust-evaluation reference for the forced decision. |
{- "decision": "ACCEPT",
- "trust_evaluation_id": "string"
}{ }Returns the extracted onboarding data (name, date of birth, document number, place of birth, …) and the S3 keys of the captured images for a single Digital Identity, addressed by its own id — no customer id needed, so it also serves in-progress identities that were never promoted to a Customer (customer_id is then null). Fetch each image via GET /v1/identities/{identityId}/images/{slot} (slot = the property name in images). On an anonymized identity the erased fields and image keys are null.
| identityId required | string The Digital Identity's external ID. |
{- "identity_id": "string",
- "customer_id": "string",
- "state": "pending",
- "decision": "pending",
- "status": "pending",
- "workflow_name": "string",
- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24",
- "date_of_birth_raw": "string",
- "date_of_expiry": "2019-08-24",
- "personal_number": "string",
- "document_number": "string",
- "issuing_country": "string",
- "chip_data": { },
- "images": {
- "document_back": "string",
- "document_front": "string",
- "document_chip_portrait": "string",
- "document_portrait": "string",
- "selfie": "string",
- "selfie_crop": "string",
- "selfie_raw": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Streams one captured image of the identity. The identity lookup in the caller's own tenant database is the tenancy proof, so every slot is servable by id — including in-progress identities the deprecated key-addressed GET /v1/customers/images/{key} cannot reach without a known key. All stored keys now share the {orgId}/verifications/… org-first layout, worker-written references included. 404 when the identity does not exist, the slot holds no image, the image was erased by anonymization, or the stored object is no longer present in storage. Sends ETag and honours If-None-Match (304); responses are privately cacheable for 24 hours.
| identityId required | string The Digital Identity's external ID. |
| slot required | string Enum: "document_back" "document_front" "document_portrait" "document_chip_portrait" "selfie" "selfie_crop" "selfie_raw" Which captured image to stream — the property names of the identity-data endpoint's |
| If-None-Match | string Entity tag from a previous response for this resource; a match short-circuits to 304 Not Modified. |
{- "success": false,
- "error": {
- "message": "string",
- "code": "string",
- "details": null
}
}Deprecated 1.2.3-compat alias of GET /v1/identities/{identityId} — identical response body; new integrations should use the flat route.
| identityId required | string The Digital Identity's external ID. |
{- "identity_id": "string",
- "customer_id": "string",
- "state": "pending",
- "decision": "pending",
- "status": "pending",
- "workflow_name": "string",
- "name": "string",
- "given_name": "string",
- "surname": "string",
- "place_of_birth": "string",
- "date_of_birth": "2019-08-24",
- "date_of_birth_raw": "string",
- "date_of_expiry": "2019-08-24",
- "personal_number": "string",
- "document_number": "string",
- "issuing_country": "string",
- "chip_data": { },
- "images": {
- "document_back": "string",
- "document_front": "string",
- "document_chip_portrait": "string",
- "document_portrait": "string",
- "selfie": "string",
- "selfie_crop": "string",
- "selfie_raw": "string"
}, - "created_at": "2019-08-24T14:15:22Z",
- "updated_at": "2019-08-24T14:15:22Z"
}Deprecated 1.2.3-compat alias — use the slot-addressed GET /v1/identities/{identityId}/images/{slot}, which also serves the workflow-storage keys this route rejects. Streams one captured image by the S3 key taken from the images object of the identity-data endpoint. Only keys under the caller's own {orgId}/verifications/… prefix are served — foreign, malformed, or internal workflow-storage keys yield 404. Sends ETag and honours If-None-Match (304); responses are privately cacheable for 24 hours.
| key required | string The S3 object key from |
| If-None-Match | string Entity tag from a previous response for this resource; a match short-circuits to 304 Not Modified. |
{- "success": false,
- "error": {
- "message": "string",
- "code": "string",
- "details": null
}
}Flat variant of POST /v1/customers/{customerId}/identities/{identityId}/anonymize that resolves the Customer FROM the identity, so it can reach customer-less identities (a standalone reject, an unresolved-duplicate cell) that the nested route structurally cannot address. Same scope resolution; cascades to the parent Customer when the identity is its only one. The active-run guard keys on the Customer, so it applies only to customer-bound identities — a customer-less identity is instead refused while still pending (409 IDENTITY_WORKFLOW_IN_PROGRESS) and never returns 503.
| identityId required | string The Digital Identity's external ID. |
{- "cascaded_to_customer": true,
- "identity_id": "string",
- "status": "anonymized"
}Link integrator-side artifacts (a SIM, a device, an account, a policy) to a Customer and move them between Customers.
Every Assignment held by this Customer, newest first. Unpaginated — the full result set is returned. An unknown customerId is a 404, not an empty list.
| customerId required | string The Customer's external ID (integrator-supplied or generated). |
| status | string Enum: "active" "suspended" "unassigned" "all" Restrict the result to one status. Omit it, or pass |
{- "items": [
- {
- "assignment_id": "string",
- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "status": "active",
- "assigned_at": "2019-08-24T14:15:22Z",
- "unassigned_at": "2019-08-24T14:15:22Z",
- "remote_reference": "string",
- "custom_fields": { }
}
]
}Every Assignment recorded for one external_identifier, across all Customers, newest first. Unpaginated — the full result set is returned.
| external_identifier required | string non-empty The integrator-side identifier to list Assignments for. |
| status | string Enum: "active" "suspended" "unassigned" "all" Restrict the result to one status. Omit it, or pass |
{- "items": [
- {
- "assignment_id": "string",
- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "status": "active",
- "assigned_at": "2019-08-24T14:15:22Z",
- "unassigned_at": "2019-08-24T14:15:22Z",
- "remote_reference": "string",
- "custom_fields": { }
}
]
}Links an integrator-side artifact to a Customer, optionally pinning it to one of that Customer's Digital Identities. The Assignment is always created active; assignment_id and assigned_at are server-owned.
A Customer may hold only one open (active or suspended) Assignment per external_identifier. Creating a second one returns 409 conflict — close the existing one with POST /v1/assignments/transfer first.
| Idempotency-Key required | string Caller-generated key that makes this write safe to retry; replaying it against the same path returns the original status and body without repeating the work. Required — a request without it is rejected with 400 |
| external_identifier required | string non-empty The integrator-side identifier to record. |
| customer_id required | string non-empty External ID of the Customer to assign to. Must already exist. |
| digital_identity_id | string or null non-empty Optional Digital Identity to pin the Assignment to. It must belong to the same Customer. |
| remote_reference | string or null |
object (AssignmentCustomFields) Flat map of extension data; values must be string, number, boolean or null, and nested objects or arrays are rejected. A write replaces the whole object rather than merging into it, so send |
{- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "remote_reference": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}
}{- "assignment_id": "string",
- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "status": "active",
- "assigned_at": "2019-08-24T14:15:22Z",
- "unassigned_at": "2019-08-24T14:15:22Z",
- "remote_reference": "string",
- "custom_fields": { }
}The Assignment field list with per-field flags, mirroring GET /v1/customers/schema. Only remote_reference and custom_fields are writable by integrators.
{- "fields": [
- {
- "name": "string",
- "type": "string",
- "label": "string",
- "source": "string",
- "writable_by_integrator": true
}
]
}Closes the open Assignment that from_customer_id holds for this external_identifier — status becomes unassigned and unassigned_at is stamped — and, when to_customer_id is supplied, opens a fresh active Assignment on that Customer with a new assignment_id. Both halves commit together. This is the only way an Assignment reaches the unassigned state.
Omit to_customer_id, or send it as null, to unassign without opening anything. In that case digital_identity_id, remote_reference and custom_fields must be absent. Sending digital_identity_id or remote_reference — even as null — returns 400 invalid_body; custom_fields: null is rejected earlier still, by schema validation, with 400 VALIDATION_ERROR.
The opened Assignment does not inherit remote_reference or custom_fields from the closed one; supply them here if the destination needs them.
| Idempotency-Key required | string Caller-generated key that makes this write safe to retry; replaying it against the same path returns the original status and body without repeating the work. Required — a request without it is rejected with 400 |
| external_identifier required | string non-empty |
| from_customer_id required | string non-empty External ID of the Customer currently holding the open Assignment. |
| to_customer_id | string or null non-empty External ID of the destination Customer. Omit it, or send |
| digital_identity_id | string or null non-empty Digital Identity to pin the newly opened Assignment to. It must belong to the destination Customer. |
| remote_reference | string or null Applied to the newly opened Assignment only. |
object (AssignmentCustomFields) Flat map of extension data; values must be string, number, boolean or null, and nested objects or arrays are rejected. A write replaces the whole object rather than merging into it, so send |
{- "external_identifier": "string",
- "from_customer_id": "string",
- "to_customer_id": "string",
- "digital_identity_id": "string",
- "remote_reference": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}
}{- "closed": {
- "assignment_id": "string",
- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "status": "active",
- "assigned_at": "2019-08-24T14:15:22Z",
- "unassigned_at": "2019-08-24T14:15:22Z",
- "remote_reference": "string",
- "custom_fields": { }
}, - "opened": {
- "assignment_id": "string",
- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "status": "active",
- "assigned_at": "2019-08-24T14:15:22Z",
- "unassigned_at": "2019-08-24T14:15:22Z",
- "remote_reference": "string",
- "custom_fields": { }
}
}| assignmentId required | string The Assignment's server-generated ID. |
{- "assignment_id": "string",
- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "status": "active",
- "assigned_at": "2019-08-24T14:15:22Z",
- "unassigned_at": "2019-08-24T14:15:22Z",
- "remote_reference": "string",
- "custom_fields": { }
}Only remote_reference and custom_fields are writable; every other field is fixed for the life of the Assignment. Closed (unassigned) Assignments stay patchable, so a late reference correction is possible. Only the keys present in the body are written.
| assignmentId required | string The Assignment's server-generated ID. |
| remote_reference | string or null
|
object (AssignmentCustomFields) Flat map of extension data; values must be string, number, boolean or null, and nested objects or arrays are rejected. A write replaces the whole object rather than merging into it, so send |
{- "remote_reference": "string",
- "custom_fields": {
- "property1": "string",
- "property2": "string"
}
}{- "assignment_id": "string",
- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "status": "active",
- "assigned_at": "2019-08-24T14:15:22Z",
- "unassigned_at": "2019-08-24T14:15:22Z",
- "remote_reference": "string",
- "custom_fields": { }
}Removes the Assignment row outright. This is a hard delete, not a state change — the record is gone and does not appear in any later listing. To close an Assignment while keeping its history, use POST /v1/assignments/transfer without a to_customer_id.
| assignmentId required | string The Assignment's server-generated ID. |
{- "success": false,
- "error": {
- "message": "string",
- "code": "string",
- "details": null
}
}Moves an active Assignment to suspended. Not idempotent — calling it on an Assignment that is not active, including one already suspended, returns 409 conflict.
| assignmentId required | string The Assignment's server-generated ID. |
{- "assignment_id": "string",
- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "status": "active",
- "assigned_at": "2019-08-24T14:15:22Z",
- "unassigned_at": "2019-08-24T14:15:22Z",
- "remote_reference": "string",
- "custom_fields": { }
}Moves a suspended Assignment back to active. Not idempotent — calling it on an Assignment that is not suspended, including one already active, returns 409 conflict.
| assignmentId required | string The Assignment's server-generated ID. |
{- "assignment_id": "string",
- "external_identifier": "string",
- "customer_id": "string",
- "digital_identity_id": "string",
- "status": "active",
- "assigned_at": "2019-08-24T14:15:22Z",
- "unassigned_at": "2019-08-24T14:15:22Z",
- "remote_reference": "string",
- "custom_fields": { }
}Unauthenticated liveness check, served outside the versioned lane — no bearer token, no tenant context. It answers from the process alone and does not reach the database, so a 200 means the service is running, not that it can serve tenant requests.
{- "ok": true
}