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

# iOS (Swift)

> Add the Agentcard wallet to your iOS app with the AgentcardWalletKit Swift package.

This is the wallet for native iOS apps. AgentcardWalletKit is a SwiftUI package: you pass it a wallet link and present it like any other view. It talks to the API natively, and only the card entry step runs in a secure web view.

## Install (Swift Package Manager)

In Xcode, add the package:

```
https://github.com/tiny-agent-company/agentcard-wallet-ios
```

Pin it at `0.1.0` or later. The repository is private while the SDK is in early access, so ask us for an invite and we'll add your GitHub account.

## Create a wallet link (server side)

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.agentcard.sh/api/v2/wallet_links \
    -H "Authorization: Bearer $ORG_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{"user_id": "USER_ID"}'
  ```

  ```javascript Node theme={null}
  const res = await fetch("https://api.agentcard.sh/api/v2/wallet_links", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${ORG_TOKEN}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ user_id: "USER_ID" }),
  });
  const link = await res.json();
  ```

  ```python Python theme={null}
  import requests

  res = requests.post(
      "https://api.agentcard.sh/api/v2/wallet_links",
      headers={"Authorization": f"Bearer {ORG_TOKEN}"},
      json={"user_id": "USER_ID"},
  )
  link = res.json()
  ```
</CodeGroup>

The response includes a `url`. Hand it to your app. Links expire after 15 minutes by default (`expires_in` accepts 60 to 86400 seconds).

## Present the wallet

```swift theme={null}
import AgentcardWalletKit

.sheet(isPresented: $showWallet) {
    AgentcardWalletSheet(link: walletLinkURL) { event in
        switch event {
        case .cardAttached(let cards):
            // the user added a card
        case .paymentCompleted(let merchant, let amountCents):
            // a payment went through
        case .tokenExpired:
            // fetch a fresh wallet link and present again
        default:
            break
        }
    }
}
```

`AgentcardWalletSheet` also accepts `linkToken:` if you'd rather pass the raw token than the URL.

## Ask for a payment

Pass a pay intent to open the pay sheet instead of the wallet home. `reference` is required: it's your stable id for this payment, and it's what makes retries safe.

```swift theme={null}
AgentcardWalletSheet(
    link: walletLinkURL,
    pay: AgentcardPayIntent(merchant: "Amazon", amountCents: 500, reference: order.id)
) { event in ... }
```

## Webhooks you will receive

Treat the Swift events as UI signals and let your server trust webhooks:

* `connected_card.updated` when the user adds a card
* `transaction.*` events when payments happen

## When it fails

The sheet handles failures itself and tells the user what to do, so there is one case your code handles: `.tokenExpired`, which fires when the link or its session dies. Create a fresh wallet link and present the sheet again.

## Sandbox behavior

With sandbox credentials, the connect code is always `111111` and the test card is `4242 4242 4242 4242` with any future expiry and any CVC. No real money moves.

Next: [Connect users](/wallet/connect-users)
