메인 콘텐츠로 건너뛰기

LLM으로 구축하기

Markdown

아래 프롬프트 중 하나를 Claude Code, Codex 또는 Cursor에 붙여넣어 전체 통합을 완료하세요.

# Authenticate with Unico Human Token — Console Login

You are helping a user authenticate with the Unico Human API Console. Before doing anything else, ask the following questions and wait for the answers:

> **1. Are you signing up for the first time (new account) or signing in to an existing account?**
> Reply with **signup** or **signin**.
>
> **2. (Only if signing in) Which authentication method do you prefer?**
> - **biometric** — face capture via the Unico SDK
> - **email** — one-time code sent to your registered email address

Then follow the matching section below.

- **SIGNUP** always uses biometric. Steps 1–2 require face capture; the link is sent to the provided email.
- **SIGNIN via biometric**: Steps 1–2 require face capture; the link is returned in the API response.
- **SIGNIN via email**: send the OTP to the registered email, then validate the code — no biometric capture required.

> **Note for AI agents:** Biometric steps (SIGNUP and SIGNIN via biometric) require a human to complete face capture — this cannot be automated. After Step 1, hand the link to the user (from the email for SIGNUP, or from `session.link` for SIGNIN biometric), then either wait for their confirmation or poll Step 2 yourself while they complete the capture. The email OTP flow (SIGNIN via email) can be automated end-to-end if the agent has access to the user's inbox.

---

## My environment

```
Base URL: https://api.humantoken.unico.app
```

---

## If SIGNUP — First-time registration + organization setup

Use this flow when the user does not yet have a Human API Console account. By the end you will have a valid `authToken` and an `x-unico-accesskey`.

### What you need before starting

- Work email address (used to identify the account and receive the biometric capture link)
- Full name of the account owner
- Company name
- Website URL
- Country code — any [ISO 3166-1 alpha-3](https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes) code (e.g. `BRA`, `USA`, `MEX`, `DEU`, `IND`)
- Tax ID — optional (e.g. CNPJ for Brazil)
- Logo — URL (optional)
- Domains allowed to use the SDK (optional, e.g. `https://app.yourcompany.com`)

---

### Step 1 — Start a signup session

```bash
curl -X POST <BASE_URL>/api/console/v1/auth/biometric/sessions \
-H "Content-Type: application/json" \
-d '{
"intent": "LOGIN_INTENT_SIGNUP",
"email": "<email>",
"name": "<name>"
}'
```

> If this email is already registered, the request returns `400 Bad Request`. Use the SIGNIN flow instead.

**Expected response:**
```json
{
"session": {
"sessionId": "<sessionId>",
"link": "",
"token": ""
}
}
```

`link` and `token` are empty for SIGNUP. The biometric capture link has been sent to `<email>`. Ask the user to check their inbox, open the link, and complete the face capture. Then proceed to Step 2.

---

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

Replace `<sessionId>` with the value from Step 1. Poll every 2–3 seconds.

```bash
curl <BASE_URL>/api/console/v1/auth/biometric/sessions/<sessionId>
```

Parse the response with a real JSON parser (e.g. `jq`) — not regex/string matching. The API's JSON formatting (whitespace, key order) is not a stable contract, and a hand-rolled extraction can silently fail to detect a resolved session, making the poll loop appear stuck.

Keep polling until `status` is `completed` and `outcome` is `matched`.

| `status` | `outcome` | Action |
|---|---|---|
| `pending` or `processing` | `pending` | Wait 2–3 seconds and poll again |
| `completed` | `matched` | Proceed to Step 3 — save `authToken` |
| `completed` | `no_match` | Biometric not recognized. Go back to Step 1 |
| `completed` | `inconclusive` | Could not be resolved. Go back to Step 1 |
| `expired` | — | Link expired. Go back to Step 1 |

> **SIGNUP-specific error:** If `GetBiometricLogin` returns `400 Bad Request` — "email already registered" — the biometric identity captured is already associated with an existing account. Ask the user to use the SIGNIN flow instead.

**Expected successful response:**
```json
{
"result": {
"sessionId": "<sessionId>",
"status": "completed",
"outcome": "matched",
"authToken": "<authToken>"
}
}
```

Save `authToken` — use it as `x-console-authorization: <authToken>` in Steps 3 and 4.

---

### Step 3 — Create your organization

> **This call can only be made once.** It provisions your tenant and generates your `branchId`.
> Confirm the organization details below with the user before sending this request — it is irreversible.

Fill in your organization details:

```
Company name: [name]
Work email: [responsibleEmail]
Website URL: [websiteUrl]
Country code: [ISO 3166-1 alpha-3, e.g. BRA | USA | MEX | DEU | IND]
Tax ID: [optional]
Logo: [URL — optional]
Allowed domains (optional, comma-separated): [allowedDomains]
```

```bash
curl -X POST <BASE_URL>/api/console/v1/organization \
-H "x-console-authorization: <authToken>" \
-H "Content-Type: application/json" \
-d '{
"name": "<name>",
"responsibleEmail": "<responsibleEmail>",
"websiteUrl": "<websiteUrl>",
"countryCode": "<countryCode>",
"logo": "<logoUrl>",
"allowedDomains": ["<domain1>"]
}'
```

**Expected response:**
```json
{
"organization": {
"id": "<organizationId>",
"name": "<name>",
"branchId": "<branchId>",
"tenantId": "<tenantId>",
...
}
}
```

Save `branchId` — you will need it when creating branches or branch-specific access keys.

---

### Step 4 — Create an access key

Provide a label to identify this key (e.g. `production-key`, `staging-key`).

```bash
curl -X POST <BASE_URL>/api/console/v1/access-keys \
-H "x-console-authorization: <authToken>" \
-H "Content-Type: application/json" \
-d '{
"label": "<label>"
}'
```

**Expected response:**
```json
{
"accessKey": "<accessKey>"
}
```

> **The `accessKey` is returned only once.** Store it immediately in your secrets manager as `UNICO_ACCESS_KEY`.
> It will not be shown again — if lost, you must rotate or revoke and create a new one.

---

### You're done (SIGNUP)

| Value | Variable | Where to use |
|---|---|---|
| `accessKey` | `UNICO_ACCESS_KEY` | `x-unico-accesskey` header in all Human Token requests |

Store this value in your secrets manager. Never commit it to source control or expose it to the browser.

To continue, see the [Human Token integration guide](https://developer.unico.io/human-token/api-reference/create-process).

---

### Optional — Manage branches

Branches let you segment your organization's configuration per product or environment.

> **Ask the user:** "Would you like to create additional branches for your organization (e.g. separate configurations for mobile, web, or staging)?"
> If yes, proceed below. If no, skip to the end-to-end test section.

#### Create a branch

```bash
curl -X POST <BASE_URL>/api/console/v1/organization/branches \
-H "x-console-authorization: <authToken>" \
-H "Content-Type: application/json" \
-d '{
"name": "<branchName>",
"logo": "<logoUrl>",
"allowedDomains": ["<domain1>"]
}'
```

**Expected response:**
```json
{
"branchId": "<branchId>"
}
```

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

#### Update a branch

```bash
curl -X PUT <BASE_URL>/api/console/v1/organization/branches \
-H "x-console-authorization: <authToken>" \
-H "Content-Type: application/json" \
-d '{
"branchId": "<branchId>",
"name": "<updatedName>",
"logo": "<updatedLogoUrl>",
"allowedDomains": ["<domain1>", "<domain2>"]
}'
```

#### Create a branch-specific access key

```bash
curl -X POST <BASE_URL>/api/console/v1/access-keys \
-H "x-console-authorization: <authToken>" \
-H "Content-Type: application/json" \
-d '{
"label": "<label>",
"branchId": "<branchId>"
}'
```

**Expected response:**
```json
{
"accessKey": "<accessKey>"
}
```

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

---

---

## If SIGNIN via biometric — Returning user, face capture

Use this flow when the user already has a Human API Console account and wants to authenticate with face recognition.

---

### Step 1 — Start a signin session

```bash
curl -X POST <BASE_URL>/api/console/v1/auth/biometric/sessions \
-H "Content-Type: application/json" \
-d '{
"intent": "LOGIN_INTENT_SIGNIN"
}'
```

**Expected response:**
```json
{
"session": {
"sessionId": "<sessionId>",
"link": "<link>",
"token": "<sdkToken>"
}
}
```

Open `link` in your browser and complete the biometric capture (face recognition). Then proceed to Step 2.

---

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

Replace `<sessionId>` with the value from Step 1. Poll every 2–3 seconds.

```bash
curl <BASE_URL>/api/console/v1/auth/biometric/sessions/<sessionId>
```

Parse the response with a real JSON parser (e.g. `jq`) — not regex/string matching. The API's JSON formatting (whitespace, key order) is not a stable contract, and a hand-rolled extraction can silently fail to detect a resolved session, making the poll loop appear stuck.

Keep polling until `status` is `completed` and `outcome` is `matched`.

| `status` | `outcome` | Action |
|---|---|---|
| `pending` or `processing` | `pending` | Wait 2–3 seconds and poll again |
| `completed` | `matched` | Login successful — save `authToken` |
| `completed` | `no_match` | Biometric not recognized. Go back to Step 1 |
| `completed` | `inconclusive` | Could not be resolved. Go back to Step 1 |
| `expired` | — | Link expired. Go back to Step 1 |

> **SIGNIN-specific error:** If `GetBiometricLogin` returns `400 Bad Request` — "user not found" — the biometric identity has no registered account. Ask the user to use the SIGNUP flow instead.

**Expected successful response:**
```json
{
"result": {
"sessionId": "<sessionId>",
"status": "completed",
"outcome": "matched",
"authToken": "<authToken>"
}
}
```

Save `authToken` — use it as `x-console-authorization: <authToken>` in all Console API requests.

---

### You're done (SIGNIN via biometric)

You now have a valid `authToken`. Use it as the `x-console-authorization` header in all authenticated Console API calls (organization management, access key management, etc.).

---

---

## If SIGNIN via email — Returning user, OTP code

Use this flow when the user already has a Human API Console account and wants to authenticate with a one-time code sent to their registered email. **Signup is not supported via email OTP** — use the SIGNUP biometric flow for first-time registration.

---

### What you need before starting

- Registered email address of the account

---

### Step 1 — Send the OTP

```bash
curl -X POST <BASE_URL>/api/console/v1/auth/email/sessions \
-H "Content-Type: application/json" \
-d '{
"email": "<email>"
}'
```

> If the email is not registered, `GetEmailLogin` will return `404 Not Found`. Ask the user to use the SIGNUP biometric flow instead.

**Expected response:**
```json
{
"session": {
"sessionId": "<sessionId>"
}
}
```

Save `sessionId`. A 6-digit code has been sent to `<email>`. Ask the user to check their inbox and provide the code.

---

### Step 2 — Validate the OTP

Replace `<sessionId>` and `<code>` with the values from Step 1 and the user's inbox.

```bash
curl <BASE_URL>/api/console/v1/auth/email/sessions/<sessionId>/<code>
```

| HTTP | Condition | Action |
|---|---|---|
| `200` | Code valid — `authToken` present | Proceed — save `authToken` |
| `400` | Wrong code (`invalid otp code`) | Ask the user to check the code and retry |
| `400` | OTP already used, max attempts reached, or expired | Go back to Step 1 |
| `404` | Email not registered | Use the SIGNUP biometric flow |

**Expected successful response:**
```json
{
"result": {
"sessionId": "<sessionId>",
"status": "completed",
"outcome": "matched",
"authToken": "<authToken>"
}
}
```

Save `authToken` — use it as `x-console-authorization: <authToken>` in all Console API requests.

---

### You're done (SIGNIN via email)

You now have a valid `authToken`. Use it as the `x-console-authorization` header in all authenticated Console API calls (organization management, access key management, etc.).