> ## 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.

# User authentication

> Connect your users to Agentcard from inside your own app.

Connect a user to Agentcard without sending them to a hosted page. You build the
screens; Agentcard sends the one-time code and hands you back the user's access
token. Everything happens through your own interface — your users never see an
Agentcard-hosted page. (If your app opens a "Connect your account" sign-in at
`mcp.agentcard.sh`, you've wired the MCP server's OAuth flow instead of this
API: trigger the code with
[`connect/start`](/companies/api/reference/connect-start) and hand the
resulting token straight to the [MCP server](/companies/guides/mcp-server).)

## Instructions for your agent

Paste this into your coding agent to implement the connect flow.

```text Instructions for your agent theme={null}
You are adding "Connect with Agentcard" to this app: the user enters a one-time
code and we hand back their Agentcard connection — no redirects. Implement it
server-side. NEVER send the user to a hosted Agentcard/MCP sign-in page (e.g.
mcp.agentcard.sh) — this API replaces it entirely.

PREREQUISITES
- client_id + client_secret from the Agentcard dashboard (Organization ->
  Developer -> Credentials -> create a client). Store as backend env vars.
  A sandbox client works now; a production client needs an active subscription.
- Base URL https://api.agentcard.sh. All calls are backend-to-backend; never
  expose the secret or any token to the client.

1. PLATFORM TOKEN (cache ~55 min)
POST /api/v2/oauth/token  (x-www-form-urlencoded)
  grant_type=client_credentials & client_id=... & client_secret=...
-> { access_token }. Send `Authorization: Bearer <access_token>` on every call.

2. SEND THE CODE
POST /api/v2/connect/start  { "email": "<email>" }   // or { "phone": "<E.164>" }, exactly one
-> 201 { id }   // store as connect_id

3. USER ENTERS THE CODE in your UI.

4. VERIFY
POST /api/v2/connect/verify  { "connect_id": "<id>", "code": "<code>" }
-> 200 { access_token, refresh_token, expires_in, user: { id, email, phone } }
Store user.id and the connection access_token + refresh_token (encrypted, per
user). 401 invalid_code -> re-prompt. invalid_connect_attempt -> restart.

5. RECORD CONSENT (when the user authorizes you) — do not skip
POST /api/v2/connect/consent  { "user_id": "<user.id>", "terms_version": "<version>" } -> 201.
Also covers the card issuer's terms: without it, identity verification later
pauses the user on an extra terms page instead of going straight to the scan.

REFRESH: tokens expire in 1h. POST /api/v2/connect/refresh { "refresh_token": "<stored>" }
-> new pair; replace BOTH stored tokens.
ERRORS: { error: { code, message, docs } } — branch on code.
```

## How it works

1. Your backend asks Agentcard to send the user a code (by email or phone).
2. The user types the code into your app.
3. Your backend submits the code and receives the user's access token.
4. Your backend records the user's consent (your terms must include the [payment-processor privacy disclosure](/companies/api/reference/connect-consent#what-your-terms-must-disclose) — it enables the wallet-funding rail for the connection).

Every call is made from your backend with your platform access token in the
`Authorization` header. Each step below links to its page in the
[API reference](/companies/api/reference), where you'll find every parameter,
every response field, and a live playground to try the call with your own
credentials.

## The flow

<Steps>
  <Step title="Authenticate your platform">
    Exchange your `client_id` + `client_secret` for a platform access token and
    send it as `Authorization: Bearer <token>` on every call. Tokens live one
    hour — cache and reuse.

    → [Create an access token](/companies/api/reference/create-access-token)
  </Step>

  <Step title="Send the code">
    Ask Agentcard to send a one-time code to the user, by email or phone
    (exactly one). Store the returned `id` — it's the `connect_id` for the next
    step.

    → [Send a code](/companies/api/reference/connect-start)
  </Step>

  <Step title="Verify the code">
    Submit the code the user typed into your app. On success you get the
    **user's connection token** — it acts on behalf of that user (send it to
    the [MCP server](/companies/mcp/overview) to create cards and shop as
    them) — plus `user.id`, which every later call names the user by. Store
    all three: `user.id`, `access_token`, `refresh_token`.

    → [Verify the code](/companies/api/reference/connect-verify)
  </Step>

  <Step title="Record consent">
    Record that the user authorized your platform to act on their behalf.
    Idempotent per user — safe to retry. Don't skip it: the consent also
    covers the card issuer's terms, so
    [identity verification](/companies/api/identity-verification) later goes
    straight to the face scan instead of pausing the user on an extra terms
    page.

    → [Record consent](/companies/api/reference/connect-consent)
  </Step>

  <Step title="Keep the connection alive">
    Connection tokens expire after one hour. Exchange the refresh token for a
    new pair before then, and replace **both** stored tokens every time.

    → [Refresh the connection](/companies/api/reference/connect-refresh)
  </Step>
</Steps>

<Note>
  In **sandbox** the code is always `111111`, so you can run this whole flow —
  including from the reference playground — without a real inbox or phone.
</Note>

## Customize the code email

The email your users receive is yours to design. Set it up in your Agentcard
dashboard, and every code you send uses it.
