Integration Guide

You can connect your POS platform with Toggle to provide on-site gift card sales and redemptions to your customers. Here’s how…

Overview

Connecting your POS platform to Toggle allows your POS users to accept gift card sales on site through your POS system. A customer can present a gift card and the staff can swipe it through or key in the card number to redeem it (partial or full).

Additionally, if a customer wants to buy a gift card while they are on site, your customers can sell a gift card through the POS.

Introduction to GraphQL

The GraphQL data query language is:

  • A specification. The spec determines the validity of the schema on the API server. The schema determines the validity of client calls.
  • Strongly typed. The schema defines an API’s type system and all object relationships.
  • Introspective. A client can query the schema for details about the schema.
  • Hierarchical. The shape of a GraphQL call mirrors the shape of the JSON data it returns. Nested fields let you query for and receive only the data you specify in a single round trip.
  • An application layer. GraphQL is not a storage model or a database query language. The graph refers to graph structures defined in the schema, where nodes define objects and edges define relationships between objects. The API traverses and returns application data based on the schema definitions, independent of how the data is stored.

For more information about GraphQL, refer to the documentation provided on the official GraphQL website.

About our GraphQL schema reference

The documentation in our reference is generated from the Toggle GraphQL schema. All calls are validated and executed against the schema.

Use these docs to find out what data you can call:

Allowed operations: queries and mutations.

Schema-defined types: scalars, objects, enums, interfaces, unions, and input objects.

GraphQL libraries

It is recommend to use a GraphQL library in your application to make queries and mutations more easily. A library will handle the requests to GraphQL for you. You can find a list of libraries for each common language on GraphQL’s website.

Forming GraphQL calls

How to create your API username and password

Creation of API users is currently actioned by the Toggle support team. Please get in touch with our support team by emailing support@usetoggle.com to make a request for an API user. Please ensure you send your email from an address that has an active Toggle account, otherwise your request may be delayed.

Authenticating with GraphQL

GraphQL uses JWT tokens to authenticate API requests. To generate your token, you need to have a user account on Toggle. Once you have a user, you can make a request to the loginUser query, which will return an Authorization header containing your token. The example GraphQL query and variables are below.

query($email:String,$username:String, $password:String!){ {
 loginUser(email:$email,username:$username,password:$password) { {
    id {
  }
}

Variables:

{
   "email": "",
   "password": ""
}

If you have been issued a Username instead of an Email address to login, you would pass these variables to the query:

{
   "username": "",
   "password": ""
}

Whenever the user wants to access a protected route or resource, the user agent should send their token in the Authorization header using the Bearer schema. The content of the header should look like the following:

Authorization: Bearer 

It is worthwhile reading the introduction from JWT which summarises how JSON Web Tokens work for more information.

As the token is time limited, it will require a refresh after 60 minutes. When you make a request and the Authorization header is returned, you should start using the new token. Therefore you will need to programmatically update your token and store it securely in your system each time you retrieve a new token, using it until such time that it is refreshed.

If you are not authorised and you attempt to make a request to a protected query or mutation, the API will return JSON with errors:

{
  "errors": [
    {
      "message": "Unauthorized",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "customer_facing": false
    }
  ],
  "data": {
    "createUser": null
  }
}

The Toggle API endpoint

https://api.mytoggle.io/graphql

Communicating with GraphQL

Because GraphQL operations consist of multiline JSON, we recommend using the Explorer to make GraphQL calls. You can also use cURL or any other HTTP-speaking library.

In GraphQL, you’ll provide a JSON-encoded body whether you’re performing a query or a mutation, so the HTTP verb is POST

Discovering the API
GraphQL is introspective. This means you can query a GraphQL schema for details about itself. For introspective queries, use the HTTP verb GET.

Query __schema
to list all types defined in the schema and get details about each:

query {
  __schema {
    types {
      name
      kind
      description
      fields {
        name
      }
    }
  }
}

Query __type to get details about any type:

query {
  __type(name: "Card") {
    name
    kind
    description
    fields {
      name
    }
  }
}

The results are in JSON, so we recommend pretty-printing them for easier reading and searching.

Note: The introspection query is the only GET request you’ll run in GraphQL. If you’re passing a body, the GraphQL request method is POST, whether it’s a query or a mutation.

Toggle Terminology

Account – When a Toggle customer signs up to the Toggle platform, they create their account. An account relates to a company. A company may decide to create multiple accounts in order to run multiple web stores, for example, for each of their brands.

Address – A physical address is stored against a customer record, where the customer has provided their address for physical gift card delivery purposes.

Cards – Cards are linked with an account. A card contains the reference number, a 19 digit IIN (Issuer Identification Number) generated by Toggle. Toggle is also compatible with non-IIN numbers which may differ in length. When an order is created via the web shop, Toggle automatically generates the card number.

Orders – An order relates to an account and sales channel.

Line Items – An item type of transactions. When a transaction is sent to Toggle, a line item is created which links to the relevant product, card and order.

Line item types – Available types, associated with a line type, are Sale, Redemption, Breakage, Reversal, Outbound Balance Transfer, Inbound Balance Transfer. Each type has a unique ID.

Transactions – A transaction represents an action taken in relation to an order.

Fulfilment methods – Available types, associated with a product are Email, Postal and In Venue Purchase.

Merchants – Merchants relate to POS companies, each merchant has a unique ID. Currently, available merchants can be queried for via the API. Transactions related to a merchant ID.

Physical cards – Toggle generates batches of 16 digit card reference numbers, which are then used for physical cards. There is no way to retrieve these through the API.

Postage – Postage types are added by the user. For example, an account might have configured 3 postage types (Free Delivery, 1st Class Postage, 2nd Class Postage). Postage types are related to a line item fulfilment.

Price modifiers – Price modifiers relate to a currency and product. The price is defined to two decimal places. For example, a £10 price modifier would have the price set to 1000.

Products – When a Toggle customer creates their account, they also create the products that display on their web store. Products are linked with an account, type, fulfilment methods, and price modifiers.

Sales channels – Sales channels define the source of an order, each sales channel has a unique ID. Currently available sales channels can be queried for via the API. Sales channels relate to an order.

Roles – A role defines the permissions available to a user.

Users – When an account is created, an associated user account is also created. Users are associated with accounts and roles.

Units – This is what our API refers to sites as. A site is a physical location, such as one of your restaurant locations.

Configuration Variables

Your application will need to keep a configuration of variables to use for each account. These are summarised below.
sales_channel_id – For POS integrations, use ‘3’ as the sales_channel_id when creating orders – this is a permanent ID used across all accounts for in-store transactions.
fulfilment_method_id – Used when creating orders, this can always be configured as ‘3’ (In-Venue Purchase).
currency_id (configurable) – Default to ‘1‘ (£ sterling), but leave this as something that can be configured as well, this will ensure the integration is future-proofed to handle other currency IDs in future.
account_id (configurable) – account_id will be manually configured, we will provide this to you each time a new account is configured. Email support@usetoggle.com to request your account_id.
 
merchant_id – Email support@usetoggle.com to request this for your account.

total –  This should equal the total of the cards being created. E.g. if a customer is buying 1 card for £20, the total would be 2000. If they are buying two £20 cards, and it’s being done as a single order, the total would be passed as 4000.

unit_epos_reference – This refers to the unique till ID, passed to Toggle so its knows the location where the transaction was made. This needs to be matched with the configured EPOS references in your Toggle account. See here for more information: http://academy.usetoggle.com/getting-started-with-toggle/setting-up-toggle-for-multiple-sites

merchant_transaction_reference – This refers to the unique reference created by the till when the transaction is made.

Physical cards

Physical cards are standard magnetic stripe cards with a number encoded on them. Toggle generates numbers using its IIN (Issuer Identification Number), which generates a 19 digit unique reference for the card. Toggle is also compatible with non-IIN numbers, which may differ in length.

Digital cards will be printed out by customers or presented on a phone with the card number displayed for manual type-in to POS or, if the technology is available on the tills, a barcode or QR code can be included on the digital card for scanning.

Query products

Before you can create an order, you must first query for products to find the products available for the account. All order items in Toggle are linked to a product.

query($account_id:Int!) {
	Products(account_id:$account_id) {
		id
		name
	}
}

This would return an array of products:

{
  "data": {
    "Products": [
      {
        "id": 244,
        "name": "In-Store Gift"
      },
      {
        "id": 245,
        "name": "Summer Promotion"
      }
    ]
  }
}

For POS integrations, you can use the id for “In-Store Gift”. This will be unique per account, but you only need to retrieve and configure this id a single time as it will not change for an account once that account exists.

Price modifiers

You can find the ‘price modifiers‘ for a product (e.g. the values entered by the Toggle user when they created this product, such as £5, £10, £15) – so you can poll the API for these, and then return them on the POS interface so that the operator can choose the value to sell. The API call for price modifiers is:

{"query":"query($account_id:Int!) {Products(account_id:$account_id) {id name    PriceModifiers {      id      price      description    }}}","variables":{"account_id":"youraccountid"}}

Example return

{
  "data": {
    "Products": [
      {
        "id": 244,
        "name": "In-Store Gift",
        "PriceModifiers": [
          {
            "id": 975,
            "price": 0,
            "description": "Blank card"
          }
        ]
      },
      {
        "id": 245,
        "name": "Summer Promotion",
        "PriceModifiers": [
          {
            "id": 976,
            "price": 3500,
            "description": null
          }
        ]
      }
    ]
  }
}

Creating an order

To create an order in Toggle, make a mutation request to createOrder with the expected payload.

mutation (
                        $account_id:Int!, 
                        $merchant_id:Int!, 
                        $order_items:[OrderItemInput]!, 
                        $currency:String!, 
                        $group_fulfilment:Boolean!,
                        $total:Int!,
                        $sales_channel_id:Int!,
                        $unit_epos_reference:String!,
                        $merchant_transaction_reference:String
                      ){
                        createOrder(
                            account_id                    : $account_id,
                            merchant_id                   : $merchant_id,
                            order_items                   : $order_items,
                            currency                      : $currency,
                            group_fulfilment              : $group_fulfilment,
                            total                         : $total,
                            sales_channel_id              : $sales_channel_id,
                            unit_epos_reference           : $unit_epos_reference,
                            merchant_transaction_reference : $merchant_transaction_reference
                        ){
                            id,
                            LineItems{
                                value,
                                Transaction{
                                    merchant_transaction_reference
                                },
                                Card{
                                        id,
                                        card_reference,
                                        card_alias_card_reference,
                                        balance,
                                        initial_balance,
                                        created_at,
                                        updated_at
                                    }
                            }
                        }
                  }

Variables

{
   "account_id": youraccountid,
   "order_items": [
{
   "fulfilment_method_id": 3,
   "product_id": yourproductid,
   "card_reference": "6301190092843818801",
   "custom_price_modifier_value": 2500
}
],
   "merchant_transaction_reference": "testreference",
   "group_fulfilment": true,
   "total": 2500,
   "currency": "GBP",
   "merchant_id": yourmerchantid,
   "unit_epos_reference": "test",
   "sales_channel_id": 3
}

Transactions

The key transactions that EPOS will need to support are:

  • The purchase and/or top-up of cards in-venue and transmitting those purchases to Toggle’s APIs
  • The debit of cards in-venue (through physical swipe, manual number key-in or barcode/QR scan)
  • The reversal of a given transaction in-venue

The createBalanceAdjustment mutation handles the creation of a transaction against a card, and the line item represents the action, linked with that transaction and card.

mutation($currency:String,$value:Int,$card_reference:String!, $unit_epos_reference:String!, $merchant_id:Int!, $merchant_transaction_reference:String){
                            createBalanceAdjustment(
                                currency: $currency,
                                card_reference: $card_reference,
                                value: $value,
                                unit_epos_reference: $unit_epos_reference,
                                merchant_id: $merchant_id,
                                merchant_transaction_reference: $merchant_transaction_reference
                            ) 
                            {
                                id,
                                value,

                                LineItem{
                                    Transaction{
                                        merchant_transaction_reference
                                    },
                                    Card{
                                        id,
                                        card_reference,
                                        card_alias_card_reference,
                                        balance,
                                        initial_balance
                                        created_at,
                                        updated_at,
                                    }
                                }
                            }
                        }

Top-up (credit)

{
	"currency": "GBP",
	"card_reference": "yourcardreference",
	"value": 2500,
	"unit_epos_reference": "youreposref",
	"merchant_id": "yourmerchantid",
	"merchant_transaction_reference": "yourmerchanttransactionref"
}

Redemptions (debit)

To make a redemption adjustment, you can pass a negative value, e.g. “-100”.
{
	"currency": "GBP",
	"card_reference": "yourcardreference",
	"value": -100,
	"unit_epos_reference": "youreposref",
	"merchant_id": "yourmerchantid",
	"merchant_transaction_reference": "yourmerchanttransactionref"
}

Reversals (cancellation)

mutation($merchant_id:Int!,$unit_epos_reference:String!,$merchant_transaction_reference:String,$ReversalItems:[ReversalItemInput]!){
                            createReversal(
                                ReversalItems: $ReversalItems,
                                merchant_transaction_reference: $merchant_transaction_reference,
                                unit_epos_reference: $unit_epos_reference,
                                merchant_id: $merchant_id
                            ) 
                            {
                                merchant_transaction_reference,
                                LineItems{
                                    value,
                                    Card{
                                        id,
                                        card_reference,
                                        card_alias_card_reference,
                                        balance,
                                        initial_balance,
                                        updated_at,
                                        created_at,
                                    }
                                }
                            }
                        }

Variables:

{
	"ReversalItems": [
		{
			"line_item_id": "thelineitemtoreverse",
			"shipping_refund": false
		}
	],
	"merchant_transaction_reference": "test-123-123-123",
	"merchant_id": yourmerchantid,
	"unit_epos_reference": "test"
}

How to find the Line Item ID to reverse

To perform a reversal, you need to look up the line item ID to reverse. To do this, run a query to find the line item ID, passing the original merchant_transaction_reference to reverse.

query($page:Int!, $limit:Int!, $merchant_transaction_reference:String!){
                    LineItems(page:$page, limit:$limit, merchant_transaction_reference:$merchant_transaction_reference){
                        data{
                            id
                        }
                    }
                }

Variables:

{
	"merchant_transaction_reference": "test-123-123-123",
	"page": 1,
	"limit": 1,
}

Checking card balance

Make a query to cards, passing the card reference to retrieve the data about a specific card.

To learn more about GraphQL and queries, refer to the official GraphQL Queries and Mutations documentation.

query($card_reference:String!, $page:Int!, $limit:Int!, $id:Int)

                    {

                        Cards(card_reference:$card_reference, limit:$limit, page:$page, id:$id)

                        {

                            data{

                                card_reference,

                                balance,

                                initial_balance,

                                created_at,

                                updated_at

                            } 

                        }

                }

Variables:

{
   "limit": 1,
   "page": 1,
   "card_reference": "6301190000554511994"
}

This will return valid JSON for cards found:

{
  "data": {
    "Cards": {
      "data": [
        {
          "card_reference": "6301190000554511994",
          "balance": 2500,
          "initial_balance": 2500,
          "created_at": "2019-05-13 13:11:47",
          "updated_at": "2019-05-13 13:11:47"
        }
      ],
      "total": 1,
      "per_page": 1
    }
  }
}

Cards are always active in Toggle. If you want to determine whether a card can be used or not, take note of the ‘Balance’ for the card. If there is zero balance, the card cannot be used for a redemption transaction.

If no cards are found for your query, the API will respond with blank JSON for “Data”:

{
  "data": {
    "Cards": {
      "data": [],
      "total": 0,
      "per_page": 1
    }
  }
}

Retrieve customers

Customer data can be retrieved for both Cards and Orders. This allows you to export customer data to a CRM.

Consent is stored on a granular basis and can also be queried from the API. The marketing opt in feature must be enabled and your account must contain customers who have given consent for this functionality to return data.

This query would return the Email, First Name, Last Name and Consent data for each card in your account.

query(
$limit:Int!,
$page:Int!,
$consents_limit:Int!,
$consents_page:Int!
){
Cards(limit:$limit, page:$page){
data{
id,
Email{
id,
first_name,
last_name,
email,
      Consents(limit:$consents_limit,page:$consents_page){
        data{
          id, 
          consent_copy,
          consented_at
        }
         
      }
    
  },
}
total,
per_page
},
}

The Consents array will return empty [] when no consent was given by the customer.

To retrieve recipient data, use this query:

query(
$limit:Int!,
$page:Int!,
$consents_limit:Int!,
$consents_page:Int!
){
Orders(limit:$limit, page:$page){
data{
id,
ReceiptEmail{
id,
first_name,
last_name,
email,
      Consents(limit:$consents_limit,page:$consents_page){
        data{
          id, 
          consent_copy,
          consented_at
        }
         
      }
    
  },
}
total,
per_page
},
}

Below is an example response from this query:

{
"id": 84,
"ReceiptEmail": {
"id": "156",
"first_name": null,
"last_name": null,
"email": "joshua+test@airship.co.uk",
"Consents": {
"data": [
{
"id": 2,
"consent_copy": "Test marketing consent",
"consented_at": "2019-06-21 14:47:39"
}
]
}
}
},

Error handling

A third party should not try to interpret errors returned by the API and use them within logic in their application. Toggle does not use error numbers for its errors, and as such only returns string messages.

Below are just some examples of errors returned by our API. There are many validation and logic rules in place, so there are many errors that can be returned.

If currency is missing:

{
  "errors": [
    {
      "message": "validation",
      "locations": [
        {
          "line": 2,
          "column": 29
        }
      ],
      "validation": {
        "currency": [
          "This field is required"
        ]
      },
      "customer_facing": false
    }
  ],
  "data": {
    "createBalanceAdjustment": null
  }
}

If you pass an invalid card reference:

{
  "errors": [
    {
      "message": "validation",
      "locations": [
        {
          "line": 2,
          "column": 29
        }
      ],
      "validation": {
        "card_reference": [
          "Must be a valid card reference."
        ]
      },
      "customer_facing": false
    }
  ],
  "data": {
    "createBalanceAdjustment": null
  }
}

If you pass an invalid merchant ID:

{
  "errors": [
    {
      "message": "validation",
      "locations": [
        {
          "line": 2,
          "column": 29
        }
      ],
      "validation": {
        "merchant_id": [
          "This field is not of an expected value"
        ]
      },
      "customer_facing": false
    }
  ],
  "data": {
    "createBalanceAdjustment": null
  }
}

Where to get help

Email support@usetoggle.com and a member of the team will get back to you.