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

# Start attested onboarding

> Create an onboarding attempt for a phone number you already hold and text the returned `wallet_url` to the user. No Agentcard account exists yet: the user sees the wallet instantly, and our one-time code fires exactly once, inside our page, at their first money action. You never see or relay the code. Requires the attested-onboarding capability on your organization (ask us to enable it).

The response is identical whether or not the phone already belongs to an Agentcard account.

## How it works

You already know your user's phone number, so assert it: create an attempt and
text the returned `wallet_url` into your thread. The user taps it and sees
their Agentcard wallet immediately. No account exists yet, nothing was created
beyond the attempt, and no code has been sent.

The one-time code fires exactly once, inside our page, at the user's first
money action (adding their card, or their first purchase confirmation).
Passing it creates the account, or binds the phone's existing Agentcard
account, and records the connection for your client. You never see or relay
the code; that is the anti-phishing property of the whole flow.

Then:

1. Listen for the `connection.created` webhook. It carries `user_id`, your
   `external_user_id`, and `onboarding_attempt_id`.
2. Call [the exchange](/companies/api/reference/onboarding-attempt-exchange)
   once to collect the connection token pair, and keep it alive with
   [`POST /api/v2/connect/refresh`](/companies/api/reference/connect-refresh).

Attempts expire after 48 hours. Daily quotas apply per organization and per
phone number. The capability is enabled per organization; ask us to turn it
on.


## OpenAPI

````yaml openapi.json POST /api/v2/onboarding_attempts
openapi: 3.1.0
info:
  title: Agentcard API
  version: 2.0.0
  description: >-
    The Agentcard v2 API — connect your users and verify their identity from
    your own backend. Every call is authenticated with a platform access token
    minted from your `client_id` + `client_secret`.
servers:
  - url: https://api.agentcard.sh
    description: >-
      There is one base URL. Sandbox vs production is decided by the client
      credential you use, never by the host.
security:
  - platformToken: []
tags:
  - name: Authentication
    description: >-
      Exchange your client credentials for a platform access token, and
      introspect what a token acts as.
  - name: Connect
    description: >-
      Connect a user to your platform: send a one-time code, verify it, record
      consent, and keep the connection alive.
  - name: Identity verification
    description: >-
      Verify a connected user's identity: upload their ID, submit any extra
      fields we ask for, then show a short face scan.
  - name: Wallet funding
    description: >-
      Fund a connected user's wallet from your own UI — request a payment link,
      relay the phone verification code, and poll until the funds land.
  - name: Withdrawals
    description: >-
      Move money out of a connected user's wallet — to a saved bank account or a
      crypto address on Base. Transfers are processed manually by the Agentcard
      team, usually within 1-3 business days.
paths:
  /api/v2/onboarding_attempts:
    post:
      summary: Start attested onboarding
      description: >-
        Create an onboarding attempt for a phone number you already hold and
        text the returned `wallet_url` to the user. No Agentcard account exists
        yet: the user sees the wallet instantly, and our one-time code fires
        exactly once, inside our page, at their first money action. You never
        see or relay the code. Requires the attested-onboarding capability on
        your organization (ask us to enable it).


        The response is identical whether or not the phone already belongs to an
        Agentcard account.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - phone
              properties:
                phone:
                  type: string
                  description: >-
                    The user's phone. E.164 preferred; US local formats are
                    normalized.
                external_user_id:
                  type: string
                  description: >-
                    Your own id for this person, echoed on `connection.created`
                    and the exchange.
            example:
              phone: '+19295550123'
              external_user_id: your-internal-id
      responses:
        '201':
          description: >-
            The attempt. Text `wallet_url` to the user; listen for
            `connection.created`, then exchange.
          content:
            application/json:
              example:
                object: onboarding_attempt
                id: oa_1a2b3c4d5e6f7a8b9c0d1e2f
                status: pending
                wallet_url: https://app.agentcard.sh/w/oa_1a2b3c4d5e6f7a8b9c0d1e2f.abc123
                expires_at: '2026-08-23T00:00:00.000Z'
                test_mode: true
        '402':
          description: '`subscription_required` in production.'
        '404':
          description: >-
            `not_found` while the capability is not enabled for your
            organization.
        '429':
          description: >-
            `rate_limited` when the per-organization or per-phone daily quota is
            reached.
components:
  securitySchemes:
    platformToken:
      type: http
      scheme: bearer
      description: >-
        A platform access token. Get one on the **Create an access token**
        endpoint by exchanging your `client_id` + `client_secret`, then send it
        as `Authorization: Bearer <token>`. Tokens live one hour.

````