> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.alphax.asia/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.alphax.asia/_mcp/server.

# Verification page

Before a company can open payment routes, its director completes identity
verification. AlphaX hosts that page for you — **unbranded**, so you can put it
inside your own product and keep the customer in your flow.

## Step 1 — Get the link

Onboarding a company onto swap returns it, and you can re-read it any time:

```
GET /v1/kyc-link
X-API-Key: <your partner API key>
X-Company-Id: <the company id>
```

```json
{
  "swap": {
    "kycUrl": "https://public-api.alphax.com/kyc/9f2c1d84e7b6a5309c8f",
    "kycStatus": "not_started",
    "tosUrl": "https://public-api.alphax.com/kyc/9f2c1d84e7b6a5309c8f/terms",
    "tosAccepted": false
  }
}
```

The link does not expire, so you can store it against the company and re-open it
whenever the customer returns to finish.

Treat `kycUrl` as a credential — the token in the path is what authorises access
to that company's verification. Don't put it anywhere public.

## Step 2 — Show it

Either send the customer to the URL directly, or embed it. The page sets
`frame-ancestors *`, so an `<iframe>` works from any origin:

```html
<iframe
  src="https://public-api.alphax.com/kyc/9f2c1d84e7b6a5309c8f"
  allow="camera;"
  style="width: 100%; height: 100%; border: 0"
></iframe>
```

Keep `allow="camera;"` — verification includes document and selfie capture, and
the flow cannot complete without camera access. Give the iframe real height too;
the form is full-page.

Pass `redirectUri` when you onboard the company to send the customer back to your
own page when they finish:

```json
{
  "products": ["Swap"],
  "redirectUri": "https://your-app.example/onboarding/done"
}
```

Omit it and we show an AlphaX completion page instead.

## Step 2b — Have the terms accepted

Verification is only half of what is asked of the company. It must also accept
the terms of service, at `tosUrl` — a second page you embed exactly the same way:

```html
<iframe
  src="https://public-api.alphax.com/kyc/9f2c1d84e7b6a5309c8f/terms"
  style="width: 100%; height: 100%; border: 0"
></iframe>
```

No camera is needed here, so `allow="camera;"` can be dropped.

**A company cannot be endorsed until the terms are accepted**, no matter how far
verification has got. Surface this alongside verification rather than after it —
`tosAccepted` tells you whether it is still outstanding.

The two are deliberately separate pages so you can deep-link to whichever step is
still needed, rather than making the customer walk through both again.

## Step 3 — React to the outcome

`kycStatus` moves through these values:

| Status                   | Meaning                                                    | What to do                              |
| ------------------------ | ---------------------------------------------------------- | --------------------------------------- |
| `not_started`            | A link exists but the customer has not begun               | Keep the link available                 |
| `incomplete`             | Begun but not submitted                                    | Prompt the customer to finish           |
| `awaiting_questionnaire` | Extra questions must be answered                           | **Ask the customer to reopen the link** |
| `awaiting_ubo`           | Details of the ultimate beneficial owners are still needed | **Ask the customer to reopen the link** |
| `under_review`           | Submitted; a human is looking at it                        | Wait — no action needed                 |
| `approved`               | Verified                                                   | Payment routes can be opened            |
| `rejected`               | Declined                                                   | Contact AlphaX support                  |
| `paused`                 | Temporarily halted                                         | Contact AlphaX support                  |
| `offboarded`             | The customer has been removed                              | Contact AlphaX support                  |

The two `awaiting_*` states are the ones to surface in your own UI — verification
is blocked until the customer supplies something, and reopening `kycUrl` takes
them straight to it. Everything else is informational.

Rather than polling `GET /v1/kyc-link`, subscribe to
[`company.kyc_status_changed`](/swap/webhooks) — it fires on every transition.
`company.kyc_link.issued` fires when the link first becomes available, which is
useful if you onboard companies from a background job.

Verification is a manual review, not an instant decision. Expect `under_review` to
last hours rather than seconds, and design your onboarding UI to let the customer
leave and come back.