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

# Onboard — Hosted UI

> Onboard personal customers using Etherfuse's hosted verification page

The hosted UI flow is the fastest way to onboard a **personal** customer. You generate a presigned URL, redirect the user to Etherfuse's verification page, and they complete identity verification, document upload, bank account registration, and agreement signing in one session.

<Info>
  **Personal customers only.** This endpoint always creates a personal organization — it forces individual KYC. To onboard a business customer, use the [Programmatic flow](/guides/onboarding-programmatic) with `accountType: "business"` instead; business customers are KYB-approved as a whole and skip individual KYC.
</Info>

<Info>
  **Supported blockchains:** The `blockchain` field accepts `solana`, `stellar`, `base`, `polygon`, or `monad`. All examples use Solana, but the flow works identically across chains — just pass the appropriate value and a valid public key for that chain.
</Info>

## Flow

<Steps>
  <Step title="Generate Presigned URL — POST /ramp/onboarding-url">
    <Expandable title="Details">
      This creates the customer organization (as a personal child org under yours) and returns a presigned URL valid for **15 minutes**. You generate the `customerId` and `bankAccountId` UUIDs. See [POST /ramp/onboarding-url](/api-reference/onboarding/generate-onboarding-url) for the full schema.

      <CodeGroup>
        ```bash Sandbox theme={null}
        curl -X POST https://api.sand.etherfuse.com/ramp/onboarding-url \
          -H "Authorization: <api_key>" \
          -H "Content-Type: application/json" \
          -d '{
            "customerId": "<customer_uuid>",       # You generate this UUID
            "bankAccountId": "<bank_account_uuid>", # You generate this UUID
            "publicKey": "<wallet_public_key>",
            "blockchain": "solana",
            "userInfo": {
              "email": "ana@example.com",
              "displayName": "Ana García"
            }
          }'
        ```

        ```bash Production theme={null}
        curl -X POST https://api.etherfuse.com/ramp/onboarding-url \
          -H "Authorization: <api_key>" \
          -H "Content-Type: application/json" \
          -d '{
            "customerId": "<customer_uuid>",       # You generate this UUID
            "bankAccountId": "<bank_account_uuid>", # You generate this UUID
            "publicKey": "<wallet_public_key>",
            "blockchain": "solana",
            "userInfo": {
              "email": "ana@example.com",
              "displayName": "Ana García"
            }
          }'
        ```
      </CodeGroup>

      **Response:**

      ```json theme={null}
      {
        "presigned_url": "https://devnet.etherfuse.com/onboarding?token=..."
      }
      ```

      <Warning>
        **Store these IDs** — you'll need `customerId` for quotes, and `bankAccountId` for orders. The `customerId` must be a new UUID, not your own organization's ID.
      </Warning>

      <Info>
        **`userInfo` is recommended** and **will eventually be required**. When provided, Etherfuse pre-creates the user record so the customer's eventual sign-in attaches to the right user, and we can email them on status changes (KYC approved/rejected, bank account verified, etc.).
      </Info>
    </Expandable>
  </Step>

  <Step title="Redirect the User">
    <Expandable title="Details">
      Send the customer to the `presigned_url`. They have 15 minutes to complete the full flow in the Etherfuse-hosted UI:

      1. Identity verification (name, address, phone, email)
      2. Document upload (government ID + selfie)
      3. Bank account registration (CLABE)
      4. Agreement signing (electronic signature, terms, customer agreement)

      <Info>In **sandbox**, fake data is accepted — no real personal information required.</Info>
    </Expandable>
  </Step>

  <Step title="Monitor Status">
    <Expandable title="Details">
      Track onboarding progress via `kyc_updated` webhooks or by polling [GET /ramp/customer/\{id}/kyc/\{pubkey}](/api-reference/kyc/get-kyc-status).

      ```bash theme={null}
      GET /ramp/customer/{customer_uuid}/kyc/{pubkey}
      ```

      In **sandbox**, the customer is auto-approved when the customer agreement is signed. In **production**, Etherfuse admins review the submitted documents before approving. See [Checking KYC Status](/guides/onboarding#checking-kyc-status) for response details and status values.
    </Expandable>
  </Step>
</Steps>

<Info>
  **Field naming convention:** API responses use `snake_case` (e.g., `presigned_url`), while request bodies use `camelCase` (e.g., `presignedUrl`). This is consistent across all Etherfuse endpoints.
</Info>

<Expandable title="Common errors">
  | Error                       | Cause                                    | Fix                                                    |
  | --------------------------- | ---------------------------------------- | ------------------------------------------------------ |
  | `presigned_url expired`     | URL is older than 15 minutes             | Generate a fresh URL via `POST /ramp/onboarding-url`   |
  | `customerId already exists` | UUID collision with an existing customer | Use a new UUID for `customerId`                        |
  | `Invalid blockchain`        | Unsupported blockchain value             | Use `solana`, `stellar`, `base`, `polygon`, or `monad` |
</Expandable>
