---
name: verify-seller
description: Run a seller through Paddle's KYB/KYC verification with the `@paddle/partner-embeds` SDK and partner API — mint a magic-session token, open the embed, poll `automated_review`, handle next steps, and take the seller live when it completes.
metadata:
  internal: true
---

# Verify a seller and take them live

## When to use this skill

Use this skill for the last stage of go-live: KYB/KYC verification. You collect the seller's details with Paddle's verification embed, Paddle reviews them asynchronously, and when the seller passes, Paddle enables live payments on their account. Most of your work is surfacing status and guiding the seller through anything Paddle asks for. Verification runs on **live**.

Two credentials are involved (see [`partner-api-basics`](/partners/embed-billing/get-started/api-basics)):

- The seller's **`user_api_key`** — to mint the magic-session token the embed needs.
- Your **partner API key** (`psk_...` + `Paddle-PartnerID`) — to read verification status.

## 1. Open the verification embed

Install the SDK (`@paddle/partner-embeds`, or `@paddle/partner-embeds-react` for the hook).

Mint a one-time token by calling `POST /magic-sessions/authorize` with the seller's `user_api_key` as the Bearer token and an empty body. A `201` returns a single-use `code`.

```bash
curl -X POST https://api.paddle.com/magic-sessions/authorize \
  -H "Authorization: Bearer $USER_API_KEY"
```

```json
{
  "data": {
    "code": "Vh7nQ2pXk9Lm4Rt1Ws8Yz6Bc3Nj0Gd5Fu2Ei7Ol4KaZ",
    "expires_at": "2026-03-05T19:21:36.711613073Z"
  },
  "meta": { "request_id": "d1f2a3b4-5c6d-47e8-9f0a-1b2c3d4e5f60" }
}
```

Pass the `code` to `PaddleVerification.create()` as its token. Prefill everything you know to speed the seller up.

```ts
import { PaddleVerification } from "@paddle/partner-embeds/verifications";

PaddleVerification.create({
  target: "#verification",
  token, // the one-time code from POST /magic-sessions/authorize
  environment: "production", // 'sandbox' only to trial the embed UI; real verification runs on live
  prefill: { countryCode: "GB", businessType: "company" },
  onComplete: ({ id }) => {
    // Seller has SUBMITTED for review — not yet verified. Refresh status in your UI.
  },
  onError: ({ code, message }) => console.error(code, message),
}).mount();
```

When the seller finishes, `onComplete` returns the verification `id` (prefixed `slrvrf_`). You can also read it from `GET /seller-verifications`. Store it against the seller — you need it to poll status.

> `onComplete` fires when the seller **submits** their details. That's not the same as being verified — Paddle's review happens after.

The embed only renders on domains on Paddle's allowlist; share your platform's domains with your Paddle contact first. See the [embed SDK reference](/partners/embed-billing/seller-go-live/embed-sdk-reference) for the full API, the React hook, and theming.

## 2. Present verification status

Paddle verifies the account in a step called `automated_review`. Poll `GET /seller-verifications/{seller_verification_id}` with your **partner key** and drive your UI from the `automated_review` step's `status`.

```bash
curl https://api.paddle.com/seller-verifications/slrvrf_01gjn16x6xxb6vkznqwfphthxb \
  -H "Authorization: Bearer $PARTNER_API_KEY" \
  -H "Paddle-PartnerID: $PARTNER_ID"
```

| `automated_review` status   | What it means                          | What to show                                                            |
| --------------------------- | -------------------------------------- | ----------------------------------------------------------------------- |
| `in_progress` / `in_review` | Review underway, no action needed      | "Verification in progress."                                             |
| `action_required`           | Paddle needs something from the seller | Surface the action (step 3)                                             |
| `completed`                 | Passed                                 | "You're verified and ready to go live."                                 |
| `failed`                    | Didn't pass                            | "There's a problem with verification. Check your email for next steps." |

Poll roughly every 60 seconds while a step is `in_progress` or `action_required` and the seller is on the verification screen; back off when they navigate away, and offer a manual refresh.

## 3. Handle verification next steps

Verifications usually move to `action_required` before `completed`. When they do, read the step from `GET /seller-verifications/{seller_verification_id}/steps/automated-review` (partner key) and use `status_reason` to decide what to surface:

| `status_reason`                   | What the seller does                                                                                                                                                                 |
| --------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `sole_trader_external_url_check`  | One identity check. Show a "Verify identity" button linking to the single stakeholder's `details.url`.                                                                               |
| `stakeholders_external_url_check` | Each stakeholder completes an identity check. List each stakeholder with a copyable link to their `details.url`.                                                                     |
| `upload_file_kyb`                 | Paddle needs documents (for example business registration). Send the seller to the dashboard with a magic link (`redirect=onboarding`) — file uploads happen in Paddle for security. |

For document uploads, mint a magic session (`POST /magic-sessions/authorize` with the `user_api_key`) and redirect the seller to `https://vendors.paddle.com/magic-sessions/login?code={code}&redirect=onboarding`. See [`access-paddle-dashboard`](/partners/embed-billing/manage-sellers/magic-links).

Keep polling. Once the action is done and Paddle finishes review, `automated_review` settles on `completed` or `failed`.

## 4. Take the seller live

When `automated_review.status` is `completed`, Paddle enables checkout on the seller's live account — **there's no separate activate or go-live call**. Give the seller a clear "go live" moment in your UI, then use your agent to switch their app to live: swap in the seller's live `api_key` and client-side token, and resolve prices against their live catalog. Keep a test/live toggle so they can still preview in sandbox.

## Common pitfalls

- **Treating `onComplete` as "verified."** It means "submitted." Poll `automated_review` for the real outcome.
- **Waiting for a webhook or an activate call.** There's neither — poll to `completed`, and live payments are already on.
- **Embedding on a non-allowlisted domain.** The iframe refuses to load. Get your domains allowlisted first.
- **Polling too aggressively.** ~60s while active, backing off when the seller leaves the screen.

## Verify

- `POST /magic-sessions/authorize` returns `201` with a `code`; the embed mounts and the seller can submit.
- `GET /seller-verifications/{id}` returns `200`; you can render each `automated_review` status.
- When status reaches `completed`, a live checkout opens on the seller's account.

## Related docs

- [Verify a seller and go-live](/partners/embed-billing/seller-go-live/verify-seller)
- [Verification embed SDK reference](/partners/embed-billing/seller-go-live/embed-sdk-reference)
- [Prepare a seller for go-live](/partners/embed-billing/seller-go-live/prepare-for-go-live)
- [`register-checkout-domain`](/partners/embed-billing/seller-go-live/checkout-domains), [`access-paddle-dashboard`](/partners/embed-billing/manage-sellers/magic-links)
