Sparkfly Wallet Integration Guide

The objective of this document is to allow a third party vendor to interact with the Sparkfly Wallet system. Interacting with the Sparkfly Wallet includes the following:

Once offers are in the wallet, they may be redeemed at the POS.

For a detailed API reference, visit the Sparkfly APIs section.

Conceptual Overview

Within Sparkfly, a wallet is represented by a member. A member may have zero or more offers available to them. A member may also have zero or more credentials associated with it. You may think of a credential as a unique identifier that represents one of a few possible concepts:

Members have associated entities referred to as offer states within the offer wallet. An offer state is an entity representing an instance of an offer as issued to a member. When a new offer state is created, an associated credential is created to identify the offer state. This credential is then used at the POS to redeem the offer. Once the offer is redeemed, the offer state is modified to show as redeemed, and the credential will no longer function at the POS.

Member Management

Creating a member

When a new member needs to be created within Sparkfly, the integrator should send a request with the unique identifier for this member. If the member does not exist, it will be created, and a new Sparkfly-internal unique member ID will be created for the member. This value will be returned, and should be stored for future API calls.

For these examples, we will be using a fictitional member identifier of member-100. We will assume that this member also has another identifier in a loyalty system external to Sparkfly, with a unique identifier of loyalty-100.

Let's see if member-100 exists within the Sparkfly member database:

GET https://api-staging.sparkfly.com/v1.0/members/search?identifier=member-100

Response:

404 Not Found

The server responds with 404 Not Found indicating that the member does not exist. Let's create it:

POST https://api-staging.sparkfly.com/v1.0/members
{
    "member": {
        "identifier": "member-100"
    }
}

Response:

201 Created
{
    "member": {
        "id": 555555,
        "identifier": "member-100",
        "account_id": 99999,
        "notification_mode": "app",
        "created_at": "2019-09-12T13:54:04.332592301Z",
        "updated_at": "2019-09-12T13:54:04.332592301Z"
    },
    "errors": null
}

The ID field 555555 is the Sparkfly-internal member ID and will be needed for future API calls.

If we make the search API call once again, we should see that our member exists:

GET https://api-staging.sparkfly.com/v1.0/members/search?identifier=member-100

Response:

200 OK
{
    "member": {
        "id": 555555,
        "identifier": "member-100",
        "account_id": 99999,
        "notification_mode": "app",
        "created_at": "2019-09-12T13:54:04.332592301Z",
        "updated_at": "2019-09-12T13:54:04.332592301Z"
    },
    "errors": {}
}

Associating an external loyalty identifier to the member as a credential

This functionality requires that a channel is created within your Sparkfly account. Our account management team will assist you with this process. For the sake of demonstration, let's assume that this has been completed and the channel ID issued to you is 999. Let's also assume that the member's unique identifier in the external loyalty system is loyalty-100.

Creating this identifier as a credential will enable the customer to enter this identifier at the store to identify themselves.

Let's ask the API to create a credential (loyalty-100) for the member identified by member-100, with the channel_id of 999 (issued by Sparkfly.)

POST https://api-staging.sparkfly.com/v1.0/credentials?member_identifier=member-100&identifier=loyalty-100&channel_id=999

Response:

201 Created
{
    "credential": {
        "id": 888888,
        "identifier": "loyalty-100",
        "member_id": 555555,
        "account_id": 99999,
        "redeeming_account_id": 99999,
        "channel_id": 999,
        "eligible_channel_id": null,
        "store_id": null,
        "voided_at": null,
        "redeemed_at": null,
        "processed_at": null,
        "reusable": false,
        "locked": false,
        "url": null,
        "created_at": "2019-09-12T14:02:05.628031185Z",
        "updated_at": "2019-09-12T14:02:05.628031185Z",
        "offer_ids": null,
        "merchant_id": null,
        "merchant_name": null,
        "token": "",
        "errors": {},
        "offer_name": null,
        "location_address": null,
        "supports_barcode": false,
        "barcodes_supported": null,
        "code_lifetime": -1,
        "offer_expires": null,
        "type": "loyalty"
    }
}

The response indicates that the credential has been created and is now active.

Member Wallet Management

Retrieving a list of offers currently in a member's wallet

As mentioned previously, an offer issued to a member is represented as an offer state. To retrieve all offers (both available and previously redeemed), we must send a request to the Member Offer States API. Note that this endpoint expects the Sparkfly-internal member ID, not the member ID supplied when creating the member. In previous examples, the member ID created was 555555. Let's continue to use that. Let's also assume an offer for a Free Entree has been created and its ID is 1000.

Send the request:

GET https://api-staging.sparkfly.com/v1.0/members/555555/offer_states

Response:

200 OK
{
    "page": 0,
    "per_page": 1000,
    "total_entries": 1,
    "offer_states": [
        {
            "offer_state": {
                "offer_state_id": 1044023,
                "offer_id": 1000,
                "member_id": 555555,
                "status": "incomplete",
                "value": 0,
                "locked": false,
                "activates_at": "2019-09-10T00:00:00Z",
                "expires_at": "2020-09-16T00:00:00Z",
                "external_ref_id": "UNIQUETRACKINGID-1",
                "offer_activities": [],
                "offer_name": "Free Entree",
                "offer_short_name": "",
                "offer_campaign_name": "Sample Campaign",
                "offer_group": "",
                "offer_description": "A free entree for you!",
                "offer_value_required": null,
                "offer_terms_and_conditions": "Sample offer terms...",
                "offer_web_image_url": "",
                "offer_web_thumb_url": "",
                "offer_mobile_image_url": "",
                "offer_mobile_thumb_url": "",
                "is_reward": false,
                "credential_identifier": "8CNHJ2",
                "token": "o95HNCYyej4bh6jp8HkmMUpKXUZM7EVdJZL7rRuIkXRW8jD0QpakVAosT1I2sWQcbOQL19F6sPrbXHoVHVQ",
                "transferable": true,
                "reusable": false
            },
            "errors": {}
        }
    ]
}

We can see from this result that the member has one redeemable offer in their wallet. The offer code for this offer is 8CNHJ2, and the associated offer is a Free Entree. If the customer provided the 8CNHJ2 code at the POS, the offer would be redeemed and the customer would receive a discount in accordance with the definition of the Free Entree offer.

Notable fields in this example:

More detailed fields can be found in the relevant documentation.

Adding an Offer to a Member's Wallet

To add an offer to a member's wallet, you will need the following:

For this example, we will use the test member 555555, the test offer 1000, the test campaign abcxyz, and the test channel of 123.

There are many optional fields related to the Create Offer State endpoint. A couple of important ones are: - external_ref_id: Optional but recommended - This field should be populated with a unique tracking code from your side. Possibly an order ID from the Offer Catalog so we can connect the offer in the wallet back to the originating order. - activates_at and expires_at are optional - if not set on a per offer basis, it will default to the campaign or parent offer.

To add the offer to the wallet, we send a request:

POST https://api-staging.sparkfly.com/v1.0/members/555555/offer_states?offer_id=1000&channel_id=123
{
    "offer_state": {
        "campaign_id": "Yz6hXMn",
        "activates_at": "2019-09-10T00:00:00Z",
        "expires_at": "2020-09-16T00:00:00Z",
        "external_ref_id": "UNIQUETRACKINGID-1"
    }
}

Response:

200 OK
{
    "offer_state": {
        "offer_state_id": 1044023,
        "offer_id": 1000,
        "member_id": 555555,
        "status": "incomplete",
        "value": 0,
        "locked": false,
        "activates_at": "2019-09-10T00:00:00Z",
        "expires_at": "2020-09-16T00:00:00Z",
        "external_ref_id": "UNIQUETRACKINGID-1",
        "offer_activities": [],
        "offer_name": "Free Entree",
        "offer_short_name": "",
        "offer_campaign_name": "Sample Campaign",
        "offer_group": "",
        "offer_description": "A free entree for you!",
        "offer_value_required": null,
        "offer_terms_and_conditions": "Sample offer terms...",
        "offer_web_image_url": "",
        "offer_web_thumb_url": "",
        "offer_mobile_image_url": "",
        "offer_mobile_thumb_url": "",
        "is_reward": false,
        "credential_identifier": "8CNHJ2",
        "token": "o95HNCYyej4bh6jp8HkmMUpKXUZM7EVdJZL7rRuIkXRW8jD0QpakVAosT1I2sWQcbOQL19F6sPrbXHoVHVQ",
        "transferable": true,
        "reusable": false
    },
    "errors": {}
}

The offer is now in the member's wallet. The credential_identifier is the redeemable code that can be displayed with a QR code and text for in store redemption. When this code is presented at the store, the Free Entree offer will be redeemed, and the Offer State in the member's wallet will change to a completed status.

Voiding an Offer State in a Member's Wallet

When voiding a member's offer state, you have two options:

Example 1: Voiding using member ID and offer state ID

For example, to void member ID 555555's offer state ID 1044023 shown in examples above, submit a POST to this endpoint:

POST https://api-staging.sparkfly.com/v1.0/members/555555/offer_states/1044023/void

Response:

200 OK

Example 2: Voiding using member identifier and offer state ID

For example, to void member ID 555555's (also referencable by identifier of member-100) offer state ID 1044023, submit a POST to this endpoint:

POST https://api-staging.sparkfly.com/v1.0/members/offer_states/1044023/void?member_identifier=member-100

Response:

200 OK

Other Voiding Examples

See API References linked above. There are numerous HTTP return codes for various situations.

Save to Wallet Through Deeplinks

The Sparkfly platform supports a process where an external website or app (i.e. a Sparkfly landing page) can save an offer distributed through a campaign directly to a member's wallet. In order to support this, the integrator will need to provide a URL that will be called to initiate the Save to Wallet process. This url will need to handle an app deeplink flow and retain a token url parameter that needs to be saved through the member sign up/sign in.

Lookup an Offer from a Token

This API call is used to retrieve the offer state details when a token comes through a Save to Wallet deeplink. Once the member has successfully logged in to the app, this call should be made using the token in order to lookup the details of the offer. The offer_id field is used to add the offer to the member's wallet in the next call to add the offer to the member's wallet.

GET https://api-staging.sparkfly.com/v1.0/members/offer_states?token=o95HNCYyej4bh6jp8HkmMUpKXUZM7EVdJZL7rRuIkXRW8jD0QpakVAosT1I2sWQcbOQL19F6sPrbXHoVHVQ

Response: 200 OK

{
    "offer_state": {
        "offer_state_id": 1044023,
        "offer_id": 2698,
        "member_id": 1880867,
        "status": "incomplete",
        "value": 0,
        "locked": false,
        "activates_at": "2019-09-10T00:00:00Z",
        "expires_at": "2020-09-16T00:00:00Z",
        "external_ref_id": "UNIQUETRACKINGID-1",
        "offer_activities": [],
        "offer_name": "Sample Offer",
        "offer_short_name": "",
        "offer_campaign_name": "Sample Campaign",
        "offer_group": "",
        "offer_description": "Sample offer description",
        "offer_value_required": null,
        "offer_terms_and_conditions": "Sample offer terms...",
        "offer_web_image_url": "",
        "offer_web_thumb_url": "",
        "offer_mobile_image_url": "",
        "offer_mobile_thumb_url": "",
        "is_reward": false,
        "credential_identifier": "8CNHJ2",
        "token": "o95HNCYyej4bh6jp8HkmMUpKXUZM7EVdJZL7rRuIkXRW8jD0QpakVAosT1I2sWQcbOQL19F6sPrbXHoVHVQ",
        "transferable": true,
        "reusable": false
    },
    "errors": {}
}

Adding an Offer to a Member by Token

After the Save to Wallet deeplink is handled, the member has successfully signed in or registered, and the offer details have been retrieved using the previous call, the offer state can be added to the currently signed in member. The offer_id parameter should have been received form the previous call, the channel_id will be the App channel_id provided during setup of the integration, and the token is the URL parameter passed through the deeplink. More details can be found in the relevant documentation.

POST https://api-staging.sparkfly.com/v1.0/members/1880867/offer_states?offer_id=2698&channel_id=337&token=o95HNCYyej4bh6jp8HkmMUpKXUZM7EVdJZL7rRuIkXRW8jD0QpakVAosT1I2sWQcbOQL19F6sPrbXHoVHVQ

Response: 200 OK

{
    "offer_state": {
        "offer_state_id": 1044023,
        "offer_id": 2698,
        "member_id": 1880867,
        "status": "incomplete",
        "value": 0,
        "locked": false,
        "activates_at": "2019-09-10T00:00:00Z",
        "expires_at": "2020-09-16T00:00:00Z",
        "external_ref_id": "UNIQUETRACKINGID-1",
        "offer_activities": [],
        "offer_name": "Sample Offer",
        "offer_short_name": "",
        "offer_campaign_name": "Sample Campaign",
        "offer_group": "",
        "offer_description": "Sample offer description",
        "offer_value_required": null,
        "offer_terms_and_conditions": "Sample offer terms...",
        "offer_web_image_url": "",
        "offer_web_thumb_url": "",
        "offer_mobile_image_url": "",
        "offer_mobile_thumb_url": "",
        "is_reward": false,
        "credential_identifier": "8CNHJ2",
        "token": "o95HNCYyej4bh6jp8HkmMUpKXUZM7EVdJZL7rRuIkXRW8jD0QpakVAosT1I2sWQcbOQL19F6sPrbXHoVHVQ",
        "transferable": true,
        "reusable": false
    },
    "errors": {}
}

Offer State Localization

The Offer State endpoints are designed to accept a lang query parameter to specify localized offer or campaign data to present to users. Currently, this localized data cannot be set from the Sparkfly Admin Portal and must be configured for an offer or campaign as a support task. The lang is intended to be an IETF Language Tag, for example "en" or "fr-CA".

The following offer state data can be localized from the associated offer:

The following offer state data can be localized from the associated campaign:

Campaign localization will have highest priority, followed by offer localization. If neither the campaign nor offer have localized text configured for the field, the default text from the Admin Portal will be used, again in order of campaign and offer.

Example:

GET https://api-staging.sparkfly.com/v1.0/members/555555/offer_states&lang=es

Response:

200 OK
{
    "page": 0,
    "per_page": 1000,
    "total_entries": 1,
    "offer_states": [
        {
            "offer_state": {
                "offer_state_id": 1044023,
                "offer_id": 1000,
                "member_id": 555555,
                "status": "incomplete",
                "value": 0,
                "locked": false,
                "activates_at": "2019-09-10T00:00:00Z",
                "expires_at": "2020-09-16T00:00:00Z",
                "external_ref_id": "UNIQUETRACKINGID-1",
                "offer_activities": [],
                "offer_name": "Free Entree",
                "offer_short_name": "Spanish offer short name",
                "offer_campaign_name": "Sample Campaign",
                "offer_group": "Spanish group",
                "offer_description": "Description in Spanish, from Campaign",
                "offer_value_required": null,
                "offer_terms_and_conditions": "T&C in Spanish, from Offer after falling back from Campaign",
                "offer_web_image_url": "URL to Spanish-localized web image",
                "offer_web_thumb_url": "URL to Spanish-localized web thumb image",
                "offer_mobile_image_url": "URL to Spanish-localized mobile image",
                "offer_mobile_thumb_url": "URL to Spanish-localized mobile thumb image",
                "is_reward": false,
                "credential_identifier": "8CNHJ2",
                "token": "o95HNCYyej4bh6jp8HkmMUpKXUZM7EVdJZL7rRuIkXRW8jD0QpakVAosT1I2sWQcbOQL19F6sPrbXHoVHVQ",
                "transferable": true,
                "reusable": false
            },
            "errors": {}
        }
    ]
}