Skip to main content
A person (per_...) is a natural person (human) or legal person (company, trust, other entity). Persons are standalone until an onboarding application referencing them is approved. Every person is built from claims — typed data points capturing identity, residence, ownership, PEP status, and so on. Every POST /persons must include at least the mandatory claim set for its person_type:
person_typeMandatory claims
naturalidentity + contact_details
legalregistration + contact_details
Omitting any of these returns 400 invalid_request with detail <person_type> persons require claim types [...]; missing: [...]. You can include additional claims in the same request (and usually will, to round out the person’s profile). person_type determines which claim types are acceptable.
person_typeRepresentsExample claim types
naturalA humanidentity, contact_details, nationalities, residence, tax_residencies, pep_status, employment, financial_profile
legalA company, trust, partnership, or other legal entityregistration, contact_details, lei, registered_address, business_nature, relationships
operating_address is also a legal-person claim. You only add it when the legal owner’s registered_address has operating_address_is_same set to false — see conditional requirements. Legal persons declare counterparties (directors, shareholders, UBOs, trustees, signatories) via a relationships claim. Related persons must already exist. Claim types are enforced against person_type: mismatches on POST /persons or POST /persons/{person_id}/claims return 400 invalid_request. See the claim type reference.

Creating a person

POST /persons with person_type and a non-empty claims array. Creation is atomic — if any claim fails validation, nothing is persisted.
import requests

response = requests.post(
    "https://api.engine.usesophic.com/persons",
    headers={
        "Authorization": "Bearer YOUR_ACCESS_TOKEN",
        "Content-Type": "application/json",
    },
    json={
        "person_type": "natural",
        "claims": [
            {
                "claim_type": "identity",
                "first_name": "Ada",
                "last_name": "Lovelace",
                "date_of_birth": "1985-12-10",
            },
            {
                "claim_type": "contact_details",
                "phone_number": "+447700900123",
                "email": "ada@example.com",
            },
            {
                "claim_type": "residence",
                "line1": "1 Example Street",
                "postal_code": "SW1A 1AA",
                "city": "London",
                "country_code": "GB",
            },
        ],
    },
)
person = response.json()

Response

A successful request returns 201 Created:
{
  "id": "per_m4k7r9s2",
  "created_at": "2026-04-18T09:30:00Z",
  "modified_at": "2026-04-18T09:30:00Z",
  "person_type": "natural",
  "full_name": "Ada Lovelace",
  "claims": [
    {
      "id": "clm_abc123",
      "created_at": "2026-04-18T09:30:00Z",
      "status": "pending",
      "claim_type": "identity",
      "first_name": "Ada",
      "last_name": "Lovelace",
      "date_of_birth": "1985-12-10"
    },
    {
      "id": "clm_def456",
      "created_at": "2026-04-18T09:30:00Z",
      "status": "pending",
      "claim_type": "contact_details",
      "phone_number": "+447700900123",
      "email": "ada@example.com"
    },
    {
      "id": "clm_ghi789",
      "created_at": "2026-04-18T09:30:00Z",
      "status": "pending",
      "claim_type": "residence",
      "line1": "1 Example Street",
      "line2": null,
      "line3": null,
      "district_county": null,
      "postal_code": "SW1A 1AA",
      "city": "London",
      "country_code": "GB"
    }
  ]
}
FieldDescription
idThe person’s unique ID, prefix per_.
person_typenatural or legal.
full_nameNatural: "{first_name} {last_name}" from the identity claim. Legal: entity_name from registration, or empty.
claimsThe claims you provided. Each element carries id, created_at, status: pending, claim_type, and the fields defined for that claim_type. To get the full claim (with person, lifecycle, verified_at, superseded_at, archived_at) for a specific claim later, call GET /persons/{person_id}/claims/{claim_id}. See claim lifecycle.
Persons don’t have their own status — lifecycle lives on claims. See lifecycle.
POST /persons doesn’t de-duplicate retries. Record the returned id and reuse it on retries.

Retrieving a person

Use GET /persons/{id} to fetch the person record. Claims aren’t included — list them separately.
curl https://api.engine.usesophic.com/persons/per_m4k7r9s2 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
Use GET /persons/{person_id}/claims to list the person’s claims, filtered by claim_type or status. By default you get every row for the person — current and historical — newest-first. Pass include_history=false to collapse to just the current rows (active + in_flight) per type. See listing and retrieving claims.
curl "https://api.engine.usesophic.com/persons/per_m4k7r9s2/claims?status=verified" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Authorities

When an application referencing a person is approved, that person becomes an authority on the resulting customer and accounts.
authority_typeMeaning
ownerThe primary owner of the customer.
joint_ownerA joint owner on a shared customer.
signatoryCan sign on behalf of the customer but doesn’t own it.
power_of_attorneyActs under a power of attorney arrangement.
tradingAuthorised to place trades on the customer’s accounts.
List authorities per person with GET /persons/{id}/authorities, or per customer with GET /customers/{id}/authorities. Create one person for the legal entity and one for every director, shareholder, UBO, trustee, settlor, or authorised signatory. Then add a relationships claim on the legal person.
{
  "person_type": "legal",
  "claims": [
    {
      "claim_type": "registration",
      "legal_name": "Ada & Co Ltd",
      "registration_number": "12345678",
      "date_of_incorporation": "2020-06-01",
      "country_of_incorporation": "GB",
      "entity_type": "private_limited_company"
    },
    {
      "claim_type": "relationships",
      "relationships": [
        {
          "related_person": "per_ada",
          "relationship_type": "director",
          "appointment_date": "2020-06-01"
        },
        {
          "related_person": "per_grace",
          "relationship_type": "shareholder",
          "ownership_percentage": "50.00"
        }
      ]
    }
  ]
}
Related persons must already exist — an unknown related_person ID fails the request with 400 and nothing is persisted. See claim types for the full relationships schema.