Manufacturer Getting Started Guide

Manufacturer APIs allow a manufacturer to deposit their own offers into TCB through their own internal systems. APIs are NOT required for a Manufacturer to connect to The Coupon Bureau, these APIs are designed specifically for partners who are looking to integrate these functions into your own system.

API functions include Master Offer File deposits, Authorized Partner authorization by account for Master Offer File management, and Provider authorization by Master Offer File or account for distribution.

Step #1 : Get Access Token


curl -X POST '{{API_SERVER}}/access_token' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
--data '{ 
    "access_key": "ACCESS_KEY", 
    "secret_key": "SECRET_KEY" 
}'

The Access Token will be valid for 24 hours. You should cache it and use the same access token for next 23 hours 59 mins to call any other APIs.

Step #2 : Create Master Offer File

curl -X POST '{{API_SERVER}}/manufacturer/base_gs1' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{
    "data":{
        "base_gs1":"8112010031493140188",
        "brand_id":"XYZ",
        "description":"50% off ",
        "campaign_start_time":"04/21/2020",
        "campaign_end_time":"04/30/2020",
        "redemption_start_time":"04/22/2020",
        "redemption_end_time":"04/30/2020",
        "total_circulation":"100",
        "primary_purchase_save_value":"1",
        "primary_purchase_requirements":"1",
        "primary_purchase_req_code":"1",
        "primary_purchase_gtins":[
            "294239749273","2390843209"
            ],
        "additional_purchase_rules_code":"",
        "second_purchase_requirements":"",
        "second_purchase_gs1_company_prefix":"",
        "second_purchase_req_code":"",
        "second_purchase_gtins":[
            ""
            ],
        "third_purchase_requirements":"",
        "third_purchase_gs1_company_prefix":"",
        "third_purchase_req_code":"",
        "third_purchase_gtins":[
            ""
            ],
        "gln":"",
        "save_value_code":"1",
        "applies_to_which_item":"",
        "store_coupon":"1",
        "donot_multiply_flag":""
    }
}'
    
        

Once the master offer file is created, you can use the below API call to manage the master offer files.
      Assign / Unassign provider for master offer file
      Delete master offer file

To get master offer file(s) created by you
      My master offer files
      Master offer file detail

Master offer file needs to be locked before a provider deposits a serialized data string. If the master offer file is editable (not locked), no one will be able to deposit a serialized data string under that master offer file.
      My master offer files
      Master offer file detail

Step #3.1 : Get all Providers connected to TCB

curl -X GET '{{API_SERVER}}/providers' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' 
      

This API response can be cached so that you can skip this step. Once you get the list of providers, you can select the desired providers (email_domain of the provider) from this list to authorize. Once the provider is authorized to distribute a master offer file, they can deposit the serialized GS1 of that master offer file.

Step #3.2 : Authorize provider(s) to allow master offer file distribution

curl -X POST '{{API_SERVER}}/manufacturer/base_gs1/<BASE_GS1>/toggle_provider' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{"email_domain":"example1.com"}'
       

You can call this API multiple times to authorize multiple providers. Once the provider is authorized, you can get the list of all authorized providers of a master offer file

      Get assigned providers of master offer file

Step #4.1 : Authorize a Authorized Partner

curl -X PUT '{{API_SERVER}}/manufacturer/toggle/manufacturer_agent' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{"email_domain":"example1.com"}'
        

You can call this API multiple times to authorize multiple Authorized Partners.
   To unauthorize a Authorized Partner use
      Call the same toggle api (/manufacturer/toggle/manufacturer_agent)

You can also get the list of all authorized Authorized Partners
      Get connected Authorized Partners

Step #4.2 : Give Brand Access to a Authorized Partner to create / manage master offer files and receive redemption data

curl -X PUT '{{API_SERVER}}/manufacturer/manufacturer_agents/:manufacturer_agent_email_domain/toggle_brand/:brand_internal_id' \
-H 'Content-Type: application/json' 
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{"access_type":"campaign_set"}'
        

You can call this API to authorize your brand to a authorized partner with proper access_type. access_type attribute value should be one of the below

  • view_only: can view all the master offer files of the brand.
  • campaign_set: can edit campaign detail of the master offer file of the brand.
  • full_set: can edit complete master offer file of the brand.
  • full_set_with_lock: can edit complete master offer and of the brand and can lock it to stop future update. Once the master offer file is locked, only campaign data (following attributes) can be edited.
    • description
    • campaign_start_time
    • campaign_end_time
    • redemption_start_time
    • redemption_end_time
    • total_circulation
    • primary_purchase_gtins
    • second_purchase_gtins
    • third_purchase_gtins

Authorized Partner Getting Started Guide

Authorized Partner APIs allow the ability to connect to the TCB from your internal systems so that you can directly deposit and manage an 8112 offer into a manufacturer’s TCB account and retrieve redemption data. APIs are NOT required for a Authorized Partner to perform your functions as they relate to The Coupon Bureau, these APIs are designed specifically for partners who are looking to integrate these functions into your own system.

Step #1 : Get Access Token


curl -X POST '{{API_SERVER}}/access_token' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
--data '{ 
    "access_key": "ACCESS_KEY", 
    "secret_key": "SECRET_KEY" 
}'

The Access Token will be valid for 24 hours. You should cache it and use the same access token for next 23 hours 59 mins to call any other APIs.

Step #2 : Get Connected Manufacturers


Required in step #3 where you will create master offer file on behalf of one manufacturer.

curl -X GET '{{API_SERVER}}/manufacturer_agent/manufacturers' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' 
        

You can cache the response of this API call as there will be no change in response until and unless another manufacturer authorizes the same Authorized Partner. Once you cache it, you can skip step #2 while creating a master offer file.

Step #3 : Create Master Offer File for a Manufacturer

curl -X POST '{{API_SERVER}}/manufacturer/base_gs1?email_domain=<MANUFACTURER_EMAIL_DOMAIN>' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{
    "data":{
        "base_gs1":"8112010031493140188",
        "brand_id":"XYZ",
        "description":"50% off ",
        "campaign_start_time":"04/21/2020",
        "campaign_end_time":"04/30/2020",
        "redemption_start_time":"04/22/2020",
        "redemption_end_time":"04/30/2020",
        "total_circulation":"100",
        "primary_purchase_save_value":"1",
        "primary_purchase_requirements":"1",
        "primary_purchase_req_code":"1",
        "primary_purchase_gtins":[
            "294239749273","2390843209"
            ],
        "additional_purchase_rules_code":"",
        "second_purchase_requirements":"",
        "second_purchase_gs1_company_prefix":"",
        "second_purchase_req_code":"",
        "second_purchase_gtins":[
            ""
            ],
        "third_purchase_requirements":"",
        "third_purchase_gs1_company_prefix":"",
        "third_purchase_req_code":"",
        "third_purchase_gtins":[
            ""
            ],
        "gln":"",
        "save_value_code":"1",
        "applies_to_which_item":"",
        "store_coupon":"1",
        "donot_multiply_flag":""
    }
}'
      

Once the master offer file is created, you can use the below API call to manage the master offer files.
To activate / deactivate / update a specific master offer file
      Activate / Deactive master offer file
      Assign / Unassign provider for master offer file
      Delete master offer file

To get master offer file(s) created by you
      My master offer files
      Master offer file detail

Step #4.1 : Get all Providers connected to TCB

curl -X GET '{{API_SERVER}}/providers' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' 
        

This API response can be cached so that you can skip this step. Once you get the list of providers, you can select the desired providers (email_domain of the provider) from this list to authorize. Once the provider is authorized to distribute a master offer file, they can deposit the serialized data string of that master offer file.

Step #4.2 : Authorize provider(s) to allow master offer file distribution

curl -X POST '{{API_SERVER}}/manufacturer/base_gs1/<BASE_GS1>/toggle_provider' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{"email_domain":"example1.com"}'
         


This API response can be cached so that you can skip this step. Once you get the list of providers, you can select the desired providers from this list to authorize. Once the provider is authorized to distribute a master offer file, they can deposit the serialized data string of that master offer file.

Step #4.3 : Authorize provider(s) to allow master offer file distribution

curl -X PUT '{{API_SERVER}}/manufacturer/toggle/manufacturer_agent' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{"email_domain":"example1.com"}'
          

You can call this API multiple times to authorize multiple Authorized Partners.
   To unauthorize a Authorized Partner use
      Call the same toggle api (/manufacturer/toggle/manufacturer_agent)

You can also get the list of all authorized Authorized Partners
      Get connected Authorized Partners

Provider Guide

Provider APIs allow a coupon provider to deposit/ delete a serialized data string (the serialized data string distributed to a consumer) into a manufacturer’s Master Offer File along with a series of other functions both required and optional to enhance the consumer experience. A provider will only be able to deposit serialized data strings into Master Offer Files of those manufacturers who have authorized them.

REQUIRED PROVIDER FUNCTIONS

The following required functions are used to meet industry standards and maintain consistent basic consumer experience functions across providers. All required functions will require proof of application before moving to the production server. Click here to view our Provider Guide to Universal Digital Coupons for more information about all provider functions.

  • DEPOSIT SERIALIZED DATA STRINGS USING PROVIDER PREFIX (instructions below)
  • DELETE SERIALIZED DATA STRINGS (instructions below)
  • APPLY FETCHCODE TO CONSUMER EXPERIENCE (instructions below)

Step #1 : Get Access Token


curl -X POST '{{API_SERVER}}/access_token' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
--data '{ 
    "access_key": "ACCESS_KEY", 
    "secret_key": "SECRET_KEY" 
}'

The Access Token will be valid for 24 hours. You should cache it and use the same access token for next 23 hours 59 mins to call any other APIs.

Step #2 : Get authorized master offer files.


Manufacturers / Authorized partners will authorize provider to distribute master offer files. To get the list of all authorized master offer files, use My master offer files API

curl -X GET '{{API_SERVER}}/provider/base_gs1s' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' 
        



Step #3 : Generate your serialized data string


To accommodate multiple providers on a single master offer file, a “provider prefix” will be assigned and implemented as part of the serial number for each data string. This will resolve any potential duplication of serial numbers across providers. Follow the below process to generate your serialized data string

Master Offer File : 8112............VLIPROVIDER_PREFIXCONSUMER_IDENTIFIER

VLI = Length(PROVIDER_PREFIX) + LENGTH(CONSUMER_IDENTIFIER) - 6

Use Serialization Prefix API to get your PROVIDER_PREFIX


curl -X POST '{{API_SERVER}}/provider/serialization_prefix' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' 



Step #4 : Deposit serialized data string


curl -X POST '{{API_SERVER}}/provider/deposit' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{"gs1s":"<Comma separated GS1s>"}'



Recommendations for Consumer Presentment



For Single Data String

Display the Single Data String as QR code to stay consistent with all display recommendations. If the QR code is not scannable, get the fetch_code and render as one dimensional Code-128 format. Also display the fetch_code below the one dimensional barcode so that the cashier can manually enter in case the screen is broken and one dimensional barcode is not scannable.



For Provider Bundle (bundle of only provider authorized offers)

Provider should implement bundling of their serialized data strings and present the expanded_bundle_id as a QR code. If the QR code is not scannable, render the bundle_id as one dimensional Code-128 barocde. Also display the fetch_code below the one dimensional barcode so that the cashier can manually enter in case the screen is broken and one dimensional barcode is not scannable.



For Universal Bundle (bundling across providers utilizing verified credential)

Provider could implement universal bundling and present the expanded_bundle_id as a QR code. If the QR code is not scannable, render the bundle_id as one dimensional barcode in Code128 format. Also display the fetch_code below the one dimensional barcode so that the cashier can manually enter in case the screen is broken and one dimensional barcode is not scannable.

NOTE: bundle_id, expired_coupon_id and fetch_code are the codes that are retrieved in real-time from a consumer's phone. These codes are valid for 5 minutes and will expire. Its recommended to refresh the code automatically without user action.

Retailer Getting Started Guide

When an AI (8112) serialized data string is scanned at the POS, the POS makes an API request to POF with that serialized data string. The POF will then return the serialized data string with a status of “success” or “Failure” – if “success,” it will also send offer details. The POS then uses offer details from the API response to validate offer against basket data and apply the discount or send a rollback response if the discount cannot be applied.

There are two main components to consider:

Redeem:
This is the primary API endpoint for TCB Positive Offer File functionality. The retailer sends scanned data string(s) to POF, and POF responds with one or more data strings with "success" or "failure" for each.

      "success" means the serialized data string is available for redemption.
      "failure" means the data string was already redeemed or was in some other way invalid.

Whenever the API returns any "success" response, it is also marking the relevant data string as "redeemed", meaning the same data string cannot be used more than once.

      On "success", the data string will be accompanied with offer details
      On "failure", the failure reason will be returned per data string

Data strings will be use in the "rollback" scenario described below.

Rollback:
It may be necessary to "rollback" a data string in the event that purchase requirements are not met or a failed payment.

Example Flows
Retailer calls the TCB "redeem" API as they scan GS1s during the checkout process.

  • In this flow, if a customer has 5 GS1s to scan, the retailer makes 5 calls to the TCB API during the checkout process. TCB will respond with applicable complete GS1s and "success" (valid) or "failure" (invalid) for each serialized GS1.
  • Before payment is processed, the retailer must determine which valid complete GS1s are applicable to the customer's basket, and apply discounts appropriately.
  • If any returned redeemed serialized GS1s are *not* applicable to the customer's basket, the TCB "rollback" API should be called for those un-applied serialized GS1s.
  • If the payment fails for any reason and the transaction itself is rolled back, the TCB "rollback" API should be called for all serialized GS1s previously returned by the TCB "redeem" API, whether or not they were applied to the basket.
Retailer scans GS1s during the checkout process, but waits to call the TCB "redeem" API until all items have been scanned.
  • In this flow, if a customer has 5 GS1s to scan, the retailer would scan GS1s during or at the end of the checkout process, and then make one single TCB "redeem" API call just before payment is processed. TCB will respond with a list of complete GS1s with "success" (valid) or "failure" (invalid) for each complete GS1.
  • After the "redeem" API call is made, the retailer should determine which redeemed serialized GS1s are applicable to the customer's basket and apply the discounts.
  • If any returned redeemed serialized GS1s are *not* applicable to the customer's basket, the TCB "rollback" API should be called for those un-applied complete GS1s.
  • If the payment fails for any reason and the transaction itself is rolled back, the TCB "rollback" API should be called for all serialized GS1s previously returned by the TCB "redeem" API, whether or not they were applied to the basket.

Step #1 : Get Access Token


curl -X POST '{{API_SERVER}}/access_token' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
--data '{ 
    "access_key": "ACCESS_KEY", 
    "secret_key": "SECRET_KEY" 
}'

The Access Token will be valid for 24 hours. You should cache it and use the same access token for next 23 hours 59 mins to call any other APIs.



Step #2.1 : Redeem a Coupon

curl -X POST '{{API_SERVER}}/retailer/redeem' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{
    "gs1s":"<Comma separated GS1s>",
    "selected_store":"<Store Internal ID>",
    "store_address":"<Store Address (E.g. Target 2417, N Haskel, Dallas)>",
  }'
        

How to handle "redeem" API responses

"redeem" API responses will be returned in a JSON array, with each item corresponding to a GS1 from the "gs1s" request array.
Response fields (per GS1 item):

  status -> "success" or "failure"
  newly_redeemed -> List of GS1s redeemed successfully
          {
            gs1: <GS1 redeemed>,
            master_offer_file: <Master offer file (base gs1) data string> Refer to master_offer_files mapping to get the purchase requirements
          }
  master_offer_files -> Master offer file purchase details


Example response for redeem

{
  "status": "success",
  "total_gs1s_processed": 3,
  "already_redeemed": [
      "811201777777754545412323432"
  ],
  "not_yet_live": [
      "8112013333333676767223234543"
  ],
  "newly_redeemed": [
      {
          "gs1": "811201777777754545412323433",
          "master_offer_file": "8112017777777545454"
      }
  ],
  "master_offer_files": {
      "8112017777777545454": {
          "primary_purchase_gtins": [
              "678987654323",
              " 876789876543"
          ],
          "second_purchase_gtins": [],
          "third_purchase_gtins": [],
          "primary_purchase_save_value": 100,
          "primary_purchase_requirements": 1,
          "primary_purchase_req_code": 0
      }
  },
  "message": "Added 1 gs1(s) as available to redeem",
  "execution_id": "9fc7f4db-c5ca-41c7-8a65-65be4bcd8e76",
  "execution_time_in_ms": 2405,
  "execution_start_time": 1587495466023
}
        
        



Step #2.2 : Rollback a Coupon

curl -X DELETE '{{API_SERVER}}/retailer/rollback/<GS1 to Rollback> \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' 
        

Clearinghouse Getting Started Guide

Retailer clearinghouse will be able to view the redemption report of authorized retailers. Retailers connected to The Coupon Bureau® will authorize a clearinghouse to do the final settlement with the manufacturer. Once the clearinghouse is authorized, they will be able to view the redemption data in realtime.

Step #1 : Get Access Token


curl -X POST '{{API_SERVER}}/access_token' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
--data '{ 
    "access_key": "ACCESS_KEY", 
    "secret_key": "SECRET_KEY" 
}'

The Access Token will be valid for 24 hours. You should cache it and use the same access token for next 23 hours 59 mins to call any other APIs.

Get Funder

This API will send back manufacturer settlement billing details for the Funder ID sent by the retailer clearinghouse.

curl -X GET '{{API_SERVER}}/clearinghouse/funder/FUNDER_ID' 
-H 'Content-Type: application/json' 
-H 'x-api-key: ACCESS_KEY' 
-H 'x-access-token: ACCESS_TOKEN'
          

Get Updated Funders List

This API can be used to get a list of all manufacturer settlement billing details that have changed within a specific date range.

curl -X GET '{{API_SERVER}}/clearinghouse/funders/updated_list/<FROM_DATE (YYYY-MM-DD)>/<TO_DATE (YYYY-MM-DD)>/<PAGE_NO (E.g. 0,1...)>' 
-H 'Content-Type: application/json' 
-H 'x-api-key: ACCESS_KEY' 
-H 'x-access-token: ACCESS_TOKEN'
        

Base GS1 Validation

The purpose of this API is to confirm that each base data string in a redemption file is valid and to return the offers details for any necessary audit.

curl -X GET '{{API_SERVER}}/clearinghouse/basegs1/<BASE_GS1>' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN'
        

Accelerator Getting Started Guide

Accelerators will facilitate retailer connectivity to The Coupon Bureau Positive Offer File. The Coupon Bureau will authorize an Accelerator to execute coupon redemption/ rollback on behalf of multiple retailers. Retailers will use this accelerator connectivity as their connection to The Coupon Bureau Positive Offer File (POF).

When an AI (8112) serialized data string is scanned at the POS, the POS makes an API request to POF with that serialized data string. The POF will then return the serialized data string with a status of “success” or “Failure” – if “success,” it will also send additional purchase requirement data. The POS then uses the additional purchase requirement data from the API response to validate offer against basket data and apply the discount or send a rollback response if the discount cannot be applied.

There are three main components to consider:

Get Connected Retailers:
Retailer will allow the accelerator to perform operation on their behalf. In this step, accelerator will pull the list of authorized retailers so that they can use the appropriate retailer_client_id while making the API calls

Redeem:
This is the primary API endpoint for TCB Positive Offer File functionality. The accelerator (on behalf of a retailer) sends scanned serialized data string(s) to POF, and POF responds with one or more serialized data strings. with "success" or "failure" for each.
   "success" means the serialized data string is available for redemption
   "failure" means the serialized data string was already redeemed or was in some other way invalid.

Whenever the API returns any "success" response, it is also marking the relevant complete serialized data string as "redeemed", meaning the same complete serialized data string cannot be used more than once.
   On "success", ", the serialized data string will be accompanied with offer details.
   On "failure", the failure reason will be returned per data string.

Data strings will be use in the "rollback" scenario described below.

Rollback:
Depending on the point of sale implementation, it may be necessary to "rollback" relevant data string redemptions. For example, if "redeem" is called before the point of sale confirms payment, and payment is rejected, any complete data strings previously "redeemed" during the checkout process must be rolled back.

Step #1 : Get Access Token


curl -X POST '{{API_SERVER}}/access_token' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
--data '{ 
    "access_key": "ACCESS_KEY", 
    "secret_key": "SECRET_KEY" 
}'

The Access Token will be valid for 24 hours. You should cache it and use the same access token for next 23 hours 59 mins to call any other APIs.

Step #2 : Get connected retailers.


Accelerator can perform operation (redeem / rollback) on behalf of an authorized retailer. Retailer connected to The Coupon Bureau® will authorize an Accelerator to do the work on their behalf.

curl -X GET '{{API_SERVER}}/accelerator/retailers' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN'           


Step #3.1 : Redeem a Coupon

curl -X POST '{{API_SERVER}}/retailer/redeem' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{
    "gs1s":"<Comma separated GS1s>",
    "selected_store":"<Store Internal ID>",
    "store_address":"<Store Address (E.g. Target 2417, N Haskel, Dallas)>",
    "retailer_email_domain":"<Retailer email domain>"
  }'                  

How to handle "redeem" API responses

"redeem" API responses will be returned in a JSON array, with each item corresponding to a GS1 from the "gs1s" request array.
Response fields (per data string item):

  status -> "success" or "failure"
  newly_redeemed -> List of data strings redeemed successfully
          {
            gs1: <data string redeemed>,
            master_offer_file: <Master offer file (base gs1) data string> Refer to master_offer_files mapping to get the purchase requirements
          }
  master_offer_files -> Master offer file purchase details


Example response for redeem

{
  "status": "success",
  "total_gs1s_processed": 3,
  "already_redeemed": [
      "811201777777754545412323432"
  ],
  "not_yet_live": [
      "8112013333333676767223234543"
  ],
  "newly_redeemed": [
      {
          "gs1": "811201777777754545412323433",
          "master_offer_file": "8112017777777545454"
      }
  ],
  "master_offer_files": {
      "8112017777777545454": {
          "primary_purchase_gtins": [
              "678987654323",
              " 876789876543"
          ],
          "second_purchase_gtins": [],
          "third_purchase_gtins": [],
          "primary_purchase_save_value": 100,
          "primary_purchase_requirements": 1,
          "primary_purchase_req_code": 0
      }
  },
  "message": "Added 1 gs1(s) as available to redeem",
  "execution_id": "9fc7f4db-c5ca-41c7-8a65-65be4bcd8e76",
  "execution_time_in_ms": 2405,
  "execution_start_time": 1587495466023
}
        
        


Step #3.2 : Rollback a Coupon

curl -X DELETE '{{API_SERVER}}/accelerator/rollback/<GS1>' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN'              

3rd Party Data Access

There are scenarios wherein you will need to fetch data from TheCouponBureau® to integrate and enhance your own SAAS platform. Imagine, your client #1 is managing their coupons inside your SAAS platform. Now, your client #1 is also subscribed to TCB as a Authorized partner. You are a SAAS provider and subscribed to TCB as Authorized partner. Your client #1 wants to manage coupons, view redemption report in your platform and the data is available in TCB database. To access data from TCB platform for your client #1,



Step #1 : Ask your client #1 to login to TCB from your portal

Construct TCB Access URL and redirect your client #1 to that URL. Your client #1 will login to TCB, on successful login, TCB will generate a temporary token and redirect to the URL you will specify while constructing the TCB Access URL. To construct the TCB Access URL, you need the followings

  • access_key You will get it from developer access page
  • secret_key: You will get it from developer access page
  • redirectURL: the URL which TCB will use to redirect on successful login. This URL will receive temp_token as GET parameter.
  • timestamp: Epoch timestamp. Click here to get the current epoch timestamp
TCB Access URL also needs a signature parameter to autheticate you. Use the below mentioned formula to calculate the signature value which you can append to the URL.
md5(access_key + redirectURL + timestamp + secret_key)
                    
Then you construct the TCB Access URL by sending access_key, redirectURL and signature as GET parameters.
{{API_SERVER}}/oauth_access?
  access_key=ACCESS_KEY&
  redirectURL=REDIRECT_URL&
  timestamp=TIMESTAMP&
  signature=CALCULATED_SIGNATURE
                    

TCB will then open a login window for your client #1 to login. It will also mention that, once you login, your data will be accessed by the SAAS provider.



On successful login, TCB will send a temp_token to the redirectURL.
redirectURL?temp_token=TEMPORARY_TOKEN                        
                    
use the temp_token to acquire the access_token which will be valid for 24 hours. To get the access_token, construct TCB Access Token URL by passing the temp_token and signature. You can calculate signature by using the following formula.
md5(temp_token + secret_key)
                    

Send a GET request to TCB Access Token URL to acquire access_token for your client #1
{{ API_SERVER }}/oauth_token?temp_token=TEMPORARY_TOKEN&signature=CALCULATED_SIGNATURE
                    

You should cache the access_token against your client #1 in your system to continue using it to make various API calls on your client's behalf. Client Access Token will be valid for 180 days. You should ask your client to relogin once the access_token had expired.

Near-realtime Webhook

If you need to receive realtime updates about the coupons (serialized data strings), you can register your webhook url and TCB will keep sending events in realtime. TheCouponBureau® backend will generate events on the below actions. If you are authorized to receive the event, TCB will send push message to your configured webhook so that you can process it as per your need.

Before you subscribe your HTTPS endpoint, you must make sure that the HTTPS endpoint has the capability to handle the HTTPS POST requests that TCB uses to send the verification, subscription confirmation and notification messages. Usually, this means creating and deploying a web application (for example, a Java servlet if your endpoint host is running Linux with Apache and Tomcat) that processes the HTTPS requests from TCB.


Webhook Registration

TheCouponBureau® backend will verify the ownership of the webhook endpoint by sending a series of HTTP POST requests. You have to code your webhook endpoint to make sure you respond to the HTTP POST requests appropriately to complete the registration successfully. If your endpoint fails to do so, TCB will show appropriate error message in the portal.



Step #1 : Save Webhook

Go to your homepage, click on Enterprise Setting, enter the webhook url and click save button. Your webhook url should be active. TCB backend will check the webhook by sending a HTTP POST request with body as shown below with Content-Type: text/plain; charset=UTF-8

POST / HTTP/1.1
Content-Length: 1336
Content-Type: text/plain; charset=UTF-8
x-amz-sns-message-type: TCBVerifier
Connection: Keep-Alive

{
  "TCBVerifier": "..."
}
                    
Your webook endpoint should return HTTP Status Code: 200. If it fails to do that, you will get an error message while saving the webhook.

TCB will try to connect with your webhook by sending a HTTP POST request with body as shown below with Content-Type: text/plain; charset=UTF-8
POST / HTTP/1.1
x-amz-sns-message-type: SubscriptionConfirmation
x-amz-sns-message-id: 165545c9-2a5c-472c-8df2-7ff2be2b3b1b
x-amz-sns-topic-arn: arn:aws:sns:us-west-2:123456789012:MyTopic
Content-Length: 1336
Content-Type: text/plain; charset=UTF-8
Host: example.com
Connection: Keep-Alive
User-Agent: Amazon Simple Notification Service Agent

{
  "Type": "SubscriptionConfirmation",
  "MessageId": "...",
  "Token": "...",
  "TopicArn": "...",
  "Message": "...",
  "SubscribeURL": "https://.....",
  "Timestamp": "...",
  "SignatureVersion": "...",
  "Signature": "...",
  "SigningCertURL": "..."
}
                    

Your code should parse the JSON document in the body of the HTTP POST request to read the name-value pairs that make up the TCB message. Use a JSON parser that handles converting the escaped representation of control characters back to their ASCII character values (for example, converting \n to a newline character). You can use an existing JSON parser such as the Jackson JSON Processor or write your own.

Once you convert the message to JSON, get the value of Type key. If Type is equal to SubscriptionConfirmation, your webhook endpoint should send a HTTP GET request to SubscribeURL to confirm the subscription. If Type is equal to Notification, your webhook endpoint should process the request as described below.



Step #2 : Process Incomming Request

A TCB push request looks like this example below. Note that the Message.data field is base64-encoded.

POST / HTTP/1.1
x-amz-sns-message-type: Notification
x-amz-sns-message-id: 165545c9-2a5c-472c-8df2-7ff2be2b3b1b
x-amz-sns-topic-arn: arn:aws:sns:us-west-2:123456789012:MyTopic
Content-Length: 1336
Content-Type: text/plain; charset=UTF-8
Host: example.com
Connection: Keep-Alive
User-Agent: Amazon Simple Notification Service Agent

{
  "Type" : "Notification",
  "MessageId": "...",
  "Message": {
    "data": "SGVsbG8gQ2xvdWQgUHViL1N1YiEgSGV..........."
  },
  "SignatureVersion": "1",
  "Signature": "...",
  "SigningCertURL": "...",
  "UnsubscribeURL": "..."
}
                    
Your webhook needs to handle incoming messages and return an HTTP status code to indicate success or failure. A success response is equivalent to acknowledging a message. The status codes interpreted as message acknowledgements by the TCB backend system are: 200, 201, 202, 204. A success response might look like this:
204 No Content
                    

If your webhook does not return a success code, TCB attempts up to three retries with a delay between failed attempts set at 20 seconds. Once you decode the Message.data, you will get the below JSON. event_timestamp will be in Unix epoch format. It will be the the number of milliseconds that have elapsed since January 1, 1970 (midnight UTC/GMT), not counting leap seconds (in ISO 8601: 1970-01-01T00:00:00Z).

Events generating webhook push message

There are 4 types of actions generates webhook push message

  • Action on Serialized GS1s (All stakeholders connected to this gs1 will get webhook push)
    • Deposit by provider (action: deposited)
    • Delete by provider (action: deleted)
    • Redemption by accelerator or retailer (action: redeemed)
    • Rollback by accelerator or retailer (action: rollback)
    • Store updation by accelerator or retailer (action: update_store)
    • Short code updation by provider (action: update_short_code)
  • Action on Brand (by manufacturer) (Manufacturer and the authorized partner associated with this brand will get webhook push)
    • Brand creation (action: brand_create)
    • Brand deletion (action: brand_delete)
    • Brand updation (action: brand_update). Following action will result in brand_update event push.
      • Update brand name
      • Assign primary provider to brand
      • Remove primary provider from brand
      • Update brand image
  • Action on Master Offer File (by manufacturer or authorized partner) (Manufacturer, authorized partner and providers associated with this mof will get webhook push). Accelerators will also get webhook push for any purchase requirement change. Accelerator can use this to update locally synced master offer file purchase requirements for faster processing.
    • MOF creation (action: mof_create)
    • MOF updation (action: mof_update)
    • MOF deletion (action: mof_delete)
  • Webhook push for reports. (action: report). When you issue a command to generate report, internally TCB creates and returns a job id. The job will be executed in the background and when the report is ready, it will be sent as a webhook push.


Message Format: Action on Serialized GS1s

In case of deposit event, below message will be pushed to webhook
{
  gs1: 'GS1 data string (coupon)', 
  action: 'deposited',
  primary_signature: '...',
  secondary_signature: '...',
  provider: { email_domain: 'qples.com' },
  event_timestamp: ...,
  did_user: 'Optional. If verifiable credential is used while depositing',
  caller: 'Base64 encoded caller object'
}
                    

In case of delete event (serialized data string is deleted by provider), below message will be pushed to webhook
{
  gs1: 'GS1 data string (coupon)', 
  action: 'deleted',
  primary_signature: '...',
  secondary_signature: '...',
  provider: { email_domain: 'qples.com' },
  event_timestamp: ...,
  did_user: 'Optional. If verifiable credential is used while depositing',
  caller: 'Base64 encoded caller object'
}
                    

In case of rollback event (redeemed serialized data string is roll backed by retailer / accelerator), below message will be pushed to webhook
{
  gs1: 'GS1 data string (coupon)', 
  action: 'rollback',
  primary_signature: '...',
  secondary_signature: '...',
  retailer: { email_domain: 'qples.com' },
  did_user: 'Optional. If verifiable credential is used while depositing',
  event_timestamp: ...,
  caller: 'Base64 encoded caller object'
}
                    

In case of redemption event, there will be an additional information passed (redeemed_at_store) to the webhook endpoint
{
  gs1: 'GS1 data string (coupon)', 
  action: 'redeemed',
  primary_signature: '...',
  secondary_signature: '...',
  redeemed_at_store: { store_id: '777', store_address: 'Store 1' },
  did_user: 'Optional. If verifiable credential is used while depositing',
  retailer: { email_domain: 'qples.com' },
  event_timestamp: ...,
  caller: 'Base64 encoded caller object'
}
                    

In case of store updation event, there will be an additional information passed (updated_store_info) to the webhook endpoint
{
  gs1: 'GS1 data string (coupon)', 
  action: 'update_store',
  primary_signature: '...',
  secondary_signature: '...',
  retailer: { email_domain: 'qples.com' },
  did_user: 'Optional. If verifiable credential is used while depositing',
  store: { selected_store: '7778', store_address: 'Stpore 1' },
  caller: 'Base64 encoded caller object'
}
                    

In case of short code updation event, there will be an additional information passed (new_code) to the webhook endpoint
{
  gs1: 'GS1 data string (coupon)', 
  action: 'update_short_code',
  primary_signature: '...',
  secondary_signature: '...',
  new_code: '...' // Updated code,
  event_timestamp: ...,
  caller: 'Base64 encoded caller object'
}
                    

Message Format: Action on Brand

In case of any brand creation, below message will be pushed to webhook
{
  brand_id: '', 
  email_domain: 'manufacturer email domain',
  action: 'brand_create',
  primary_signature: '...',
  secondary_signature: '...',
  event_timestamp: ...,
  caller: 'Base64 encoded caller object'
}
                    

In case of any brand deletion, below message will be pushed to webhook
{
  brand_id: '', 
  email_domain: 'manufacturer email domain',
  action: 'brand_delete',
  primary_signature: '...',
  secondary_signature: '...',
  event_timestamp: ...,
  caller: 'Base64 encoded caller object'
}
                    

In case of any brand updation, below message will be pushed to webhook
{
  brand_id: '', 
  email_domain: 'manufacturer email domain',
  action: 'brand_update',
  primary_signature: '...',
  secondary_signature: '...',
  event_timestamp: ...,
  caller: 'Base64 encoded caller object'
}
                    

Message Format: Action on Master Offer File

In case of master offer file creation / updation event, following message will be pushed to webhook
{
  base_gs1: '',
  action: 'mof_update', 
  primary_signature: '...',
  secondary_signature: '...',
  event_timestamp: ...,
  email_domain: 'manufacturer email domain',
  updated_mof_encoded: 'Base64 encoded master offer file object',
  caller: 'Base64 encoded caller object'
}
                    

In case of master offer file deletion event, following message will be pushed to webhook
{
  base_gs1: '',
  internal_id: '', // This will come only in mof_delete action
  action: 'mof_delete', 
  primary_signature: '...',
  secondary_signature: '...',
  event_timestamp: ...,
  email_domain: 'manufacturer email domain',
  updated_mof_encoded: 'Base64 encoded master offer file object',
  caller: 'Base64 encoded caller object'
}
                    

Use the atob library in NodeJS to convert the updated_mof_encoded back to master offer file object. var actual = JSON.parse(atob(updated_mof_encoded));

updated_mof_encoded object will have the following information. You can keep the information in your own database to track changes in the master offer file.

{
  internal_id: ,
  brand_id: , 
  base_gs1: , 
  description: , 
  campaign_start_time: , 
  campaign_end_time: , 
  redemption_start_time: , 
  redemption_end_time: , 
  rolling_expiration: , 
  rolling_expiration_days: , 
  total_circulation: , 
  primary_purchase_save_value: , 
  primary_purchase_requirements: , 
  primary_purchase_req_code: , 
  primary_purchase_gtins: , 
  additional_purchase_rules_code: , 
  second_purchase_requirements: , 
  second_purchase_gs1_company_prefix: , 
  second_purchase_req_code: , 
  second_purchase_gtins: , 
  third_purchase_requirements: , 
  third_purchase_gs1_company_prefix: , 
  third_purchase_req_code: , 
  third_purchase_gtins: , 
  save_value_code: , 
  applies_to_which_item: , 
  store_coupon: , 
  donot_multiply_flag: , 
  providers: , 
  active: , 
  campaign_metadata: 
}
                                          

Message Format: Webhook push for report

In case of any query initiation inside TCB platform, report will be sent to the webhook endpoint
{
  reportUrl: 'CSV report url. This URL is valid for 5 days', 
  action: 'report',
  job_id: 'The job id will be returned when you run the query',
  primary_signature: '...',
  secondary_signature: '...',
  event_timestamp: ...
}
                    

Caller object will have the following information identifying the caller (portal user or API key identified using access_key) who did the action. This will be a base64 encoded JSON object. To get the actual JSON object, var caller = JSON.parse(atob(caller)); (NodeJS Code).
{
  identity: 'email address (portal user) or access_key (api user)', 
  access_type: 'portal or api',
  email_domain: '',
  source_ip: ''
}
                    

Primary / Secondary signature will help you validate that the message is originated at TheCouponBureau® server and it is intended for you. As soon as your callback is approved (Enterprise Setting page), you will see two secret keys (primary and secondary) associated with your callback.

TheCouponBureau® backend will sign the message before pushing to your webhook using both primary and secondary keys and send those to your webhook as primary_signature / secondary_signature. Webhook implementation should recalculate the signatures and proceed execution if any one of the signatures matches.

  • primary_signature will be calculated using Primary Callback Secret
  • secondary_signature will be calculated using Secondary Callback Secret
Follow the below process to calculate the signature value (if value of the action key is "deposited" | "deleted" | "redeemed" | "rollback" | "update_store")

primary_signature = md5 ( concat(gs1 + action + primary callback secret) )

secondary_signature = md5 ( concat(gs1 + action + secondary callback secret) )
                    

Follow the below process to calculate the signature value (if value of the action key is "report")

primary_signature = md5 ( concat(reportUrl + action + job_id + primary callback secret) )

secondary_signature = md5 ( concat(reportUrl + action + job_id + secondary callback secret) )
                                          

Follow the below process to calculate the signature value (if value of the action key is "brand_create" | "brand_update" | "brand_delete")

primary_signature = md5 ( concat(brand_id + action + primary callback secret) )

secondary_signature = md5 ( concat(brand_id + action + secondary callback secret) )
                                          

Follow the below process to calculate the signature value (if value of the action key is "mof_create" | "mof_update" | "mof_delete")

primary_signature = md5 ( concat(base_gs1 + action + updated_mof_encoded + primary callback secret) )

secondary_signature = md5 ( concat(base_gs1 + action + updated_mof_encoded + secondary callback secret) )
                                          

Two secret keys concept will enable you rotate the key in case you want to change your keys. Here if the process you can use to safely rotate two keys.

  • Regenerate primary secret
  • Key change will take some time to reflect across TCB backend cluster
  • In the meantime, your backend will keep matching secondary_signature value
  • Once the key change is reflected across TCB cluster, which will take atleast 300 seconds, your primary_signature will start matching
  • You can now safely regenerate secondary secret
  • Your backend will keep matching primary_signature for sometime till secondary key will get stabilised in TCB cluster

Your webhook should calculate both signatures and continue if any one of the signatures matches. This will enable your to make sure that the messages are generated from TCB backend and not from other sources. As your endpoint is publicly available, its highly recommended to implement and validate signatures before processing the messages.

NOTE: Duplicate Message

TCB backend follows AT LEAST ONCE delivery mechanism. This means your webhook might receive duplicate messages. Its recommended to make your webhook idempotent using the MessageId key which will be passed along with every message.

Retry window

If the initial delivery of the message fails, TCB attempts up to three retries with a delay between failed attempts set at 20 seconds.

Embeddable Widgets

Extend your own SaaS platform by embedding TheCouponBureau® Master Offer File management widgets as iframe. There are three widgets available to embed.

  • Create Master Offer File Widget
  • Manage Your Master Files Widget
  • Edit Your Master File Widget


Step #1 : Get Access Token

curl -X POST '{{API_SERVER}}/access_token' \
-H 'Content-Type: application/json' \
--data '{ 
    "access_key": "ACCESS_KEY", 
    "secret_key": "SECRET_KEY" 
}'
                    



Step #2 : Create Widget Link

You have to pass following query parameters to load the secure widgets.

  • x-api-key
  • x-access-token

E.g. WIDGET_URL?x-api-key=...&x-access-token=...

NOTE: Access token acquired via 3rd party data access protocol will also work here. Widget link will be active till the access token expires.



Create Master Offer File Widget Link

{{API_SERVER}}/enterprise/product/Manufacturer/create_mof/noheader?x-api-key=ACCESS_KEY&x-access-token=ACCESS_TOKEN
                    



Manage Master Offer Files Widget Link

{{API_SERVER}}/enterprise/product/Manufacturer/my_mofs/noheader?x-api-key=ACCESS_KEY&x-access-token=ACCESS_TOKEN
                    



Edit Master Offer File Widget Link

{{API_SERVER}}/enterprise/product/Manufacturer/my_mofs/noheader?x-api-key=ACCESS_KEY&x-access-token=ACCESS_TOKEN&base_gs1=BASE_GS1
                    

Local Master Offer File Validation During Redemption

Accelerators and Retailers can make use of TCB's master offer file sync API to create a local database to speed up the redemption process. This process will eliminate the need of redemption API call if the basket does not match with the purchase requirements.


Sync API (/syncmof/:from_date/:to_date/:mode)

Use this API to pull all master offer files purchase requirements into your server for faster processing. Use created mode first to fetch all the master offer files created till date in the selected date range. Then use updated mode to fetch the master offer files that are updated. We recommend running sync mof api call with updated mode in every day to keep your local database up to date. This API needs webhook setup. TCB runs the query in background, generate a file and send the file url via webhook as soon as its ready.

The webhook message will look like this

{
  reportUrl: 'CSV report url. This URL is valid for 5 days', 
  action: 'report',
  job_id: 'The job id will be returned when you run the query',
  primary_signature: '...',
  secondary_signature: '...',
  event_timestamp: ...
}
                  

CSV file will include the followings (CSV File Header).
"primary_purchase_gtins","second_purchase_gtins","third_purchase_gtins","settled","base_gs1","campaign_start_time","campaign_end_time","redemption_start_time","redemption_end_time","primary_purchase_save_value","primary_purchase_requirements","primary_purchase_req_code","additional_purchase_rules_code","second_purchase_requirements","second_purchase_gs1_company_prefix","second_purchase_req_code","third_purchase_requirements","third_purchase_gs1_company_prefix","third_purchase_req_code","save_value_code","applies_to_which_item","store_coupon","donot_multiply_flag","update_datetime"
                  

reportUrl file is public and will be valid for 5 days. You could download the file and parse it to get the master offer file purchase requirements. Sample parsing code in NodeJS (using fast-csv library)
const fs = require('fs');
const path = require('path');
const csv = require('fast-csv');

fs.createReadStream(path.resolve(__dirname, '', 'file.csv'))
    .pipe(csv.parse({ headers: true }))
    .on('error', error => console.error(error))
    .on('data', row => console.log(row))
    .on('end', rowCount => console.log(`Parsed ${rowCount} rows`));
                  

fast-csv will convert every row to a JSON object and every key in the JSON object will be converted to string. You need to do appropriate formatting of the keys as defined in Master Offer File Creation API before storing in your local database.


Use Local Database during coupon redemption

There are multiple ways coupons can be presented by consumers at the checkout counter.

  • Single 8112 data string: This will start with either 81120 or 81121 and length of the string > 14
      Local database can be used in this scenario. Click here to get the parsing logic (in NodeJS) to extract the base_gs1 which you can use to get the purchase requirement from your local database.
  • Fetch Code: This will start 8112 and have fixed lengh (14)
      Local database can not be used in this scenario. Call redemption API directly with this string to retrieve the purchase requirements.
  • Bundle: This will start 81125. Bundling of coupons is one of the fundamental features recommended by Coupon Bureau and our consumer app ecosystems created by providers apps and wallets will have this in built. This will enable consumers to select up to 15 coupons and then bundle them together into a single barcode to reduce the no of scans at the checkout counter. The Coupon Bureau supports two bundling formats.
    • Simple Bundle: Displayed as a Code128 barcode
        Local database can not be used in this scenario. Use the redemption API directly.
    • Expanded Bundle (with MOF data): Displayed as a QR code.
        Local database can be used in this scenario. Click here to get the parsing logic (in NodeJS) to extract the base_gs1s and bundle_id. With the base_gs1s in hand, you will be able to use local database to extract the purchase requirements and validate basket. When the basket validation is done and you have identified the base_gs1s that are not applicable for this transaction, you will exclude these base_gs1s from the bundle by passing appropriate value in exclude_from_bundle parameter duing redemption. Click here to understand how you need to format the data for exclude_from_bundle parameter.


Without Local Database

For retailers and accelerators not using local database validation, any code presented (fetch_code, 8112 data string, bundle id, expanded_bundle_id) will be passed using TCB redemption API. We recommend two phase redemption process. First phase with pre_process flag, which will return the exact same response without doing actual redemption. This process will help Retailers and Accelerators get the purchase requirements. Then the basket validation will happen and once the appropriate data stings are identified for the transaction, redeem the data strings with pre_process flag "no".


Recommended Local Database Workflow

Below is a possible workflow to process redemption with local database efficiently. This process will update the local database in real time if the the master offer files are missing from local database or if there is any changes in the purchase requirements. You can use this approach without the sync API call. This approach will eventually build the local database as the redemption happens.

Offline Redemption

In response to a request to find a solution for in-store, offline redemptions, we have created the following approach. This approach will allow Retailers and Accelerators to use a local database to retrieve purchase requirements for a given data string allowing for basket adjudication even when a retailer’s internet is down. When systems come back online, any redemptions captured during the offline period can be synced back up with TCB. TCB platform supports 20 offline coupon redemption per store per day.

Verification that is not possible through this process will be verification of the serial number and redemption dates. Because of this, retailers will need to assume verification, potentially increasing the risk for accepting invalid coupons. We recommend at least 3 retries before you fall back to the offline mode. Most provider consumer experiences remove used coupons or invald coupons increasing the probability that the serialized data string provided in the offline environment is valid.


Step #1 : Get Master Offer File Purchase Information

To do this, you need to sync master offer files with TCB. Please follow the "Local MOF Validation" document to understand how to do this locally.


Step #2 : Local redemption

Apply the serialized data string with the assumed verification previously explained . Store these serialized data strings in your local database and make sure to lookup in your local database so that the serialized data string is applied only once. This step is imperative to ensure only one offline redemption occurs per serialized data string. To sync these locally stored serialized data strings, you need to pass offline: yes while redeeming the coupon.

curl -X POST '{{API_SERVER}}/retailer/redeem' \
-H 'Content-Type: application/json' \
-H 'x-api-key: ACCESS_KEY' \
-H 'x-access-token: ACCESS_TOKEN' \
--data '{
    "gs1s":"<Comma separated GS1s>",
    "selected_store":"<Store Internal ID>",
    "store_address":"<Store Address (E.g. Target 2417, N Haskel, Dallas)>",
    "offline": "yes"
}'
                    

If the serialized gs1 is redeemed with an offline flag, you will not be allowed to roll back this coupon. This is because TCB will assume that this serialized gs1 was applied without redeeming as there was no internet connection at that time. So you need to be 100% sure before marking the serialized data string as offline redeemed.


How we handle the offline redemption internally

When you redeem, the serialized data string will have the following states. Here is how the TCB platform internally handles each case.

  • newly_redeemed
    • This is a valid use case. This means that the serialized gs1 was valid and not used before. TCB will mark it as redeemed. This case will not break TCB single-use coupon promise. As TCB coupons are digital and will stay in the provider app, you can expect this case in most of the offline redeemed cases.
  • already_redeemed
    • This means that the serialized data string was already redeemed. TCB will internally add a flag so that we can detect double redemption. We expect this to be a rare occasion.
  • store_mismatch
    • This means that the serialized data string was not for the selected store. TCB will internally redeem this coupon and mark the redemption error condition for future tracking.
  • invalid_gs1s
    • Accelerator and Retailers should validate the serialized data string format before accepting this for offline redemption. This condition should never arise.
  • mof_not_found
    • This means the master offer file associated with this serialized gs1 is not there in the TCB database. This condition should not arise as the accelerator or retailer should validate the purchase requirements using a local database which would never have a copy of the master offer file in this case.
  • serialized_gs1_not_found
    • This means that this serialized gs1 was not deposited by any provider before. This should never arise as the provider app displays the serialized data string barcode.TCB will internally deposit this coupon and redeem it and mark the redemption error condition. We record this serialized gs1 just to make sure the settlement happens correctly.
  • expired
    • This means that this serialized gs1 was expired. TCB will mark this as redeemed so that settlement happens correctly.

As this process is designed to handle extreme conditions (no internet connectivity) and is crafted specifically for customer satisfaction. TCB internally imposes a limit to reducing its effect. Accelerators and Retailers will have to code their offline redemption so that it works under this limit.
LIMIT: 20 OFFLINE REDEMPTION PER STORE PER DAY

Universal (Cross Provider) Bundling

TCB has partnered with Hedera Hashgraph to enable universal bundling through the use of decentralized identities and verifiable credentials. Universal Bundling will allow shoppers to cross bundle coupons across distribution providers, creating the opportunity to bundle all of their coupons into a single barcode, all without having to share their personally identifiable information.

Hedera is the most used enterprise grade public network backed by reputed governing council. Click here to view hedera echosystem. The Hedera proof-of-stake public network, powered by Hashgraph Consensus, achieves the highest grade of security possible (ABFT). With industry-leading transaction speeds and incredibly low bandwidth consumption, it makes it an ideal partner for TCB.


Decentralized Identity and Verifiable Credential

In identity management, a distributed ledger (a “blockchain”) enables everyone in the network to have the same source of truth about which credentials are valid and who attested to the validity of the data inside the credential, without revealing the actual data. Click here to see W3C's Decentralized Identifier (DIDs) specification.


How to execute Universal Bundling :


Step #1 : Acquire user's verifiable credential.

Use TCB's initiate_auth and verify_auth API to acquire user's verifiable credential against a phone number. Coupon provider would have to associate the verifiable credential with it's own user. The verifiable credential will be valid till its revoked. TCB will issue the verifiable credential for the coupon provider and only the coupon provider will be able to revoke it using TCB's revoke VC api.


Step #2 : Associate serialized gs1s with the user using verifiable credential.

This can be achieved while depositing the serialized gs1 using the TheCouponBureau Deposit API. Deposit API takes VC(verifiable credential) as an optional parameter. This will ensure that the coupon provider user’s personal identifier is not exposed to TCB. Coupon provider would use the TCB's API to get VC as a two-factor authentication.



Step #3: Get coupons associated with the user

Once you have a valid verifiable credential for the user (issued by TCB Authorized Identity provider), you would query user coupons using Get User Coupons API. This API takes a valid VC and returns coupons associated with the decentralized identity embedded inside the VC.

curl -X POST '/ub/user/coupons'
-H 'Content-Type: application/json' 
-H 'x-api-key: API_KEY' 
-H 'x-access-token: ACCESS_TOKEN' 
--data '{"vc":"BASE 64 Encoded Verifiable Credential"}'
                    

This retuns coupons assocaited with the user.
{
    "status": "success",
    "coupons": [
        {
            "description": "Save 1 Desc",
            "brand": "Izzy's Ice Cream",
            "coupon_id": "618fd060684ffb53bf9b31c1",
            "valid_till": "2021-12-10",
            "valid_till_human_readable": "10 December, 2021",
            "serialized_gs1": "811201151919110043248437766566",
            "title": "Save 1 Title",
            "image_url": "https://...",
            "terms": "...",
            "dollar_amount": 2
        }
    ],
    "coupons_others": [
        {
            "coupon_id": "61934bd654b025258cf7935c",
            "valid_till": "2021-12-10",
            "valid_till_human_readable": "10 December, 2021",
            "image_url": "https://...",
            "dollar_amount": 2
        }
    ],
    "execution_id": "ca90c720-a1ba-4b21-9008-050416790988",
    "execution_time_in_ms": 825,
    "execution_start_time": 1587556027311
}
                    

TCB neither exposes the provider who deposited the coupon nor the serialized data string. Instead, it returns a coupon_id which is an internal id associated with each serialized data string inside the TCB database. You could use these coupon_ids to generate a cross-provider bundle.




Step #4 : Generate Universal (Cross Provider) Bundle

Once you have retrieved the coupon IDs associated with a user, using the verifiable credentials of the same user, you could ask TCB to generate a bundle for the coupons. You could bundle a maximum of 20 coupons in one transaction. Please note that the generated bundle identifiers are not fixed and expire in 300 seconds. Your app needs to keep refreshing the bundle barcode if the time to redeem the bundle exceeds 5 mins.

curl -X POST '/ub/user/coupons/bundle/custom'
-H 'Content-Type: application/json' 
-H 'x-api-key: API_KEY' 
-H 'x-access-token: ACCESS_TOKEN' 
--data '{"vc":"BASE 64 Encoded Verifiable Credential", coupon_ids: ['...', '...']}'
                    
This API will return a bundle identifier which you can redeem within 5 minutes of generation.
{
    "status": "success",
    "bundle_id": "8112.....",
    "coupons": [
        {
            "description": "Save 1 Desc",
            "brand": "Izzy's Ice Cream",
            "coupon_id": "618fd060684ffb53bf9b31c1",
            "valid_till": "2021-12-10",
            "valid_till_human_readable": "10 December, 2021",
            "serialized_gs1": "811201151919110043248437766566",
            "title": "Save 1 Title",
            "image_url": "https://...",
            "terms": "...",
            "dollar_amount": 2
        }
    ],
    "execution_id": "ca90c720-a1ba-4b21-9008-050416790988",
    "execution_time_in_ms": 825,
    "execution_start_time": 1587556027311
} 
                    
Bundle identifier starts with 8112.

AI (8112) data string formats and processing

There are multiple ways coupons can be presented by consumers at the checkout counter. Each is necessary for accomplishing the unique needs of the shopper.


Data string formats:

  • Single standard AI (8112) data string: This will start with either 81120 or 81121 with a maximum length of 40 digits
  • Fetch Code: This will start with 8112 and have a fixed length (14 digits)
    • The Fetch Code is a shortened data string that appears on a consumer's phone in the event the barcode cannot be scanned and an alternative data string is required for manual entry.
  • Bundle: This will start 81125.
    • Bundling of coupons is one of the fundamental features that will enable consumers to select up to 15 coupons and then bundle them together into a single barcode to reduce the number of scans at the checkout counter. The Coupon Bureau supports two bundling formats.
      • Simple Bundle: A single 27-28 digit data string starting with 81125
      • Expanded Bundle: series of standard AI (8112) data strings in a single scannable barcode
        • This execution is built for use of local database authentication. To learn more about local database authentication and expanded bundle assembly, visit Local MOF Validation.


Processing recommendations:

For retailers and accelerators not using local database validation, any code presented (fetch_code, 8112 data string, bundle id, expanded_bundle_id) will be passed using TCB redemption API. We recommend two phase redemption process. First phase with pre_process flag, which will return the exact same response without doing actual redemption. This process will help Retailers and Accelerators get the purchase requirements. Then the basket validation will happen and once the appropriate data stings are identified for the transaction, redeem the data strings with pre_process flag "no".

  • Bundle ID
    • 27-28 digit data string that starts with 8112
    • Process
      • Scanned as usual
      • Sent to TCB
      • TCB will unbundle and send offer purchase requirements to POS for processing as usual
  • Fetch code
    • Manual code for broken phone
    • Process
      • Typed in by cashier
      • Sent to TCB
      • TCB will retrieve data string, authenticate and send offer purchase requirements to POS for processing as usual
  • Series of coupons in a single QR code
    • Create to support local database validation
    • If not using local database validation, all data strings sent to TCB as usual
    • All QR codes will have back up code-128 barcode