> For the complete documentation index, see [llms.txt](https://devcenter.unico.io/you/Ol1H6eGO4sQvPYB1Nmyl/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://devcenter.unico.io/you/Ol1H6eGO4sQvPYB1Nmyl/authentication/obtaining-credentials-1.md).

# Obtaining credentials

This guide walks you through authenticating with the You Console and generating the `x-unico-accesskey` you will use in all Human Tokenization API requests.

The flow has two phases:

1. **Authenticate** — complete a login and obtain an access token. Two authentication methods are available:
   * **Biometric login** — face capture via the Unico SDK (available for both signup and signin)
   * **Email OTP login** — one-time code sent to the registered email address (signin only)
2. **Set up your organization** — create your company profile and generate an access key (first-time signup only)

***

### Two ways to set up your credentials

Everything in this guide can also be done through the **Unico Dashboard** at [dashboard.unico.app](https://dashboard.unico.app) — no API calls required.

| Option        | When to use                                                          |
| ------------- | -------------------------------------------------------------------- |
| **Dashboard** | First-time setup, manual key rotation, occasional management         |
| **API**       | Automated provisioning, CI/CD pipelines, programmatic key management |

#### Using the dashboard

1. Go to [dashboard.unico.app](https://dashboard.unico.app)
2. **Sign up or sign in** — use biometric login (face capture) or email OTP
3. **Create your organization** — fill in your company name, country, and allowed domains
4. **Generate an access key** — go to **Access Keys** and click **Create key**; copy it immediately, it is shown only once
5. **Manage branches** — create and configure branches under **Branches**; each branch generates its own access key

The access key you get from the dashboard is the same `x-unico-accesskey` used in all API requests — the two approaches are fully interchangeable.

***

### Base URLs

| Environment   | Base URL                        |
| ------------- | ------------------------------- |
| UAT (testing) | `https://api.you.uat.unico.app` |
| Production    | `https://api.you.unico.app`     |

***

### Authentication methods

Two methods are available to authenticate and obtain an `authToken`:

| Method        | Endpoint                                       | When to use                                     |
| ------------- | ---------------------------------------------- | ----------------------------------------------- |
| **Biometric** | `POST /api/console/v1/auth/biometric/sessions` | Signup (new account) or Signin (returning user) |
| **Email OTP** | `POST /api/console/v1/auth/email/sessions`     | Signin only — account must already exist        |

***

### Biometric login intent

Every call to `StartBiometricLogin` must declare an `intent`:

| `intent`              | When to use                                      | `email` field | `name` field |
| --------------------- | ------------------------------------------------ | ------------- | ------------ |
| `LOGIN_INTENT_SIGNUP` | First-time registration — creating a new account | **Required**  | **Required** |
| `LOGIN_INTENT_SIGNIN` | Returning user — account already exists          | Not used      | Not used     |
| *(omitted)*           | Treated as `LOGIN_INTENT_SIGNIN`                 | Not used      | Not used     |

The intent controls validation in `GetBiometricLogin`:

* **SIGNUP** — rejects the login if that biometric identity is already registered (prevents duplicate accounts).
* **SIGNIN** — rejects the login if that biometric identity is *not* registered (account must exist to log in).

***

### Phase 1 — Authenticate

#### Step 1: Start a biometric login session

**SIGNUP (first-time registration)**

```bash
curl -X POST https://api.you.uat.unico.app/api/console/v1/auth/biometric/sessions \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "LOGIN_INTENT_SIGNUP",
    "email": "admin@acme.com",
    "name": "Jane Doe"
  }'
```

> **Email uniqueness** — if an account is already registered with that email, the request returns `400 Bad Request`. The `link` and `token` fields are empty in the response — the biometric capture link is sent to the provided email address.

Response:

```json
{
  "session": {
    "sessionId": "b3f1a2c4-0000-0000-0000-abcdef012345",
    "link": "",
    "token": ""
  }
}
```

**SIGNIN (returning user)**

```bash
curl -X POST https://api.you.uat.unico.app/api/console/v1/auth/biometric/sessions \
  -H "Content-Type: application/json" \
  -d '{
    "intent": "LOGIN_INTENT_SIGNIN"
  }'
```

Response:

```json
{
  "session": {
    "sessionId": "b3f1a2c4-0000-0000-0000-abcdef012345",
    "link": "https://you.unico.io/...",
    "token": "eyJhbGciOiJSUzI1NiJ9..."
  }
}
```

Save the `sessionId`.

* **SIGNUP**: the biometric capture link is sent to the email provided in Step 1. Ask the user to check their inbox and complete the capture.
* **SIGNIN**: open `link` in your browser and complete the biometric capture.

***

#### Step 2: Poll until the session is resolved

```bash
curl https://api.you.uat.unico.app/api/console/v1/auth/biometric/sessions/b3f1a2c4-0000-0000-0000-abcdef012345
```

Poll every 2–3 seconds until `status` reaches a terminal state.

| `status`     | `outcome`      | Meaning                                               |
| ------------ | -------------- | ----------------------------------------------------- |
| `pending`    | `pending`      | User has not completed the capture yet — keep polling |
| `processing` | `pending`      | Capture done, results being computed — keep polling   |
| `completed`  | `matched`      | Login successful — `authToken` is present             |
| `completed`  | `no_match`     | Biometric did not match any record                    |
| `completed`  | `inconclusive` | Capture succeeded but could not be resolved           |
| `expired`    | —              | Link expired — restart from Step 1                    |
| `canceled`   | —              | Session was canceled — restart from Step 1            |

**Additional intent-specific errors from `GetBiometricLogin`:**

| HTTP  | Condition                                                                  |
| ----- | -------------------------------------------------------------------------- |
| `400` | **SIGNUP** — biometric identity is already registered (duplicate account)  |
| `400` | **SIGNIN** — biometric identity is not registered (account does not exist) |

Successful response:

```json
{
  "result": {
    "sessionId": "b3f1a2c4-0000-0000-0000-abcdef012345",
    "status": "completed",
    "outcome": "matched",
    "authToken": "eyJhbGciOiJSUzI1NiJ9..."
  }
}
```

Save `authToken` — use it as the `x-console-authorization` header in all subsequent Console API requests.

***

### Phase 1 (alternative) — Email OTP signin

Use this flow instead of biometric if the user already has an account and prefers to authenticate via a one-time code sent to their registered email. **Signup is not supported via email OTP** — use the biometric flow for first-time registration.

#### Step 1: Send the OTP

```bash
curl -X POST https://api.you.uat.unico.app/api/console/v1/auth/email/sessions \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@acme.com"
  }'
```

> The email must belong to an existing account. If no account is found, `GetEmailLogin` will return `404 Not Found`.

Response:

```json
{
  "session": {
    "sessionId": "b3f1a2c4-0000-0000-0000-abcdef012345"
  }
}
```

Save the `sessionId`. A 6-digit code is sent to the provided email address.

***

#### Step 2: Validate the OTP

```bash
curl https://api.you.uat.unico.app/api/console/v1/auth/email/sessions/{sessionId}/{code}
```

| HTTP  | Condition                                          |
| ----- | -------------------------------------------------- |
| `200` | Code is valid — `authToken` is present             |
| `400` | Code is wrong (`invalid otp code`)                 |
| `400` | OTP already used, max attempts reached, or expired |
| `404` | Email not registered                               |

Successful response:

```json
{
  "result": {
    "sessionId": "b3f1a2c4-0000-0000-0000-abcdef012345",
    "status": "completed",
    "outcome": "matched",
    "authToken": "eyJhbGciOiJSUzI1NiJ9..."
  }
}
```

Save `authToken` — use it as the `x-console-authorization` header in all subsequent Console API requests.

***

### Phase 2 — Set up your organization

#### Step 3: Create your organization

> This call can only be made **once**. It provisions your tenant and generates your `branchId`.

Any country is accepted. Use the [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) three-letter code (e.g. `BRA`, `USA`, `MEX`, `DEU`, `IND`). `taxId` is optional for all countries.

```bash
curl -X POST https://api.you.uat.unico.app/api/console/v1/organization \
  -H "x-console-authorization: <authToken>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Corp",
    "responsibleEmail": "admin@acme.com",
    "websiteUrl": "https://acme.com",
    "countryCode": "BRA",
    "logo": "https://acme.com/logo.png",
    "allowedDomains": ["https://app.acme.com"]
  }'
```

Response:

```json
{
  "organization": {
    "id": "e5d3f1a2-0000-0000-0000-abcdef012345",
    "name": "Acme Corp",
    "responsibleEmail": "admin@acme.com",
    "websiteUrl": "https://acme.com",
    "countryCode": "BRA",
    "tenantId": "tenant-acme-prod",
    "branchId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "taxId": "12345678000195"
  }
}
```

Save `branchId` — it identifies your default branch and is used when managing branches and access keys.

***

#### Step 4: Create an access key

```bash
curl -X POST https://api.you.uat.unico.app/api/console/v1/access-keys \
  -H "x-console-authorization: <authToken>" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "production-key"
  }'
```

Response:

```json
{
  "accessKey": "uk_live_a1b2c3d4e5f6..."
}
```

> **The `accessKey` is returned only once and cannot be retrieved again.** Store it in your secrets manager immediately as `YOU_ACCESS_KEY`.

This value is the `x-unico-accesskey` header used in all Human Tokenization API requests.

***

### What you now have

| Value       | Where to use it                                                       |
| ----------- | --------------------------------------------------------------------- |
| `branchId`  | Identifying your default branch; creating branch-specific access keys |
| `accessKey` | `x-unico-accesskey` header in all Human Tokenization requests         |

***

### Managing your organization

#### Get organization

```bash
curl https://api.you.uat.unico.app/api/console/v1/organization/<organizationId> \
  -H "x-console-authorization: <authToken>"
```

Response:

```json
{
  "organization": {
    "id": "e5d3f1a2-0000-0000-0000-abcdef012345",
    "name": "Acme Corp",
    "responsibleEmail": "admin@acme.com",
    "websiteUrl": "https://acme.com",
    "countryCode": "BRA",
    "tenantId": "tenant-acme-prod",
    "branchId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "taxId": "12345678000195"
  }
}
```

#### Update organization

```bash
curl -X PUT https://api.you.uat.unico.app/api/console/v1/organization \
  -H "x-console-authorization: <authToken>" \
  -H "Content-Type: application/json" \
  -d '{
    "id": "e5d3f1a2-0000-0000-0000-abcdef012345",
    "name": "Acme Corp",
    "responsibleEmail": "admin@acme.com",
    "websiteUrl": "https://acme.com",
    "countryCode": "BRA",
    "taxId": "12345678000195",
    "logo": "https://acme.com/logo-updated.png",
    "allowedDomains": ["https://app.acme.com", "https://checkout.acme.com"]
  }'
```

***

### Managing access keys

**List keys** (metadata only — secret is never returned):

```bash
curl https://api.you.uat.unico.app/api/console/v1/access-keys \
  -H "x-console-authorization: <authToken>"
```

**Rotate a key** (old key is immediately invalidated):

```bash
curl -X POST https://api.you.uat.unico.app/api/console/v1/access-keys/rotate \
  -H "x-console-authorization: <authToken>" \
  -H "Content-Type: application/json" \
  -d '{"accessKey": "uk_live_a1b2c3d4e5f6..."}'
```

**Revoke a key** (irreversible):

```bash
curl -X DELETE https://api.you.uat.unico.app/api/console/v1/access-keys \
  -H "x-console-authorization: <authToken>" \
  -H "Content-Type: application/json" \
  -d '{"accessKey": "uk_live_a1b2c3d4e5f6..."}'
```

***

### Managing branches

Branches let you segment your organization's configuration (name, logo, allowed domains) per product or environment. Each branch has its own access keys, so the branch context is resolved automatically from the key used in the request — no need to pass `branchId` in `CreateProcess`.

#### Create a branch

```bash
curl -X POST https://api.you.uat.unico.app/api/console/v1/organization/branches \
  -H "x-console-authorization: <authToken>" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mobile App",
    "logo": "https://acme.com/mobile-logo.png",
    "allowedDomains": ["https://mobile.acme.com"]
  }'
```

Response:

```json
{
  "branchId": "7ab1c2d3-0000-0000-0000-abcdef012345"
}
```

Save `branchId` — use it when creating a branch-specific access key.

#### Update a branch

```bash
curl -X PUT https://api.you.uat.unico.app/api/console/v1/organization/branches \
  -H "x-console-authorization: <authToken>" \
  -H "Content-Type: application/json" \
  -d '{
    "branchId": "7ab1c2d3-0000-0000-0000-abcdef012345",
    "name": "Mobile App v2",
    "logo": "https://acme.com/mobile-logo-v2.png",
    "allowedDomains": ["https://mobile.acme.com", "https://app.acme.com"]
  }'
```

#### Create a branch-specific access key

To generate an access key scoped to a specific branch, include `branchId` in the request body:

```bash
curl -X POST https://api.you.uat.unico.app/api/console/v1/access-keys \
  -H "x-console-authorization: <authToken>" \
  -H "Content-Type: application/json" \
  -d '{
    "label": "mobile-app-key",
    "branchId": "7ab1c2d3-0000-0000-0000-abcdef012345"
  }'
```

Response:

```json
{
  "accessKey": "uk_live_z9y8x7w6v5u4..."
}
```

> **The `accessKey` is returned only once.** Store it immediately. Any `CreateProcess` request authenticated with this key will automatically use the branch configuration associated with it.
