Generate a Client Token

Get an API Key

You require an API Key to talk with our APIs. Head to the Developers area to manage your API keys.

When your account is created, we will also create an API token automatically. You can use this API key to get started.

Never share your API Key, only your backend should have access to it.

Find out more about API Keys in our API Reference

Generate a Client Session

client token A client session is the starting point for integrating payments at Primer. You can attach all the metadata associated with the order to the client session, and generate a clientToken, a temporary key used to initialize Universal Checkout.

The information you include in the client session is used in the Dashboard to conditionally route payments with Workflows, and activate payment methods and other features in Universal Checkout, so pass as much information as you can.

The X-Api-Version specifies the API version information. Earlier, this was supposed to be a date. For example, 2021-10-19. This has changed post API version v2 which was represented by 2021-09-27 date. Starting API version v2.1, the X-Api-Version needs to provide the API version as v2.1. Depending upon the API version specified in the client-session request, your client-session will be processed accordingly with requisite features and options that are available for that version.

See API Reference Changelog for details.

Here is how the client session request to the Primer API should look like:

# Generate a client token with cURLcurl --location --request \  POST '' \  --header 'X-Api-Key: <YOUR_API_KEY>' \  --header 'X-Api-Version: 2021-10-19' \  --header 'Content-Type: application/json'  --data '{    "orderId": "<YOUR_ORDER_ID>",    "currencyCode": "GBP",    "amount": 1200,    "customerId": "<YOUR_CUSTOMER_ID>"    "order": { "countryCode": "GB" }  }'

Example Response

{  "clientToken": "<THE_CLIENT_TOKEN>",  "clientTokenExpirationDate": "2021-08-12T16:14:08.578695",  "orderId": "<YOUR_ORDER_ID>",  "currencyCode": "GBP",  "amount": 1200,  "customerId": "<YOUR_CUSTOMER_ID>",  "metadata": {},  "warnings": []}
Make sure to pass all the information required by the payment methods and features activated on your Dashboard.

As a rule of thumb, pass as much information as you can when creating the client session. As a minimum, make sure to pass:

  • orderId
  • currencyCode
  • amount
  • order.countryCode

The clientToken is a key concept within Primer. You may receive a client token from various places but as long as you pass it to the SDK, Universal Checkout knows where to start/resume the flow.

Set up the Universal Checkout

Step 1. Install the SDK

With CocoaPods

The iOS SDK is available with Cocoapods. Just add the PrimerSDK pod and run pod install.

target 'MyApp' do  # Other pods...   # Add this to your Podfile  pod 'PrimerSDK' # Add this lineend

For specific versions of the SDK, please refer to the changelog.

With Swift Package Manager

The Swift Package Manager is a tool for automating the distribution of Swift code and is integrated into Xcode. In order to add PrimerSDK with Swift Package Manager;

  1. 1
    Select your project, and then navigate to Package Dependencies
  2. 2
    Click on the + button at the bottom-left of the Packages section
  3. 3
  4. 4
    Press Add Package
  5. 5
    Let Xcode download the package and set everything up

spm 3

Step 2. Initialize the SDK

Import the Primer SDK and set its delegate as shown in the following example:

import PrimerSDK class MyViewController: UIViewController {     override func viewDidLoad() {        super.viewDidLoad()         // Initialize the SDK with the default settings.        Primer.shared.delegate = self    }} extension MyViewController: PrimerDelegate {    // ...}

Step 3. Add the Client Token Callback

When showing Universal Checkout, the SDK first asks you to retrieve a client session token by calling clientTokenCallback on the delegate. Create your client session as described above.

In the meantime, a loading indicator is displayed.

extension MyViewController: PrimerDelegate {     func clientTokenCallback(_ completion: @escaping (String?, Error?) -> Void) {        // Request a client session token from your backend        requestClientSession(completion: { (clientToken, err) in            completion(clientToken, err)        })    }}

Step 4. Show Universal Checkout

When ready, display Universal Checkout.

class MyViewController: UIViewController {     func startUniversalCheckout() {        Primer.shared.showUniversalCheckout(on: self)    } }

Step 5. Handle Callbacks for Creating and Resuming Payments

Handling onTokenizeSuccess callback

  • When a customer submits payment data, the credentials are tokenized and you'll receive a payment method token in onTokenizeSuccess(_:resumeHandler:)

  • Send the payment method token to your server to create a payment with the Payments API. The checkout stays in a loading state in the meantime.

  • Call the resumeHandler's handle(error:) to show an error message, or handleSuccess() to show a success message.

  • In case you receive a requiredAction with a new clientToken, call the resumeHandler's handle(newClientToken:) function.

Handling onResumeSuccess callback

  • The SDK will continue and you'll get notified of the resume result in one of the following delegate functions: onResumeSuccess(_:resumeHandler:) or onResumeError(_:).

  • If the onResumeSuccess(_:resumeHandler:) is called, use the resumeToken to resume your payment.

extension MyViewController: PrimerDelegate {     func onTokenizeSuccess(_ paymentMethodToken: PaymentMethodToken, resumeHandler: ResumeHandlerProtocol) {        createPayment(with: paymentMethodToken) { (res, err) in            if let err = err {                resumeHandler.handle(error: err)            } else if let res = res {                guard let requiredAction = res["requiredAction"] as? [String: Any],                    let clientToken = requiredAction["clientToken"] as? String                else {                    resumeHandler.handleSuccess()                    return                }                 resumeHandler.handle(newClientToken: clientToken)            }        }    }     func onResumeSuccess(_ resumeToken: String, resumeHandler: ResumeHandlerProtocol) {        // Resume the payment with the resumeToken.        resumePayment(with: resumeToken) { (res, err) in              if let err = err {                  resumeHandler.handle(error: err)              } else if let res = res {                  resumeHandler.handleSuccess()              }        }    }     func onResumeError(_ error: Error) {        // Handle the error    }}

Step 6: Handle callback for updating the client session

As the customer interacts with the UI, Universal Checkout fires "client session actions" via onClientSessionActions(:resumeHandler:). Forward these to your server to update the client session with the Client Session Actions endpoint.

A new client token will be provided. Pass it back to the SDK using the resumeHandler's handle(newClientToken:) to refresh Universal Checkout and continue the flow.

extension MyViewController: PrimerDelegate {     func onClientSessionActions(_ actions: [ClientSession.Action], resumeHandler: ResumeHandlerProtocol?) {        // Send the client session actions to your backend and update        // your client session.        requestClientSessionWithActions(actions) { (clientToken, err) in            if let err = err {                resumeHandler?.handle(error: err)            } else if let clientToken = clientToken {                resumeHandler?.handle(newClientToken: clientToken)            }        }    } }
// ClientSession.Actionvar type: Stringvar params: [String: Any]?

Create a Payment

Once you've received a paymentMethodToken from Universal Checkout, use it to create a payment.

payment creation

Payment request POST/payments

curl --location --request \    POST '' \    --header 'X-Api-Key: <YOUR_API_KEY>' \    --header 'X-Api-Version: 2021-09-27' \    --header 'X-Idempotency-Key: <YOUR_IDEMPOTENCY_KEY>' \    --data '{        "orderId": "<YOUR_ORDER_ID>",        "amount": 800,        "currencyCode": "GBP",        "paymentMethodToken": "<PAYMENT_METHOD_TOKEN>",    }'
Required fields
  1. orderId
your unique order ID
  1. amount

payment amount
example in currency (USD) with minor units: 700 for \$7.00
example in currency (JPY) without minor units: 100 for ¥100

  1. currencyCode

ISO 4217 three-letter currency code: USD for US dollars

  1. paymentMethodToken

paymentMethodToken obtained from Universal Checkout or the Payment Methods API


Data passed in the payment request overwrites any data passed in the clientToken.

See more request options in the API Reference.

Payment response

The payment request is synchronous. It will trigger a Workflow and return a payment object containing, among other things, the payment status. In circumstances where the payment flow is asynchronous, you may receive a status of PENDING.

// 2XX response {    "id": "slklmjh4",    "status": "AUTHORIZED",    "orderId": "<YOUR_ORDER_ID>",    "currencyCode": "GBP",    "amount": 800,    "paymentMethodToken": "<PAYMENT_METHOD_TOKEN>"     // ... additional attributes for the Payment object    // ... see API ref}

Did It Work?

If everything went well, you should be able to see the payment you just created on your dashboard under the Payments menu. Payment list

To receive updates about the status of your payments you’ll need to listen to webhooks. Head to the Developers area to setup a webhook for PAYMENT.STATUS event.

If you are not yet ready to receive webhooks, you can use to test your implementation.