> ## Documentation Index
> Fetch the complete documentation index at: https://docs.braintest.ir/llms.txt
> Use this file to discover all available pages before exploring further.

# Participant Profiles and Authentication

> How Braintest participant profiles work: required fields, external IDs, and the two authentication paths (SMS verification or instant).

A profile represents a single test participant in the Braintest platform. It stores demographic and contact data that link a real person to their test records and roadmap results. Braintest supports two authentication paths, selected by the organizer setting `tests_auth_required` and echoed on every record and roadmap payload.

## Required fields

Every profile must include the following fields when calling an authentication endpoint:

| Field     | Type    | Constraints                                                                                                                                                                 |
| --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `name`    | string  | Persian letters only, maximum 50 characters.                                                                                                                                |
| `mobile`  | string  | Iranian format: 11 digits starting with `09` (for example, `09123456789`). Roadmaps take a single top-level `mobile`; standalone records take `mobile` on the profile body. |
| `birth`   | string  | ISO 8601 date (for example, `1990-05-15`).                                                                                                                                  |
| `is_male` | boolean | `true` for male, `false` for female.                                                                                                                                        |

## Optional fields

| Field         | Type    | Description                                                                                                                                         |
| ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `external_id` | integer | Your own identifier for the participant. Must be unique per organizer. Useful for idempotent lookups and cross-referencing with your user database. |

## Authentication paths

The organizer setting `tests_auth_required` (visible on every record and roadmap payload) selects the flow. Your integration should always read the flag from the resource and branch on it.

### Path A: SMS verification (`tests_auth_required: true`, default)

1. `POST /record/{token}/auth/` or `POST /roadmap/{token}/auth/` with the profile data.
2. The API validates the fields, sends an SMS code to the participant's mobile, and returns a `draft_token`.
3. Prompt the participant for the code and call `PUT /.../auth/verify/` with the `draft_token` and `vcode`.
4. On success, the API returns the final profile (or role profiles) and links them to the record or every record in the roadmap.

Draft tokens expire after **5 minutes**. Requesting new codes is throttled per mobile, and mobile numbers that hit the per-account duplicate limit receive a 400 error.

### Path B: Instant (`tests_auth_required: false`)

1. `POST /record/{token}/auth/` or `POST /roadmap/{token}/auth/` with the profile data.
2. If validation passes, the profile is created (or matched by `external_id`) and linked immediately.
3. There is no SMS code, email link, or secondary confirmation. Move directly to fetching questions or completing tests.

<Warning>
  Do not call `PUT /.../auth/verify/` when `tests_auth_required` is `false`. It returns a 400 error with the message `SMS verification is not required for this organizer account.`
</Warning>

## Validation checks (both paths)

Regardless of the path, the API always validates:

1. Format: name length, mobile pattern, birth date format, and boolean type.
2. Prerequisite checks: age and gender restrictions defined by the specific test.
3. Uniqueness: `external_id` must be unique within your organizer account.

If any check fails, the response returns `successful: false` with a descriptive message in the `messages` array.

## Age and gender prerequisites

Some psychological tests restrict participation by age or gender. For example, a test may specify:

* `min_age`: 18
* `max_age`: 65
* `gender_permission`: `"male"` or `"female"` (or `null` for no restriction)

If the participant does not meet these prerequisites, authentication fails with a descriptive message.

## Auto-generated fields

After successful authentication, Braintest assigns the following fields automatically:

| Field         | Description                                                                            |
| ------------- | -------------------------------------------------------------------------------------- |
| `token`       | Profile UUID generated by Braintest.                                                   |
| `case_number` | Unique organizer-scoped identifier for this participant across all tests and roadmaps. |
| `age`         | Computed age in years from the provided birth date.                                    |

## Example payload (standalone record)

```json theme={"dark"}
{
  "name": "علی احمدی",
  "mobile": "09123456789",
  "birth": "1990-05-15",
  "is_male": true,
  "external_id": 98765
}
```

## Example payload (roadmap)

For roadmaps, provide a shared `mobile` and an array of role/profile pairs:

```json theme={"dark"}
{
  "mobile": "09123456789",
  "roles": [
    {
      "id": 1,
      "profile": {
        "name": "علی احمدی",
        "birth": "1990-05-15",
        "is_male": true,
        "external_id": 98765
      }
    }
  ]
}
```

<Tip>
  Use `external_id` to reliably match Braintest participants with users in your own system. It prevents duplicate profiles when the same person takes multiple tests.
</Tip>
