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

# Vaulting card data

Vaulting allows you to securely capture and store card details within a **Checkout Session** without handling 3DS authentication immediately. This is useful for simple payment flows or scenarios where you want to tokenize a card for later use.

## Installation

The official Gr4vy mobile SDKs are available for both iOS and Android platforms. Add them to your project to get started.

<Tabs>
  <Tab title="Swift (iOS)">
    The official Gr4vy Swift SDK is available via Swift Package Manager.

    1. In Xcode, select **File** -> **Add Packages**

    2. Enter the repository URL: [https://github.com/gr4vy/gr4vy-swift](https://github.com/gr4vy/gr4vy-swift)

    3. Select the version or branch you wish to use.
  </Tab>

  <Tab title="Kotlin (Android)">
    The official Gr4vy Kotlin SDK is available via Maven Central. Add it to your build.gradle file:

    ```kotlin theme={"system"}
    dependencies {
        implementation("com.gr4vy:gr4vy-kotlin:1.0.0")
    }
    ```
  </Tab>
</Tabs>

## The vaulting flow

<Steps>
  <Step title="Initialize Checkout Session">
    Create a checkout session on your backend with the transaction details to store the vaulted card data.
  </Step>

  <Step title="Initialize the SDK">
    Initialize the SDK with your Gr4vy ID, then use your own native UI components to collect the card number, expiry date, and CVV.
  </Step>

  <Step title="Vault via SDK">
    Pass the collected card data and checkout session ID to the native SDK to securely vault the card without 3DS authentication.
  </Step>

  <Step title="Process Payment">
    Use the vaulted session ID on your backend to create a transaction or store the card for future use.
  </Step>
</Steps>

## Implementation

### 1. Initialize Checkout Session

First, create a checkout session on your backend. This session stores the vaulted card data.

<CodeGroup>
  ```csharp C# theme={"system"}
  using Gr4vy;
  using Gr4vy.Models.Components;

  var sdk = new Gr4vySDK(
      merchantAccountId: "default",
      bearerAuth: "<YOUR_BEARER_TOKEN_HERE>"
  );

  var checkoutSession = await sdk.CheckoutSessions.CreateAsync();

  // Return the session ID to your mobile app
  var sessionId = checkoutSession.CheckoutSession.Id;
  ```

  ```go Go theme={"system"}
  package main

  import(
  	"context"
  	gr4vygo "github.com/gr4vy/gr4vy-go"
  	"os"
  	"log"
  )

  func main() {
      ctx := context.Background()

      s := gr4vygo.New(
          gr4vygo.WithMerchantAccountID("default"),
          gr4vygo.WithSecurity(os.Getenv("GR4VY_BEARER_AUTH")),
      )

      checkoutSession, err := s.CheckoutSessions.Create(ctx, nil)
      if err != nil {
          log.Fatal(err)
      }
      if checkoutSession != nil {
          // Return the session ID to your mobile app
          log.Printf("Session ID: %s", checkoutSession.CheckoutSession.ID)
      }
  }
  ```

  ```java Java theme={"system"}
  import com.gr4vy.sdk.Gr4vy;
  import com.gr4vy.sdk.models.operations.CreateCheckoutSessionResponse;
  import java.lang.Exception;

  public class Application {
      public static void main(String[] args) throws Exception {
          Gr4vy sdk = Gr4vy.builder()
                  .merchantAccountId("default")
                  .bearerAuth("<YOUR_BEARER_TOKEN_HERE>")
              .build();

          CreateCheckoutSessionResponse res = sdk.checkoutSessions().create()
              .call();

          if (res.checkoutSession().isPresent()) {
              // Return the session ID to your mobile app
              String sessionId = res.checkoutSession().get().id();
              System.out.println("Session ID: " + sessionId);
          }
      }
  }
  ```

  ```php PHP theme={"system"}
  declare(strict_types=1);

  require 'vendor/autoload.php';

  use Gr4vy;

  $sdk = Gr4vy\SDK::builder()
      ->setMerchantAccountId('default')
      ->setSecurity('<YOUR_BEARER_TOKEN_HERE>')
      ->build();

  $response = $sdk->checkoutSessions->create();

  if ($response->checkoutSession !== null) {
      // Return the session ID to your mobile app
      echo "Session ID: " . $response->checkoutSession->id;
  }
  ```

  ```python Python theme={"system"}
  from gr4vy import Gr4vy
  import os

  with Gr4vy(
      merchant_account_id="default",
      bearer_auth=os.getenv("GR4VY_BEARER_AUTH", ""),
  ) as g_client:
      # Create an empty checkout session
      checkout_session = g_client.checkout_sessions.create()
      # Return the session ID to your mobile app
      print(checkout_session.id)
  ```

  ```ts TypeScript theme={"system"}
  import { Gr4vy } from '@gr4vy/sdk'

  const gr4vy = new Gr4vy({
      gr4vyId: 'your-gr4vy-id',
      privateKey: 'your-private-key',
      environment: 'sandbox',
  })

  async function createCheckoutSession() {
      const checkoutSession = await gr4vy.checkoutSessions.create()
      // Return the session ID to your mobile app
      console.log(checkoutSession.id)
  }

  createCheckoutSession()
  ```
</CodeGroup>

Pass this session ID to your mobile app so it can be used in the next step.

### 2. Initialize the SDK

In your mobile app, initialize the SDK with your Gr4vy ID and the correct environment. Then use your own UI components to collect the card number, expiry date, and CVV.

<CodeGroup>
  ```swift Swift (iOS) theme={"system"}
  import Gr4vy

  let gr4vy = Gr4vy(
      gr4vyId: "your-gr4vy-id",
      environment: .sandbox
  )

  ```

  ```kotlin Kotlin (Android) theme={"system"}
  import com.gr4vy.Gr4vy
  import com.gr4vy.models.Gr4vyConfig
  import com.gr4vy.models.Environment

  val config = Gr4vyConfig(
      gr4vyId = "your-gr4vy-id",
      environment = Environment.SANDBOX
  )
  val gr4vy = Gr4vy(config)
  ```
</CodeGroup>

### 3. Vault via SDK

Use the `tokenize` method to send the card details to Gr4vy. In this basic flow, set the `authenticate` parameter to `false` to skip the 3DS process.

<CodeGroup>
  ```swift Swift (iOS) theme={"system"}
  // Create card data
  let cardData = Gr4vyCardData(
      paymentMethod: .card(CardPaymentMethod(
          number: "4111111111111111",
          expirationDate: "12/25",
          securityCode: "123"
      ))
  )

  // Tokenize card data into checkout session
  do {
      try await gr4vy.tokenize(
          checkoutSessionId: "session_123",
          cardData: cardData
      )
      print("Payment method tokenization complete")
  } catch {
      print("Error tokenizing payment method: \(error)")
  }

  // Completion handler
  gr4vy.tokenize(
      checkoutSessionId: "session_123",
      cardData: cardData
  ) { result in
      switch result {
      case .success:
          print("Payment method tokenization complete")
      case .failure(let error):
          print("Error tokenizing payment method: \(error)")
      }
  }
  ```

  ```kotlin Kotlin (Android) theme={"system"}
  // Create card data
  val cardData = Gr4vyCardData(
      paymentMethod = Gr4vyPaymentMethod.Card(
          number = "4111111111111111",
          expirationDate = "12/25",
          securityCode = "123"
      )
  )

  // Tokenize card data into checkout session (suspend function)
  lifecycleScope.launch {
      try {
          val response = gr4vy.tokenize(
              checkoutSessionId = "session_123",
              cardData = Gr4vyCheckoutSessionRequest(paymentMethod = cardData.paymentMethod)
          )
          println("Payment method tokenized successfully: ${response.data.status}")
      } catch (error: Gr4vyError) {
          println("Error tokenizing payment method: $error")
      }
  }

  // Callback version
  gr4vy.tokenize(
      checkoutSessionId = "session_123",
      cardData = Gr4vyCheckoutSessionRequest(paymentMethod = cardData.paymentMethod)
  ) { result ->
      when {
          result.isSuccess -> {
              val response = result.getOrNull()
              println("Payment method tokenized successfully: ${response?.data?.status}")
          }
          result.isFailure -> {
              println("Error tokenizing payment method: ${result.exceptionOrNull()}")
          }
      }
  }
  ```
</CodeGroup>

### 4. Process payment

Once the SDK returns a success result, your backend can use that
`checkout_session_id` to create a transaction. Since 3DS was skipped, this can be processed as a standard non-3DS transaction.

```json theme={"system"}
POST /transactions
{

    "amount": 1800,
    "currency": "EUR",
    "country": "DE",
    "intent": "capture",
    "payment_method": {
        "method": "checkout-session",
        "id": "[checkout-session-id]"
    },
    ...
}
```
