Skip to main content
Before you add the SDK to your iOS app you will need to create a client token that can be used to authenticate the transaction.

Install a server-side SDK

Use the package manager in your preferred programming language to install our server-side SDK. Token generation can only be done server side and we do not recommend doing this client side as it will expose your API key to your customers.
dotnet add package Gr4vy
go get github.com/gr4vy/gr4vy-go
# Please check for the latest version
implementation 'com.gr4vy:sdk:1.0.0'
composer require "gr4vy/gr4vy-php"
pip install gr4vy
npm install @gr4vy/sdk
# or: yarn add @gr4vy/sdk
Please always check and install the latest release of your preferred SDK.

Initialize the SDK client

Next, initialize the SDK with the ID of your instance and the private key.
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: "mattilda",
    server: SDKConfig.Server.Sandbox,
    bearerAuthSource: Auth.WithToken(privateKey),
    merchantAccountId: "example"
);
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("mattilda"),
		gr4vy.WithServer(gr4vy.ServerSandbox),
		gr4vy.WithSecuritySource(withToken),
		gr4vy.WithMerchantAccountID("example"),
	)
}
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("mattilda")
                .server(AvailableServers.SANDBOX)
                .merchantAccountId("example")
                .securitySource(new BearerSecuritySource.Builder(privateKey).build())
            .build();
    }
}
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('mattilda')
    ->setServer('sandbox')
    ->setSecuritySource(Auth::withToken($privateKey))
    ->setMerchantAccountId('example')
    ->build();
from gr4vy import Gr4vy, auth
import os

client = Gr4vy(
    id="mattilda",
    server="production",
    merchant_account_id="example",
    bearer_auth=auth.with_token(open("./private_key.pem").read())
)
import fs from "fs";
import { Gr4vy, withToken } from "@gr4vy/sdk";

const gr4vy = new Gr4vy({
    server: "sandbox",
    id: "mattilda",
    bearerAuth: withToken({
      privateKey: fs.readFileSync("private_key.pem", "utf8"),
    }),
});

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 your external identifier for a buyer to link the transaction to.
using Gr4vy;

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

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

var checkoutSession = await sdk.CheckoutSessions.CreateAsync()

auth.get_embed_token(
    privatekey,
    embedParams=new Dictionary<string, object>
    {
        ["amount"]: 1299,
        ["currency"]: 'MXN',
        ["buyer_external_identifier"]: 'user-1234',
    },
    checkoutSessionId=checkoutSession.ID
)
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)
}
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);
declare(strict_types=1);

require 'vendor/autoload.php';

use Gr4vy\SDK;
use Gr4vy\Auth;

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

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

$checkoutSessionCreate = new Gr4vy\CheckoutSessionCreate();
$response = $sdk->checkoutSessions->create();

$embed = [
  'amount' => 1299,
  'currency' => 'MXN',
  'buyerExternalIdentifier' => 'user-1234'
];

$token = Auth::getEmbedToken(
  privateKey: $privateKey,
  checkoutSessionId: $response->checkoutSession->id,
  embedParams: $embed
);
from gr4vy import Gr4vy, auth

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

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

checkout_session = g_client.checkout_sessions.create()

auth.get_embed_token(
    privatekey,
    embed_params={
        "amount": 1299,
        "currency": 'MXN',
        "buyer_external_identifier": 'user-1234',
    },
    checkout_session_id=checkout_session.id
)
import { Gr4vy, getEmbedToken } from "@gr4vy/sdk";

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

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

    const checkoutSession = await gr4vy.checkoutSessions.create()

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

    console.log(token);
}

run();
This token can now be served to the frontend where it will be used by our SDK. If you would prefer to generate the client token without using a server-side SDK, then please read our guide on manually generating a JWT.

Checkout sessions

We recommend passing a checkout session ID to the Embed token function. 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 store also store cart_items, metadata, airline data, and more, removing the need to pass these values on the transaction request.
using Gr4vy;
using Gr4vy.Models.Components;
using NodaTime;
using System;
using System.Collections.Generic;

// Init SDK

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 = "MX",
        },
        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 = "MX",
        },
        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 = "MX",
        },
    },
    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 = "MX",
                PostalCode = "94560",
                State = "California",
                StateCode = "US-CA",
                HouseNumberOrName = "10",
                Line1 = "Stafford Appartments",
                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 = "MX",
                PostalCode = "94560",
                State = "California",
                StateCode = "US-CA",
                HouseNumberOrName = "10",
                Line1 = "Stafford Appartments",
                Line2 = "29th Street",
                Organization = "Gr4vy",
            },
        },
    },
});

// handle response
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("MX"),
            },
            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("MX"),
            },
        },
        Metadata: map[string]string{
            "cohort": "cohort-a",
            "order_id": "order-12345",
        },
        Buyer: nil,
    })
    if err != nil {
        log.Fatal(err)
    }
    if res != nil {
        // handle response
    }
}
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("MX")
                            .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("MX")
                            .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
        }
    }
}
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 Appartments',
                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
}
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="MX",
        ),
        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="MX",
        ),
        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="MX",
        ),
    ],
    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="MX",
                postal_code="94560",
                state="California",
                state_code="US-CA",
                house_number_or_name="10",
                line1="Stafford Appartments",
                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="MX",
                postal_code="94560",
                state="California",
                state_code="US-CA",
                house_number_or_name="10",
                line1="Stafford Appartments",
                line2="29th Street",
                organization="Gr4vy",
            ),
        ),
    ),
))

# Handle response
print(res)
const result = await gr4vy.checkoutSessions.create();
Checkout session expiryCheckout sessions expire after 1 hour by default. Updating a checkout session will not extend the time.

Loading token in iOS

The token needs to be shared with your iOS application via your own API. We recommend you create a token per checkout and only use a token for a short amount of time.

Summary

In this step you:
  • Created a signed JWT token using a server-side SDK.
  • Shared the JWT with your iOS application