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

# Apple Pay In-App Provisioning

> Integrate Apple Pay In-App Provisioning into your iOS app

## Overview

Apple Pay In-App Provisioning lets a user add their card to Apple Wallet without entering the card details manually. Your app starts the system Apple Pay flow, sends the values supplied by PassKit to Gnosis Pay, and gives the encrypted response back to PassKit.

> [!NOTE]
>
> Apple Pay In-App Provisioning must be enabled for your card program before you can use this flow. Contact your Gnosis Pay representative before starting integration or testing.

## Before you start

You need:

* An iOS app with the Apple-issued `com.apple.developer.payment-pass-provisioning` entitlement.
* The app and card program approved for Apple Pay In-App Provisioning.
* An authenticated Gnosis Pay user with an active, eligible card.
* PassKit integrated into your iOS app.

See Apple's [Apple Pay for developers](https://developer.apple.com/apple-pay/) and [`PKAddPaymentPassViewController`](https://developer.apple.com/documentation/passkit/pkaddpaymentpassviewcontroller) documentation for the entitlement and app setup.

## End-to-end flow

```mermaid theme={null}
sequenceDiagram
    participant User
    participant App as iOS App
    participant PassKit
    participant API as Gnosis Pay user-api

    User->>App: Tap Add to Apple Wallet
    App->>PassKit: Present PKAddPaymentPassViewController
    PassKit->>App: Certificates, nonce, and nonce signature
    App->>API: POST /user-api/cards/{cardId}/apple-pay/provisioning
    API-->>App: Encrypted provisioning data
    App->>PassKit: PKAddPaymentPassRequest
    PassKit-->>User: Card added or verification required
```

> [!WARNING]
>
> Make the request to Gnosis Pay only from the PassKit delegate callback. Apple requires the completion handler to be called within 20 seconds.

## Implement the flow

**1. Check that In-App Provisioning is available**

Use `PKAddPaymentPassViewController.canAddPaymentPass()` before showing the Add to Apple Wallet action.

**2. Create the PassKit configuration**

Create a `PKAddPaymentPassRequestConfiguration` using the ECC V2 encryption scheme. Set the cardholder name, the card's last four digits, and the Visa payment network.

```swift theme={null}
import PassKit

guard let configuration = PKAddPaymentPassRequestConfiguration(
    encryptionScheme: .ECC_V2
) else {
    return
}

configuration.cardholderName = cardholderName
configuration.primaryAccountSuffix = cardLastFour
configuration.localizedDescription = cardDisplayName
configuration.paymentNetwork = .visa
```

Present `PKAddPaymentPassViewController` with this configuration and set your app as its delegate.

**3. Send the PassKit values to Gnosis Pay**

PassKit calls your delegate with a certificate chain, nonce, and nonce signature. Base64-encode each `Data` value and call:

```http theme={null}
POST /user-api/cards/{cardId}/apple-pay/provisioning
```

Send the two certificates in the order provided: leaf certificate first, intermediate certificate second. Do not append the root certificate.

```json theme={null}
{
  "certificates": [
    "<base64-leaf-certificate>",
    "<base64-intermediate-certificate>"
  ],
  "nonce": "<base64-nonce>",
  "nonce_signature": "<base64-nonce-signature>",
  "device_type": "mobile_phone",
  "app_version": "1.0.0"
}
```

Map the delegate values without modifying them:

```swift theme={null}
let requestBody: [String: Any] = [
    "certificates": certificates.map { $0.base64EncodedString() },
    "nonce": nonce.base64EncodedString(),
    "nonce_signature": nonceSignature.base64EncodedString(),
    "device_type": deviceType,
    "app_version": appVersion
]
```

`device_type` accepts:

| Value | Use when provisioning to |
| - | - |
| `mobile_phone` | The user's iPhone |
| `watch` | A paired Apple Watch |

Set `device_type` from the provisioning target selected in your app before presenting the PassKit flow.

`app_version` should be the current app version, such as the value of `CFBundleShortVersionString`.

`product_type` is optional. Omit it unless Gnosis Pay has provided a value for your card program.

**4. Create the payment pass request**

A successful response contains:

```json theme={null}
{
  "activation_data": "<base64>",
  "encrypted_pass_data": "<base64>",
  "ephemeral_public_key": "<base64>"
}
```

Base64-decode all three values, assign them to a `PKAddPaymentPassRequest`, and call the PassKit completion handler.

```swift theme={null}
guard
    let activationData = Data(base64Encoded: response.activationData),
    let encryptedPassData = Data(base64Encoded: response.encryptedPassData),
    let ephemeralPublicKey = Data(base64Encoded: response.ephemeralPublicKey)
else {
    controller.dismiss(animated: true)
    return
}

let request = PKAddPaymentPassRequest()
request.activationData = activationData
request.encryptedPassData = encryptedPassData
request.ephemeralPublicKey = ephemeralPublicKey
completionHandler(request)
```

See Apple's [`PKAddPaymentPassRequest`](https://developer.apple.com/documentation/passkit/pkaddpaymentpassrequest) documentation for the PassKit object.

## API request examples

Use the `cardId` returned by the Cards API. The card must belong to the authenticated user.

> [tab] Sandbox
>
> ```bash theme={null}
> curl --request POST \
>   --url https://core.sandbox.gnosispay.in/user-api/cards/{cardId}/apple-pay/provisioning \
>   --header 'Authorization: Bearer <token>' \
>   --header 'Content-Type: application/json' \
>   --data '{
>     "certificates": [
>       "<base64-leaf-certificate>",
>       "<base64-intermediate-certificate>"
>     ],
>     "nonce": "<base64-nonce>",
>     "nonce_signature": "<base64-nonce-signature>",
>     "device_type": "mobile_phone",
>     "app_version": "1.0.0"
>   }'
> ```

> [tab] Production
>
> ```bash theme={null}
> curl --request POST \
>   --url https://core.prod.gnosispay.com/user-api/cards/{cardId}/apple-pay/provisioning \
>   --header 'Authorization: Bearer <token>' \
>   --header 'Content-Type: application/json' \
>   --data '{
>     "certificates": [
>       "<base64-leaf-certificate>",
>       "<base64-intermediate-certificate>"
>     ],
>     "nonce": "<base64-nonce>",
>     "nonce_signature": "<base64-nonce-signature>",
>     "device_type": "mobile_phone",
>     "app_version": "1.0.0"
>   }'
> ```

## Errors

| Status | Error | What to do |
| - | - | - |
| `400` | `APPLE_PAY_INVALID_DATA` | Start a new PassKit flow and send the newly generated values. |
| `401` | Unauthorized | Refresh the user session before starting again. |
| `404` | `CARD_NOT_FOUND` | Refresh the user's cards and verify the selected `cardId`. |
| `409` | `APPLE_PAY_NOT_AVAILABLE` | Do not retry. In-App Provisioning is not currently available for the card. |
| `502` | `APPLE_PAY_PROVISIONING_FAILED` | End the current PassKit flow and let the user try again. |
| `503` | `APPLE_PAY_PROVISIONING_UNAVAILABLE` | End the current PassKit flow and let the user try again later. |

Do not reuse certificates, nonce values, signatures, or provisioning responses from a previous PassKit callback.

## Verification and security

Apple Wallet may require the user to complete an additional verification step after the provisioning data is accepted. Verification is delivered through the channels configured for your card program; no additional provisioning endpoint is required in the app.

Treat all provisioning request and response fields as sensitive and short-lived:

* Do not log or persist certificates, nonce values, nonce signatures, or encrypted provisioning data.
* Do not cache the API response.
* Do not send the card number, security code, or other card credentials to this endpoint.
* Always start a new PassKit flow after an error or timeout.

Test the complete flow on eligible iPhone and Apple Watch devices before release, including successful provisioning, verification, cancellation, and temporary API failures.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.