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

# Generating tokens for authentication

Before adding the SDK to the iOS app, create a client
token that can be used to authenticate the transaction.

## Install a server-side SDK

Use the package manager in the preferred programming language to install the
server-side SDK. Token generation can only be done server side and doing this client side is not recommended
as it exposes the API key to customers.

<CodeGroup>
  ```sh C# theme={"system"}
  dotnet add package Gr4vy
  ```

  ```sh Go theme={"system"}
  go get github.com/gr4vy/gr4vy-go
  ```

  ```sh Java theme={"system"}
  # Please check for the latest version
  implementation 'com.gr4vy:sdk:1.0.0'
  ```

  ```sh PHP theme={"system"}
  composer require "gr4vy/gr4vy-php"
  ```

  ```sh Python theme={"system"}
  pip install gr4vy
  ```

  ```sh TypeScript theme={"system"}
  npm install @gr4vy/sdk
  # or: yarn add @gr4vy/sdk
  ```
</CodeGroup>

<Note>
  Please always check and install the [latest release](/guides/get-started#sdks-and-plugins) of the preferred SDK.
</Note>

## Initialize the SDK client

Next, initialize the SDK with the ID of the instance and the private key.

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

  // Loaded the key from a file, env variable, 
  // or anywhere else
  var privateKey = "..."; 

  var sdk = new Gr4vySDK(
      id: "example",
      server: SDKConfig.Server.Sandbox,
      bearerAuthSource: Auth.WithToken(privateKey),
      merchantAccountId: "default"
  );
  ```

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

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

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

  	privateKey := "...." // Private key loaded from disk or env var
  	withToken := gr4vy.WithToken(privateKey, []JWTScope{ReadAll, WriteAll}, 60)

  	s := gr4vy.New(
  		gr4vy.WithID("example"),
  		gr4vy.WithServer(gr4vy.ServerSandbox),
  		gr4vy.WithSecuritySource(withToken),
  		gr4vy.WithMerchantAccountID("default"),
  	)
  }
  ```

  ```java Java theme={"system"}
  package hello.world;

  import com.gr4vy.sdk.BearerSecuritySource;
  import com.gr4vy.sdk.Gr4vy;
  import com.gr4vy.sdk.Gr4vy.AvailableServers;
  import com.gr4vy.sdk.models.components.AccountUpdaterJobCreate;
  import com.gr4vy.sdk.models.errors.*;
  import com.gr4vy.sdk.models.operations.ListTransactionsRequest;
  import java.lang.Exception;
  import java.util.List;

  public class Application {

      public static void main(String[] args) throws Exception {

          String privateKey = "-----BEGIN PRIVATE KEY-----\n...."; // a valid private key

          Gr4vy sdk = Gr4vy.builder()
                  .id("example")
                  .server(AvailableServers.SANDBOX)
                  .merchantAccountId("default")
                  .securitySource(new BearerSecuritySource.Builder(privateKey).build())
              .build();
      }
  }
  ```

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

  require 'vendor/autoload.php';

  use Gr4vy;
  use Gr4vy\Auth;

  // Loaded the key from a file, env variable, 
  // or anywhere else
  $privateKey = "..."; 

  $sdk = Gr4vy\SDK::builder()
      ->setId('example')
      ->setServer('sandbox')
      ->setSecuritySource(Auth::withToken($privateKey))
      ->setMerchantAccountId('default')
      ->build();
  ```

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

  client = Gr4vy(
      id="example",
      server="production",
      merchant_account_id="default",
      bearer_auth=auth.with_token(open("./private_key.pem").read())
  )
  ```

  ```ts TypeScript theme={"system"}
  import fs from "fs";
  import { Gr4vy, withToken } from "@gr4vy/sdk";

  const gr4vy = new Gr4vy({
      server: "sandbox",
      id: "example",
      bearerAuth: withToken({
        privateKey: fs.readFileSync("private_key.pem", "utf8"),
      }),
  });
  ```
</CodeGroup>

<Note>
  The instance ID is the unique identifier for the deployment of the system and is included in every API call.
  Together with the environment (sandbox or production) it is used to connect to the right APIs, as well as dashboard.
</Note>

## Generate a token

The next step is to create a new token for frontend authentication. The SDK comes with
a helper function for exactly that purpose. It requires an amount and currency
for the transaction to be created and additionally accepts either the ID of a buyer
or an external identifier for a buyer to link the transaction to.

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

  // Loaded the key from a file, env variable, 
  // or anywhere else
  var privateKey = "..."; 

  var sdk = new Gr4vySDK(
      id: "example",
      server: SDKConfig.Server.Sandbox,
      bearerAuthSource: Auth.WithToken(privateKey),
      merchantAccountId: "default"
  );

  var checkoutSession = await sdk.CheckoutSessions.CreateAsync()

  auth.get_embed_token(
      privatekey,
      embedParams=new Dictionary<string, object>
      {
          ["amount"]: 1299,
          ["currency"]: 'USD',
          ["buyer_external_identifier"]: 'user-1234',
      },
      checkoutSessionId=checkoutSession.ID
  )
  ```

  ```go Go theme={"system"}
  import (
  	gr4vy "github.com/gr4vy/gr4vy-go"
  	"log"
  	"os"
  )

  privateKey := "...." // Private key loaded from disk or env var

  token, err := GetEmbedToken(privateKey, nil, "")
  if err != nil {
  	log.Fatal(err)
  }
  ```

  ```java Java theme={"system"}
  import com.gr4vy.sdk.Auth;

  Map<String, Object> embedParams = ...; // a map of extra params to use with Embed
  String privateKey = "-----BEGIN PRIVATE KEY-----\n...."; // a valid private key
  String checkoutSessionId = ""; // a valid ID for a checkout session
  String token = Auth.getEmbedToken(privateKey, embedParams, checkoutSessionId);
  ```

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

  require 'vendor/autoload.php';

  use Gr4vy;
  use Gr4vy\Auth;

  // Loaded the key from a file, env variable, 
  // or anywhere else
  $privateKey = "..."; 

  $sdk = Gr4vy\SDK::builder()
      ->setId('example')
      ->setServer('sandbox')
      ->setSecuritySource(Auth::withToken($privateKey))
      ->setMerchantAccountId('default')
      ->build();
  ```

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

  private_key = open("./private_key.pem").read()

  g_client = Gr4vy(
      id="example",
      server="production",
      merchant_account_id="default",
      bearer_auth=auth.with_token(private_key)
  )

  checkout_session = g_client.checkout_sessions.create()

  auth.get_embed_token(
      privatekey,
      embed_params={
          "amount": 1299,
          "currency": 'USD',
          "buyer_external_identifier": 'user-1234',
      },
      checkout_session_id=checkout_session.id
  )
  ```

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

  async function run() {
      const privateKey = fs.readFileSync("private_key.pem", "utf8")

      const gr4vy = new Gr4vy({
          server: "sandbox",
          id: "example",
          bearerAuth: withToken({ privateKey }),
      });

      const checkoutSession = await gr4vy.checkoutSessions.create()

      const token = await getEmbedToken({ 
        privateKey,
        checkoutSessionId: checkoutSession.id,
        embedParams: {
          amount: 1299,
          currency: 'USD',
          buyerExternalIdentifier: 'user-1234',
        }
      });

      console.log(token);
  }

  run();
  ```
</CodeGroup>

This token can now be served to the frontend where it is used by the SDK.

If generating the client token without using a
server-side SDK is preferred, then please read the guide on [manually generating a JWT](/guides/api/authentication#manual-jwt).

## Checkout sessions

Passing a [checkout session](/reference/checkout-sessions/new-checkout-session) ID to the Embed token function is recommended.
This ID can be used to help identify multiple transaction attempts. This is useful to identify if one or more failed/declined
transactions eventually result in a successful transaction. Checkout sessions can also store `cart_items`, `metadata`, airline data, and more,
removing the need to pass these values on the transaction request.

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


  var res = await sdk.CheckoutSessions.CreateAsync(checkoutSessionCreate: new CheckoutSessionCreate() {
      CartItems = new List<CartItem>() {
          new CartItem() {
              Name = "GoPro HD",
              Quantity = 2,
              UnitAmount = 1299,
              DiscountAmount = 0,
              TaxAmount = 0,
              ExternalIdentifier = "goprohd",
              Sku = "GPHD1078",
              ProductUrl = "https://example.com/catalog/go-pro-hd",
              ImageUrl = "https://example.com/images/go-pro-hd.jpg",
              Categories = new List<string>() {
                  "camera",
                  "travel",
                  "gear",
              },
              ProductType = "physical",
              SellerCountry = "GB",
          },
          new CartItem() {
              Name = "GoPro HD",
              Quantity = 2,
              UnitAmount = 1299,
              DiscountAmount = 0,
              TaxAmount = 0,
              ExternalIdentifier = "goprohd",
              Sku = "GPHD1078",
              ProductUrl = "https://example.com/catalog/go-pro-hd",
              ImageUrl = "https://example.com/images/go-pro-hd.jpg",
              Categories = new List<string>() {
                  "camera",
                  "travel",
                  "gear",
              },
              ProductType = "physical",
              SellerCountry = "GB",
          },
          new CartItem() {
              Name = "GoPro HD",
              Quantity = 2,
              UnitAmount = 1299,
              DiscountAmount = 0,
              TaxAmount = 0,
              ExternalIdentifier = "goprohd",
              Sku = "GPHD1078",
              ProductUrl = "https://example.com/catalog/go-pro-hd",
              ImageUrl = "https://example.com/images/go-pro-hd.jpg",
              Categories = new List<string>() {
                  "camera",
                  "travel",
                  "gear",
              },
              ProductType = "physical",
              SellerCountry = "US",
          },
      },
      Metadata = new Dictionary<string, string>() {
          { "cohort", "cohort-a" },
          { "order_id", "order-12345" },
      },
      Buyer = new GuestBuyerInput() {
          DisplayName = "John Doe",
          ExternalIdentifier = "buyer-12345",
          BillingDetails = new BillingDetailsInput() {
              FirstName = "John",
              LastName = "Doe",
              EmailAddress = "john@example.com",
              PhoneNumber = "+1234567890",
              Address = new Address() {
                  City = "San Jose",
                  Country = "US",
                  PostalCode = "94560",
                  State = "California",
                  StateCode = "US-CA",
                  HouseNumberOrName = "10",
                  Line1 = "Stafford Apartments",
                  Line2 = "29th Street",
                  Organization = "Gr4vy",
              },
              TaxId = new TaxId() {
                  Value = "12345678931",
                  Kind = "ar.cuit",
              },
          },
          ShippingDetails = new ShippingDetailsCreate() {
              FirstName = "John",
              LastName = "Doe",
              EmailAddress = "john@example.com",
              PhoneNumber = "+1234567890",
              Address = new Address() {
                  City = "San Jose",
                  Country = "US",
                  PostalCode = "94560",
                  State = "California",
                  StateCode = "US-CA",
                  HouseNumberOrName = "10",
                  Line1 = "Stafford Apartments",
                  Line2 = "29th Street",
                  Organization = "Gr4vy",
              },
          },
      },
  });

  // handle response
  ```

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

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

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

      // Init SDK

      res, err := s.CheckoutSessions.Create(ctx, &components.CheckoutSessionCreate{
          CartItems: []components.CartItem{
              components.CartItem{
                  Name: "GoPro HD",
                  Quantity: 2,
                  UnitAmount: 1299,
                  DiscountAmount: gr4vygo.Int64(0),
                  TaxAmount: gr4vygo.Int64(0),
                  ExternalIdentifier: gr4vygo.String("goprohd"),
                  Sku: gr4vygo.String("GPHD1078"),
                  ProductURL: gr4vygo.String("https://example.com/catalog/go-pro-hd"),
                  ImageURL: gr4vygo.String("https://example.com/images/go-pro-hd.jpg"),
                  Categories: []string{
                      "camera",
                      "travel",
                      "gear",
                  },
                  ProductType: components.ProductTypePhysical.ToPointer(),
                  SellerCountry: gr4vygo.String("US"),
              },
              components.CartItem{
                  Name: "GoPro HD",
                  Quantity: 2,
                  UnitAmount: 1299,
                  DiscountAmount: gr4vygo.Int64(0),
                  TaxAmount: gr4vygo.Int64(0),
                  ExternalIdentifier: gr4vygo.String("goprohd"),
                  Sku: gr4vygo.String("GPHD1078"),
                  ProductURL: gr4vygo.String("https://example.com/catalog/go-pro-hd"),
                  ImageURL: gr4vygo.String("https://example.com/images/go-pro-hd.jpg"),
                  Categories: []string{
                      "camera",
                      "travel",
                      "gear",
                  },
                  ProductType: components.ProductTypePhysical.ToPointer(),
                  SellerCountry: gr4vygo.String("US"),
              },
          },
          Metadata: map[string]string{
              "cohort": "cohort-a",
              "order_id": "order-12345",
          },
          Buyer: nil,
      })
      if err != nil {
          log.Fatal(err)
      }
      if res != nil {
          // handle response
      }
  }
  ```

  ```java Java theme={"system"}
  package hello.world;

  import com.gr4vy.sdk.Gr4vy;
  import com.gr4vy.sdk.models.components.*;
  import com.gr4vy.sdk.models.errors.*;
  import com.gr4vy.sdk.models.operations.CreateCheckoutSessionResponse;
  import java.lang.Exception;
  import java.time.LocalDate;
  import java.time.OffsetDateTime;
  import java.util.List;
  import java.util.Map;
  import org.openapitools.jackson.nullable.JsonNullable;

  public class Application {

      public static void main(String[] args) throws Exception {

          // Init SDK

          CreateCheckoutSessionResponse res = sdk.checkoutSessions().create()
                  .checkoutSessionCreate(CheckoutSessionCreate.builder()
                      .cartItems(List.of(
                          CartItem.builder()
                              .name("GoPro HD")
                              .quantity(2L)
                              .unitAmount(1299L)
                              .discountAmount(0L)
                              .taxAmount(0L)
                              .externalIdentifier("goprohd")
                              .sku("GPHD1078")
                              .productUrl("https://example.com/catalog/go-pro-hd")
                              .imageUrl("https://example.com/images/go-pro-hd.jpg")
                              .categories(List.of(
                                  "camera",
                                  "travel",
                                  "gear"))
                              .productType(ProductType.PHYSICAL)
                              .sellerCountry("US")
                              .build(),
                          CartItem.builder()
                              .name("GoPro HD")
                              .quantity(2L)
                              .unitAmount(1299L)
                              .discountAmount(0L)
                              .taxAmount(0L)
                              .externalIdentifier("goprohd")
                              .sku("GPHD1078")
                              .productUrl("https://example.com/catalog/go-pro-hd")
                              .imageUrl("https://example.com/images/go-pro-hd.jpg")
                              .categories(List.of(
                                  "camera",
                                  "travel",
                                  "gear"))
                              .productType(ProductType.PHYSICAL)
                              .sellerCountry("US")
                              .build()))
                      .metadata(Map.ofEntries(
                          Map.entry("cohort", "cohort-a"),
                          Map.entry("order_id", "order-12345")))
                      .buyer(JsonNullable.of(null))
                      .build())
                  .call();

          if (res.checkoutSession().isPresent()) {
              // handle response
          }
      }
  }
  ```

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

  require 'vendor/autoload.php';

  use Brick\DateTime\LocalDate;
  use Gr4vy;
  use Gr4vy\Utils;

  // Init SDK

  $checkoutSessionCreate = new Gr4vy\CheckoutSessionCreate(
      cartItems: [
          new Gr4vy\CartItem(
              name: 'GoPro HD',
              quantity: 2,
              unitAmount: 1299,
              discountAmount: 0,
              taxAmount: 0,
              externalIdentifier: 'goprohd',
              sku: 'GPHD1078',
              productUrl: 'https://example.com/catalog/go-pro-hd',
              imageUrl: 'https://example.com/images/go-pro-hd.jpg',
              categories: [
                  'camera',
                  'travel',
                  'gear',
              ],
              productType: 'physical',
              sellerCountry: 'US',
          ),
          new Gr4vy\CartItem(
              name: 'GoPro HD',
              quantity: 2,
              unitAmount: 1299,
              discountAmount: 0,
              taxAmount: 0,
              externalIdentifier: 'goprohd',
              sku: 'GPHD1078',
              productUrl: 'https://example.com/catalog/go-pro-hd',
              imageUrl: 'https://example.com/images/go-pro-hd.jpg',
              categories: [
                  'camera',
                  'travel',
                  'gear',
              ],
              productType: 'physical',
              sellerCountry: 'US',
          ),
      ],
      metadata: [
          'cohort' => 'cohort-a',
          'order_id' => 'order-12345',
      ],
      buyer: new Gr4vy\GuestBuyerInput(
          displayName: 'John Doe',
          externalIdentifier: 'buyer-12345',
          billingDetails: new Gr4vy\BillingDetailsInput(
              firstName: 'John',
              lastName: 'Doe',
              emailAddress: 'john@example.com',
              phoneNumber: '+1234567890',
              address: new Gr4vy\Address(
                  city: 'San Jose',
                  country: 'US',
                  postalCode: '94560',
                  state: 'California',
                  stateCode: 'US-CA',
                  houseNumberOrName: '10',
                  line1: 'Stafford Apartments',
                  line2: '29th Street',
                  organization: 'Gr4vy',
              ),
              taxId: new Gr4vy\TaxId(
                  value: '12345678931',
                  kind: 'my.frp',
              ),
          ),
          shippingDetails: new Gr4vy\ShippingDetailsCreate(
              firstName: 'John',
              lastName: 'Doe',
              emailAddress: 'john@example.com',
              phoneNumber: '+1234567890',
              address: null,
          ),
      ),
  );

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

  if ($response->checkoutSession !== null) {
      // handle response
  }
  ```

  ```python Python theme={"system"}
  from datetime import date
  from gr4vy import Gr4vy, models
  from gr4vy.utils import parse_datetime
  import os

  # Init SDK

  res = g_client.checkout_sessions.create(checkout_session_create=models.CheckoutSessionCreate(
      cart_items=[
          models.CartItem(
              name="GoPro HD",
              quantity=2,
              unit_amount=1299,
              discount_amount=0,
              tax_amount=0,
              external_identifier="goprohd",
              sku="GPHD1078",
              product_url="https://example.com/catalog/go-pro-hd",
              image_url="https://example.com/images/go-pro-hd.jpg",
              categories=[
                  "camera",
                  "travel",
                  "gear",
              ],
              product_type="physical",
              seller_country="GB",
          ),
          models.CartItem(
              name="GoPro HD",
              quantity=2,
              unit_amount=1299,
              discount_amount=0,
              tax_amount=0,
              external_identifier="goprohd",
              sku="GPHD1078",
              product_url="https://example.com/catalog/go-pro-hd",
              image_url="https://example.com/images/go-pro-hd.jpg",
              categories=[
                  "camera",
                  "travel",
                  "gear",
              ],
              product_type="physical",
              seller_country="GB",
          ),
          models.CartItem(
              name="GoPro HD",
              quantity=2,
              unit_amount=1299,
              discount_amount=0,
              tax_amount=0,
              external_identifier="goprohd",
              sku="GPHD1078",
              product_url="https://example.com/catalog/go-pro-hd",
              image_url="https://example.com/images/go-pro-hd.jpg",
              categories=[
                  "camera",
                  "travel",
                  "gear",
              ],
              product_type="physical",
              seller_country="GB",
          ),
      ],
      metadata={
          "cohort": "cohort-a",
          "order_id": "order-12345",
      },
      buyer=models.GuestBuyerInput(
          display_name="John Doe",
          external_identifier="buyer-12345",
          billing_details=models.BillingDetailsInput(
              first_name="John",
              last_name="Doe",
              email_address="john@example.com",
              phone_number="+1234567890",
              address=models.Address(
                  city="San Jose",
                  country="US",
                  postal_code="94560",
                  state="California",
                  state_code="US-CA",
                  house_number_or_name="10",
                  line1="Stafford Apartments",
                  line2="29th Street",
                  organization="Gr4vy",
              ),
              tax_id=models.TaxID(
                  value="12345678931",
                  kind="ar.cuit",
              ),
          ),
          shipping_details=models.ShippingDetailsCreate(
              first_name="John",
              last_name="Doe",
              email_address="john@example.com",
              phone_number="+1234567890",
              address=models.Address(
                  city="San Jose",
                  country="US",
                  postal_code="94560",
                  state="California",
                  state_code="US-CA",
                  house_number_or_name="10",
                  line1="Stafford Apartments",
                  line2="29th Street",
                  organization="Gr4vy",
              ),
          ),
      ),
  ))

  # Handle response
  print(res)
  ```

  ```ts Typescript theme={"system"}
  const result = await gr4vy.checkoutSessions.create();
  ```
</CodeGroup>

<Warning>
  **Checkout session expiry**

  Checkout sessions expire after 1 hour by default. Updating a checkout session does not extend the time.
</Warning>

## Loading token

The token needs to be shared with the iOS app via a custom API.
Creating a token per checkout and only using a token for a short
amount of time is recommended.

## Summary

In this step:

* Created a signed JWT token using a server-side SDK.
* Shared the JWT with the iOS app
