In no particular order, here are some useful recommendations when integrating the API, Embed or Secure Fields.

Associate transactions with a Buyer

A Buyer allows you to link transactions with your customer as well as send buyer-specific information such as name, email, address and tax ID, etc.

See Buyers for further details.

Set a unique reference ID for each transaction

A unique transaction reference ID helps you to link transactions to your order (see step 2). A unique reference ID can either be set as an external identifier or metadata on the transaction. This is available if you are using Embed, Secure Fields, or our API directly.

We are aware that Embed is sometimes displayed at checkout before an order is created by your system. After all, you would not want to create an order every time a customer loads a checkout page. We have introduced an onBeforeTransaction callback in Embed that can be used to set the externalIdentifier or metadata right before a transaction is created. This will allow you to create a unique reference ID just-in-time before a transaction is created by Embed.

Update the external identifier
  onBeforeTransaction: async () => {
    // Merchant could make a call to a server here to get an order ID.
    // let { orderId } = await client.getOrder()
    return { 
      externalIdentifier: orderId,

Metadata can be updated in a similar way. In the case that the metadata has been pinned you will also need to update your JWT token because the metadata may be pinned in the token.

Update the metadata
  onBeforeTransaction: async ({ metadata }) => {
    // Merchant could make a call to a server here to get an order ID.
    // let { orderId, newToken } = client.getOrder()
    return { 
      token: newToken,
      metadata: {
        orderId: orderId

Use webhooks to listen for transaction updates

We recommend you listen for updates to transactions by using webhooks. As you have set a unique reference ID (see above) you can use this to listen to webhook events, which will notify you of a transaction completing, failing, or being declined.

Please reach out to our team to set up your webhook URL.

We highly recommend you use webhooks and do not exclusively rely on any in-browser events like Embed’s transactionCreated event or onComplete callback. Because browsers are an unreliable environment this message between Embed and your system could get lost for many reasons, and so listening to webhook updates is generally considered the only fully reliable option when dealing with transaction updates.

Use idempotent requests

Sometimes transactions fail, either because of bad input or because of some kind of network or other system error. In the case of an error where the response was not received by the buyer’s browser (or your system), a transaction can be retried using a special header.

curl -i -X POST "https://api.{gr4vyId}" \
    -H "Authorization: Bearer {jwtToken}" \
    -H "Idempotency-Key: bffa9ce6-7a8a-449c-889a-65bd2ee86903" \
    -d "{...}"

The Idempotency-Key header is used to uniquely identify a transaction when retrying the same transaction after a network error or some kind of timeout. The second request will be matched using this key against the original request, and rather than creating a new transaction the original response is returned.

See Idempotent Requests for further details.

If you are using Embed then you are already using idempotent requests.

Transaction request information

Some payment methods require specific ‘non-standard’ information to process. For example, some Buy Now Pay Later (BNPL) methods require cart items to successfully process payments. Therefore to future-proof your integration we recommend integrating as much information in the transaction request as possible. This will allow you to add new additional methods of payment without having to update your integration.

Here are a few examples of optional request information to include.

  • buyer information
  • cart_items
  • shipping information
  • connection_options (where applicable)
  • payment_source
  • is_subsequent_payment
  • merchant_initiated