Get persona (v2)
Same persona payload as v1 plus linked_to, the list of records this persona is linked to as {record_type, record_id} pairs. Unlike the v1 equivalents, the refusals here come from the v2 service and use the shared codes: common.forbidden for 403 and common.record_not_found for 404, rather than v1's common.rbac_no_rec_access and bare NotFound404.
Authorization
bearerAuth In: header
Path Parameters
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/v2/personas/497f6eca-6276-4993-bfeb-53cbbbba6f08"{
"first_name": "string",
"last_name": "string",
"date_of_birth": "2019-08-24",
"date_of_death": "2019-08-24",
"nationality": "string",
"hash_id": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"active": true,
"metadata": {},
"created_at": "2019-08-24T14:15:22Z",
"created_by": "ee824cad-d7a6-4f48-87dc-e8461a9201c4",
"modified_at": "2019-08-24T14:15:22Z",
"modified_by": "e8d4374d-93a1-4e98-a6c6-fdcf00c5059f",
"linked_to": [
{
"record_type": "string",
"record_id": "8bf519b6-a3e0-49d2-8e42-039542d9a489"
}
]
}{
"status": 400,
"message": "Invalid persona ID",
"code": "personas_m.invalid_persona_id",
"class": "validation"
}{
"status": 401,
"message": "Unauthorized",
"code": "common.unauthorized",
"class": "business"
}{
"status": 403,
"message": "Access denied",
"code": "common.forbidden",
"class": "business"
}{
"status": 404,
"message": "Record not found",
"code": "common.record_not_found",
"class": "business"
}{
"status": 429,
"message": "Rate limit exceeded",
"code": "rate_limits_m.exceeded",
"class": "temporary",
"retryable": true
}{
"status": 500,
"message": "Database error",
"code": "common.database_error",
"class": "business"
}{
"overall_status": "unhealthy",
"message": "Service is shutting down",
"timestamp": "2026-08-27T15:04:05Z"
}The shared list envelope — data, total, total_unfiltered, keys — with real filtering, sorting and pagination, which /v1/personas has none of. Filterable fields are id, created_at, created_by, modified_at, modified_by, active, metadata, first_name, last_name, date_of_birth, date_of_death, nationality and hash_id. Any other search.<field> is dropped by the shared parser rather than rejected, so the response comes back UNFILTERED instead of empty. search.linked_to.record_id and search.linked_to.record_type are the exception: they are not columns and would be dropped like any unknown key, so the handler lifts them out of the raw query string and puts them back into the search map by hand before the service runs. The .eq suffix form is accepted for both.
Same persona payload as v1 plus linked_to, the list of records this persona is linked to as {record_type, record_id} pairs. Unlike the v1 equivalents, the refusals here come from the v2 service and use the shared codes: common.forbidden for 403 and common.record_not_found for 404, rather than v1's common.rbac_no_rec_access and bare NotFound404.