Magic Receipts API

This page describes how to set up and use the Magic Receipts API

OVERVIEW:

Magic Receipts allows users to snap pictures of their grocery receipts and earn awards when their purchases contain promoted product (offers). Offers have specified restrictions such as expiration date, price minimum, store , quantity, and varietal limitations ( must match specific UPCs).

Physical receipt submissions must include a clear photo that contains the entire receipt: Store Name, Date, Product, and Sub-Totals. Receipts must be original and not previously used for another incentivized shopping program.

Upon submission, members will be informed of of success or failure. A success will initiate an Award Pending status. A failure we yield an accompanying Error Code (reason) with an option to resubmit for success or request “Manual Review” (2-3 business days processing time)

There are four possible statuses:

  • AWARD_PENDING
  • APPROVED
  • REJECTED
  • MANUAL_REVIEW

Once an offer is APPROVED, it cannot transition to another status. However, a status of the other 3 can be transitioned to a another status.

📘

The API does only return magic receipts offers for US and CA.

CORE FUNCTIONALITY:

A successful Magic Receipts Integration will allow:

  • Retrieve current available offers and metadata to display to users
  • Retrieve list of supported merchants and associated available offers
  • Retrieve list of categories and associated available offers
  • MY List - retrieve list of offers that member has indicated as interested in.
  • Receipt Upload - Send call to BitLabs with photo, offers indicated, store indicated
    • Offer Upload Response
    • Offer Status Changes

MAGIC RECEIPTS ENDPOINTS:

  • Get access token for magic receipts endpoint requests
  • OFFERS LIST: instore-offers-short
  • OFFER DETAILS: instore-Offer-Details
  • CATEGORIES: Get-Category-Types
  • In-Store-Receipt-Validation
  • In-Store-Manual-Review
  • Get-Instore-Merchants
  • Post Offers( My List) Endpoint
  • In-Store-Manual-Review-Offer

Get access token for magic receipts

This will return an access token for a user which you need to provide in the magic receipts endpoint requests. A token is only valid for 2 hours and therefore needs to be requested again after it is no longer valid.

curl \
 -X GET https://api.bitlabs.ai/v1/client/magic-receipts/access-token \
 -H "X-Api-Token: $API_KEY" \
 -H "X-User-Id: $API_KEY"

All other endpoint requests have to be made from https://receipts.bitlabs.ai

Generating a token, requires you to have a BitLabs account. You can create one here: https://dashboard.bitlabs.ai/


Instore Offers Short Endpoint

Description

This endpoint gets the list of offers for a logged in member

curl \
-X GET https://receipts.bitlabs.ai/api/instore-offers-short \
-H "Authorization: Bearer <token>"

Response Parameters

Param NameValue(s)
status200 (success), 400 (failure)
dataarray[] of offers.

Offer Fields

NameTypeDescription
addedToListbooleanif the offer is added to the users list
anyReceiptEligiblebooleanif the offer is an any receipt these are given special treatment as they will accept any receipt
bannerImageUrlstringthere are several sizes for images from rectangular to square this is the rectangular ones typically used for a banner
baseAmountintegerthis is the cashback amount in an integer format
bonusobjectnot really relevant at this time
buyingOptionsbuyingOptions ObjectSee additional documentation below for buyingOptions
categoryIDsinteger[]These are the categories that the offer is included within
detailUrlstringthis is the url the links to the offer details view
eligibleMediumsthis is an enum[] and will contain either INSTORE or ONLINEOut of the gate we will only offer support for the INSTORE variant
expirationDatea string formatted version of the expiration dateThis is the date that the offer expires and is inclusive (if the end date is today then today is still valid)


It will look like this expirationDate: "02/14/2024",
imageUrlstringImage url for the offer will often coincide with the square image url
isIncentivizedbooleanDelineates between a high value offer or not. We have house offers that are loss leaders and this is what sets them apart.

Typically we add a star to the offer to highlight it’s importance as a higher paid offer.
isQuantitySelectionEnabledbooleanWe allow users to select the quantity or amount of line items that are on their receipt. If that quantity differs from what we parsed we will send their receipt into manual review for closer inspection.
line1stringThis was poorly named but you can think of this as the offer title
line3stringEqually poorly named this is the actual cashback value to the user formatted as
"line3": "$4",
line4stringThis is the string formatted cashback value in the client currency
"line4": "400 SB",
line6stringThis is the string formatted cashback value in the client currency with “Cash Back” appended
"line6": "$4 Cash Back",
notManyLeftbooleanDetermines if there aren’t a lot of these offers left. On our O&O we show small “not many left” banner
offerIDintegerThis is the offer id
purchaseQuantityintegerThis is the minimum required quantity a user will be required to buy to get the offer.

Be forewarned a lot of this logic was moved into the buying options which defines if there are multiple goals like “buy 1” or “buy 2”
redemptionsPerClaimintegerthis has mostly been deprecated
restrictedToMerchantsbooleanboolean value delineating if this offer is restricted to instore merchants or if it is available at all merchants
restrictedToMerchantsOnlinebooleanboolean value delineating if this offer is restricted to online merchants or is available at all online merchants

At this time online uploads are not supported
restrictToMerchantsCountintegerthe amount of merchants this offer is restricted to
restrictToMerchantsShorta dto[] { "logoUrl": "https://ucontent.prdg.io/img/instore/logos/logo-1.png?v=1694019930000", "merchantID": 1, "merchantName": "Walmart" },This will list a sublist of the merchants that the offer is available at with additional data like logos + name + merchantID.

Expect this sublist to be variable but presume it to be set at 5.
shortDescriptionstringThis is the description of the offer. Expect this to be a few words at most
showUpTobooleanthis determines if we should show the “Up To” description on the offer card before the payout amount.

”400 SB”
vs
”Up To 400 SB”

Buying Options Fields

NameTypeDescription
awardFormattedstringThe string formatted reward value in the clients currency

"awardFormatted": "150 SB",
cashbackAmountdoubleThe reward amount in dollars

"cashbackAmount": 1.5,
cashbackFormattedstringThe string formatted reward amount in dollars formatted like so:

cashbackFormatted": "$1.50",
goalDescriptionstringThis is the description of the goal so there might be a buy1 or a buy 2 and this is the description for it

"goalDescription": "Buy 1 pack of SweeTARTS Gummies Fruity Splitz",
payoutAmountdoubleThe reward amount in the clients currency

"payoutAmount": 400,
requiredQuantityintegerThis is the required amount of the product that the user is expected to purchase to meet this goal.
requiredSpendFormattedExpect to mostly see required quantity. This is a separate kind of goal that requires the user to spend a certain amount on an offer rather than purchase a certain number
useGoalDescriptionbooleanTypically the goal will look something like the following:

Buy any 1 eligible product

were we pull in the required quantity. If this is enabled we display the description from the goal instead.

In practice this is mostly not used.
useRequiredSpendbooleandetermines if required spend is used. This is almost never enabled.

Example Response:

{  
    "bonus": null,  
    "data": \[  
        {  
            "addedToList": true,  
            "anyReceiptEligible": false,  
            "bannerImageUrl": "<https://ucontent.prdg.io/pimages/96/96773959-73c5-4c8c-8cdc-f5178860c012.jpg">,  
            "baseAmount": 400,  
            "bonus": null,  
            "buyingOptions": \[  
                {  
                    "awardFormatted": "150 SB",  
                    "cashbackAmount": 1.5,  
                    "cashbackFormatted": "$1.50",  
                    "goalDescription": "Buy 1 pack of SweeTARTS Gummies Fruity Splitz",  
                    "payoutAmount": 150,  
                    "requiredQuantity": 1,  
                    "requiredSpendFormatted": null,  
                    "useGoalDescription": false,  
                    "useRequiredSpend": false  
                },  
                {  
                    "awardFormatted": "400 SB",  
                    "cashbackAmount": 4,  
                    "cashbackFormatted": "$4",  
                    "goalDescription": "Buy 2 packs of SweeTARTS Gummies Fruity Splitz",  
                    "payoutAmount": 400,  
                    "requiredQuantity": 2,  
                    "requiredSpendFormatted": null,  
                    "useGoalDescription": false,  
                    "useRequiredSpend": false  
                }  
            \],  
            "categoryIDs": \[  
                13,  
                18,  
                40,  
                44,  
                45,  
                8  
            \],  
            "detailUrl": "/grocery-receipts/sweetarts-gummies-fruity-splitz-coupon/7045645",  
            "eligibleMediums": \[  
                "INSTORE"  
            \],  
            "expirationDate": null,  
            "imageUrl": "<https://ucontent.prdg.io/pimages/b8/b829991d-14c1-406a-bacb-5925ca873518.jpg">,  
            "isIncentivized": true,  
            "isQuantitySelectionEnabled": true,  
            "line1": "SweeTARTS® Gummies Fruity Splitz",  
            "line3": "$4",  
            "line4": "400 SB",  
            "line6": "$4 Cash Back",  
            "notManyLeft": false,  
            "offerID": 7045645,  
            "purchaseQuantity": 1,  
            "redemptionsPerClaim": 0,  
            "restrictedToMerchants": true,  
            "restrictedToMerchantsOnline": false,  
            "restrictToMerchantsCount": 23,  
            "restrictToMerchantsShort": \[  
                {  
                    "logoUrl": "<https://ucontent.prdg.io/img/instore/logos/logo-1.png?v=1694019930000">,  
                    "merchantID": 1,  
                    "merchantName": "Walmart"  
                },  
                {  
                    "logoUrl": "<https://ucontent.prdg.io/img/instore/logos/logo-11.png?v=1694019930000">,  
                    "merchantID": 11,  
                    "merchantName": "Ralphs"  
                },  
                {  
                    "logoUrl": "<https://ucontent.prdg.io/img/instore/logos/logo-14.png?v=1694019930000">,  
                    "merchantID": 14,  
                    "merchantName": "Smith's Food and Drug"  
                },  
                {  
                    "logoUrl": "<https://ucontent.prdg.io/img/instore/logos/logo-2.png?v=1694019931000">,  
                    "merchantID": 2,  
                    "merchantName": "Kroger"  
                },  
                {  
                    "logoUrl": "<https://ucontent.prdg.io/img/instore/logos/logo-3.png?v=1694019931000">,  
                    "merchantID": 3,  
                    "merchantName": "Walgreens"  
                }  
            \],  
            "shortDescription": "Double the Fun with SweeTARTS® Gummies Fruity Splitz!",  
            "showUpTo": true,  
            "squareImageUrl": "<https://ucontent.prdg.io/pimages/b8/b829991d-14c1-406a-bacb-5925ca873518.jpg">  
        }  
    \],  
    "status": 200  
}

Sample Pictures Displaying The Offer List:

image-20240209-213600.png

Instore Offer Details Endpoint

Description

This endpoint provides additional information about an offer, including its description, images, buying options, and eligibility criteria.

Endpoint

curl \
-X GET https://receipts.bitlabs.ai/api/instore-offer-details&offerID={offerId} \
-H "Authorization: Bearer <token>"

Parameters

Param NameValue(s)
status200 (success), 400 (failure)
dataarray[] of offers.

Offer Detail Fields

NameTypeDescription
addedToListbooleanif the offer is added to the users list
allowRawHtmlbooleanthis is mostly internal and can be ignored
anyReceiptEligiblebooleanif the offer is an any receipt these are given special treatment as they will accept any receipt
awardLookBackintegerThis will mostly only ever be used with the anyReceiptEligible. This is the number of days in the past for which we will still allow the users receipt date
bannerImageUrlstringthere are several sizes for images from rectangular to square this is the rectangular ones typically used for a banner
barcodeScanEligiblebooleanYou can ignore this for the time being. We have a feature that allows users to submit images are barcodes and use them for redemption
baseAmountintegerthis is the cashback amount in an integer format
bonusobjectnot really relevant at this time
buyingOptionsbuyingOptions ObjectSee additional documentation below for buyingOptions
capmostly internal for now
categoryIDsinteger[]These are the categories that the offer is included within
clippedInReceiptChallengebooleanThis is internal and can be ignored
conditionsstringThis will display a displaimer about the offer
detailUrlstringthis is the url the links to the offer details view
eligibleMediumsthis is an enum[] and will contain either INSTORE or ONLINEOut of the gate we will only offer support for the INSTORE variant
eligibleProductsstring[]This is a string[] that contains the eligible products for this offer

"eligibleProducts": [

"SweeTARTS® Gummies Fruity Splitz 5oz",

"SweeTARTS® Gummies Fruity Splitz 9oz "

],
eligibleProductsInfodto[]This is an array contains additional eligible product information

"eligibleProductsInfo": [ { "imageID": 263025, "imageURL": "https://ucontent.prdg.io/pimages/34/34c8eb65-272e-4508-b38c-1053aa9a06fd.PNG", "name": "SweeTARTS® Gummies Fruity Splitz 5oz", "upc": "079200074593" }, { "imageID": 263026, "imageURL": "https://ucontent.prdg.io/pimages/85/85b8b299-2ad8-4575-9543-7a9bec98264d.PNG", "name": "SweeTARTS® Gummies Fruity Splitz 9oz", "upc": "079200074562" } ],
expirationDatea string formatted version of the expiration dateThis is the date that the offer expires and is inclusive (if the end date is today then today is still valid)

It will look like this expirationDate: "02/14/2024",
featuredbooleanDetermines if this offer is “featured”.

Typically featured offers show at the top of the sort list
imageUrlstringImage url for the offer will often coincide with the square image url
impressionScriptstringthis is internal and can be ignored
isIncentivizedbooleanDelineates between a high value offer or not. We have house offers that are loss leaders and this is what sets them apart.

Typically we add a star to the offer to highlight it’s importance as a higher paid offer.
isQuantitySelectionEnabledbooleanWe allow users to select the quantity or amount of line items that are on their receipt. If that quantity differs from what we parsed we will send their receipt into manual review for closer inspection.
line1stringThis was poorly named but you can think of this as the offer title
line2stringThis is the product description but it is an extremely lengthy variant of it. Expect multiple sentences to a paragraph here

"line2": "Tired of choosing between sweet and tart? Now you don't have to! SweeTARTS® Gummies Fruity Splitz brings you the best of both worlds in one delicious gummy. Each chewy piece is bursting with two bold, fruity flavors, one sweet and one tart, for a flavor adventure in every bite.

\n\nBuy SweeTARTS® Gummies Fruity Splitz to earn!*

\nMaximum Of Two Receipt Submissions Per Week For This Offer.",
line3stringEqually poorly named this is the actual cashback value to the user formatted as
"line3": "$4",
line4stringThis is the string formatted cashback value in the client currency
"line4": "400 SB",
line5stringYou can think of this one as a very lengthy offer disclaimer

"line5": "*Only purchases of the following products are eligible for SB:
\nSweeTARTS® Gummies Fruity Splitz 9oz
\nSweeTARTS® Gummies Fruity Splitz 5oz
\n\n
No other products are eligible for SB.
Must purchase at least 1 of the above eligible products to earn SB.
\nSB for this offer can only be earned twice per week (Sunday-Saturday), while supplies last.

\nNot all products available at all eligible retailers.
\nThis offer is subject to change at any time and is available in limited quantities.
\nPurchase must be made between January 8, 2024 and March 8, 2024. Receipt must be uploaded by 11:30 pm Pacific Time on March 8, 2024. Purchases made outside of the listed dates are not eligible for SB.

\nUploaded receipts are not eligible for SB if linked to other promotions.",
line6stringThis is the string formatted cashback value in the client currency with “Cash Back” appended
"line6": "$4 Cash Back",
line7stringDisclaimer about how many times the user is eligible to claim the offer
longDescriptionstringA longer offer description
notManyLeftbooleanDetermines if there aren’t a lot of these offers left. On our O&O we show small “not many left” banner
offerIDintegerThis is the offer id
pendingDaysintegerCertain new users will have their offers automatically go into award pending. This is a measure to prevent fraud.

If after the pending period is up the user will be approved. It is also possible for the user to be rejected out of award pending if their receipt is fraudulent
purchaseQuantityintegerThis is the minimum required quantity a user will be required to buy to get the offer.

Be forewarned a lot of this logic was moved into the buying options which defines if there are multiple goals like “buy 1” or “buy 2”
receiptChallengeIDintegerThis is internal and can be ignored
rectangleImageUrlstringImage url for a rectangular image of the offer
redemptionsPerClaimintegerthis has mostly been deprecated
referralUrlstringThis is internal and can be ignored
restrictedToMerchantsbooleanboolean value delineating if this offer is restricted to instore merchants or if it is available at all merchants
restrictedToMerchantsOnlinebooleanboolean value delineating if this offer is restricted to online merchants or is available at all online merchants

At this time online uploads are not supported
restrictToMerchantsa dto[] of restricted instore merchantsThe documentation for this is provided below about the instore merchant dto. It will include things like the name and logo also please note that on the -short call we provided a short list and this will include the full list.
restrictToMerchantsCountintegerthe amount of merchants this offer is restricted to
restrictToMerchantsOnlinea dto[]This can be ignored as we don’t currently support online through this api
restrictToMerchantsShorta dto[]This will list a sublist of the merchants that the offer is available at with additional data like logos + name + merchantID.

Expect this sublist to be variable but presume it to be set at 5.

Look at the restrictToMerchants documentation below
seocontentThis is internal and can be ignored
seotitlesThis is internal and can be ignored
shortDescriptionstringThis is the description of the offer. Expect this to be a few words at most
showUpTobooleanthis determines if we should show the “Up To” description on the offer card before the payout amount.

”400 SB”
vs
”Up To 400 SB”
squareImageUrlstringA url pointing to the square image of the offer
startDatestringThe day that the offer starts (inclusive) formatted like so

"startDate": "01/08/2024",
swagcodestringthis is internal and can be ignored
swagcodestringthis is internal and can be ignored
videoUrlstringSome of these offers include videos that will pop up in a player and display on the details view. This is not a requirement and few of these offers will include it.

Buying Options Fields

NameTypeDescription
awardFormattedstringThe string formatted reward value in the clients currency

"awardFormatted": "150 SB",
cashbackAmountdoubleThe reward amount in dollars

"cashbackAmount": 1.5,
cashbackFormattedstringThe string formatted reward amount in dollars formatted like so:

cashbackFormatted": "$1.50",
goalDescriptionstringThis is the description of the goal so there might be a buy1 or a buy 2 and this is the description for it

"goalDescription": "Buy 1 pack of SweeTARTS Gummies Fruity Splitz",
payoutAmountdoubleThe reward amount in the clients currency

"payoutAmount": 400,
requiredQuantityintegerThis is the required amount of the product that the user is expected to purchase to meet this goal.
requiredSpendFormattedExpect to mostly see required quantity. This is a separate kind of goal that requires the user to spend a certain amount on an offer rather than purchase a certain number
useGoalDescriptionbooleanTypically the goal will look something like the following:

Buy any 1 eligible product

were we pull in the required quantity. If this is enabled we display the description from the goal instead.

In practice this is mostly not used.
useRequiredSpendbooleandetermines if required spend is used. This is almost never enabled.

RestrictToMerchants Fields

NameTypeDescription
logoUrlstringThis is the logo url for the retailer
loyaltyLinkingInfoThis is internal and can be ignored
mediumsthis is an enum[] and will contain either INSTORE or ONLINEOut of the gate we will only offer support for the INSTORE variant
merchantIDintegerThe internal merchants id
merchantNamestringThis is the merchants name
orderStatusThis is internal and can be ignored
shopMerchantIDintegerThis is internal and can be ignored
shopMerchantUrlstringThis is internal and can be ignored

Example Response:

{  
    "data": {  
        "addedToList": false,  
        "allowRawHtml": true,  
        "anyReceiptEligible": false,  
        "awardLookBack": 0,  
        "bannerImageUrl": "<https://ucontent.prdg.io/pimages/96/96773959-73c5-4c8c-8cdc-f5178860c012.jpg">,  
        "barcodeScanEligible": true,  
        "baseAmount": 600,  
        "bonus": null,  
        "buyingOptions": \[  
            {  
                "awardFormatted": "200 SB",  
                "cashbackAmount": 2,  
                "cashbackFormatted": "$2",  
                "goalDescription": "Buy 1 pack of SweeTARTS Gummies Fruity Splitz",  
                "payoutAmount": 200,  
                "requiredQuantity": 1,  
                "requiredSpendFormatted": null,  
                "useGoalDescription": false,  
                "useRequiredSpend": false  
            },  
            {  
                "awardFormatted": "600 SB",  
                "cashbackAmount": 6,  
                "cashbackFormatted": "$6",  
                "goalDescription": "Buy 2 packs of SweeTARTS Gummies Fruity Splitz",  
                "payoutAmount": 600,  
                "requiredQuantity": 2,  
                "requiredSpendFormatted": null,  
                "useGoalDescription": false,  
                "useRequiredSpend": false  
            }  
        \],  
        "cap": null,  
        "categoryIDs": \[  
            13,  
            18,  
            40,  
            44,  
            45,  
            8  
        \],  
        "clippedInReceiptChallenge": false,  
        "conditions": null,  
        "detailUrl": "/grocery-receipts/sweetarts-gummies-fruity-splitz-coupon/7045645",  
        "eligibleMediums": \[  
            "INSTORE"  
        \],  
        "eligibleProducts": \[  
            "SweeTARTS® Gummies Fruity Splitz 5oz",  
            "SweeTARTS® Gummies Fruity Splitz 9oz "  
        \],  
        "eligibleProductsInfo": \[  
            {  
                "imageID": 263025,  
                "imageURL": "<https://ucontent.prdg.io/pimages/34/34c8eb65-272e-4508-b38c-1053aa9a06fd.PNG">,  
                "name": "SweeTARTS® Gummies Fruity Splitz 5oz",  
                "upc": "079200074593"  
            },  
            {  
                "imageID": 263026,  
                "imageURL": "<https://ucontent.prdg.io/pimages/85/85b8b299-2ad8-4575-9543-7a9bec98264d.PNG">,  
                "name": "SweeTARTS® Gummies Fruity Splitz 9oz",  
                "upc": "079200074562"  
            }  
        \],  
        "expirationDate": null,  
        "featured": false,  
        "imageUrl": "<https://ucontent.prdg.io/pimages/58/5844d280-9839-4f1e-8321-46a07608fd16.jpg">,  
        "impressionScript": "",  
        "isIncentivized": true,  
        "isQuantitySelectionEnabled": true,  
        "line1": "SweeTARTS® Gummies Fruity Splitz",  
        "line2": "Tired of choosing between sweet and tart? Now you don't have to! SweeTARTS® Gummies Fruity Splitz brings you the best of both worlds in one delicious gummy. Each chewy piece is bursting with two bold, fruity flavors, one sweet and one tart, for a flavor adventure in every bite.<br><br>\\n\\nBuy SweeTARTS® Gummies Fruity Splitz to earn!\_<br><br>\\nMaximum Of Two Receipt Submissions Per Week For This Offer.",  
        "line3": "$6",  
        "line4": "600 SB",  
        "line5": "\_Only purchases of the following products are eligible for SB:<br>\\nSweeTARTS® Gummies Fruity Splitz 9oz<br>\\nSweeTARTS® Gummies Fruity Splitz 5oz<br>\\n\\n<br>No other products are eligible for SB.<br>Must purchase at least 1 of the above eligible products to earn SB.<br>\\nSB for this offer can only be earned twice per week (Sunday-Saturday), while supplies last.<br><br>\\nNot all products available at all eligible retailers. <br>\\nThis offer is subject to change at any time and is available in limited quantities.<br>\\nPurchase must be made between January 8, 2024 and March 8, 2024. Receipt must be uploaded by 11:30 pm Pacific Time on March 8, 2024. Purchases made outside of the listed dates are not eligible for SB.<br><br>\\nUploaded receipts are not eligible for SB if linked to other promotions.",  
        "line6": "$6 Cash Back",  
        "line7": "Maximum Of Two Receipt Submissions Per Week For This Offer.",  
        "longDescription": "Tired of choosing between sweet and tart? Now you don't have to! SweeTARTS® Gummies Fruity Splitz brings you the best of both worlds in one delicious gummy. Each chewy piece is bursting with two bold, fruity flavors, one sweet and one tart, for a flavor adventure in every bite.<br><br>\\n\\nBuy SweeTARTS® Gummies Fruity Splitz to earn!\*<br><br>\\nMaximum Of Two Receipt Submissions Per Week For This Offer.",  
        "notManyLeft": false,  
        "offerID": 7045645,  
        "pendingDays": 0,  
        "purchaseQuantity": 1,  
        "receiptChallengeID": 0,  
        "rectangleImageUrl": "<https://ucontent.prdg.io/pimages/58/5844d280-9839-4f1e-8321-46a07608fd16.jpg">,  
        "redemptionsPerClaim": 0,  
        "referralUrl": "<https://www.swagbucks.com/grocery-receipts/refer/sweetarts-gummies-fruity-splitz-coupon/7045645?erb=etcwbiomx5neojt642cibnk33xpyhi42pnl4l6i=">,  
        "restrictedToMerchants": true,  
        "restrictedToMerchantsOnline": false,  
        "restrictToMerchants": \[  
            {  
                "logoUrl": "<https://ucontent.prdg.io/img/instore/logos/logo-1.png?v=1694019930000">,  
                "loyaltyLinkingInfo": {  
                    "bgImageURL": "<https://ucontent.prdg.io/img/instore/bg-logos/bg-logo-1.png?v=1694019929000">,  
                    "blinkMerchantID": 11,  
                    "loyaltyAccountMerchantID": 1,  
                    "loyaltyLinkingEnabled": true,  
                    "registrationLink": "<https://www.walmart.com/account/signup?vid=oaoh">,  
                    "tutorialText1": "Curbside pick up and online orders are not currently supported.",  
                    "tutorialText2": "Curbside pick up and online orders are not currently supported."  
                },  
                "mediums": \[  
                    "INSTORE"  
                \],  
                "merchantID": 1,  
                "merchantName": "Walmart",  
                "orderStatus": "",  
                "shopMerchantID": 183,  
                "shopMerchantUrl": "/shop/walmart-coupons"  
            }  
        \],  
        "restrictToMerchantsCount": 23,  
        "restrictToMerchantsOnline": null,  
        "restrictToMerchantsShort": \[  
            {  
                "logoUrl": "<https://ucontent.prdg.io/img/instore/logos/logo-1.png?v=1694019930000">,  
                "loyaltyLinkingInfo": {  
                    "bgImageURL": "<https://ucontent.prdg.io/img/instore/bg-logos/bg-logo-1.png?v=1694019929000">,  
                    "blinkMerchantID": 11,  
                    "loyaltyAccountMerchantID": 1,  
                    "loyaltyLinkingEnabled": true,  
                    "registrationLink": "<https://www.walmart.com/account/signup?vid=oaoh">,  
                    "tutorialText1": "Curbside pick up and online orders are not currently supported.",  
                    "tutorialText2": "Curbside pick up and online orders are not currently supported."  
                },  
                "mediums": \[  
                    "INSTORE"  
                \],  
                "merchantID": 1,  
                "merchantName": "Walmart",  
                "orderStatus": "",  
                "shopMerchantID": 183,  
                "shopMerchantUrl": "/shop/walmart-coupons"  
            }  
        \],  
        "seocontent": {},  
        "seotitles": {},  
        "shortDescription": "Double the Fun with SweeTARTS® Gummies Fruity Splitz!",  
        "showUpTo": true,  
        "squareImageUrl": "<https://ucontent.prdg.io/pimages/b8/b829991d-14c1-406a-bacb-5925ca873518.jpg">,  
        "startDate": "01/08/2024",  
        "swagcode": "",  
        "videoUrl": ""  
    },  
    "status": 200  
}

Sample Pictures Displaying The Offer Details View

image-20240209-213639.png image-20240209-215619.png

Instore Category Endpoint

In-Store Categories API Endpoint

Overview

This endpoint provides a comprehensive list of in-store categories that Instore Offers are classified under. Categories are a pivotal element of offer organization and presentation:

  • Offers are associated with multiple categories as defined in the Offer Server, which enables categorization for better searchability and filtering.
  • Clients can retrieve offers by category, allowing them to display offers pertinent to a selected category.
  • Each category has a unique name and an associated type, which correspond to specific database tables (prodege.shm_category and prodege.shm_category_type respectively).
  • Categories may be ordered explicitly; if no order is specified, the backend will determine the order dynamically.
  • Only active categories are available for display and operations; inactive categories are excluded from caching and presentation.

The API mirrors the structure and relationships of these categories as they exist in the database, ensuring that clients can retrieve up-to-date and relevant information for displaying offers to end-users. Additionally, it provides the flexibility to manage these categories through an administrative interface, where new categories can be created, existing ones can be edited or updated, and category icons can be uploaded.

HTTP Request

curl \
-X GET https://receipts.bitlabs.ai/api/instore-categories \
-H "Authorization: Bearer <token>"

Request Parameters

None required.

Response

The response will be a JSON object containing an array of categories. Each category has the following structure:

Instore Category Object Fields

NameTypeDescription
idintegerThe unique identifier for the category, automatically generated upon creation.
typeIDintegerThe type ID that corresponds to the classification of the category.
orderNumintegerThe specific order in which the category should appear on the front end, visible only to admin views.
namestringThe unique name of the category, displayed on the front end.
urlPngstringThe URL to the PNG icon for the category.
urlSvgstringThe URL to the SVG icon for the category.
adminPrioritizedbooleanIndicates if the category is prioritized by admins and is not ordered dynamically based on member preferences.

Instore Category Type Object Fields

NameTypeDescription
categoryTypeIDintegerUnique identifier for the type of category.
categoryNamestringName of the category type.
descriptionstringDescription of what the category type represents.

Example Response

{  
  "categories": \[  
    {  
      "id": 1,  
      "typeID": 1,  
      "name": "All Deals",  
      "url": "<https://content.prod.img/path/to/image.png">,  
      "description": "Regular Colored Instore Category"  
    },  
    {  
      "id": 45,  
      "typeID": 2,  
      "name": "New",  
      "url": "<https://content.prod.img/path/to/image.png">,  
      "description": "Special Category that is colored on the front end"  
    },  
    // Additional categories...  
  \],  
  "categoryTypes": \[  
    {  
      "categoryTypeID": 1,  
      "categoryName": "Standard",  
      "description": "Regular Colored Instore Category"  
    },  
    {  
      "categoryTypeID": 2,  
      "categoryName": "Special Color",  
      "description": "Special Category that is colored on the front end"  
    }  
    // Additional category types...  
  \]  
}

Sample Categories Display:

  • When clicking on a category it makes a offers-short call to our backend that filters to only include the offers that have that specific category.
image-20240209-185344.png

If you click on the three dots to the right of the categories, then it shows the below screen with all the categories, when clicking on one of them, it makes a call to offers-short with that categoryID

image-20240209-221510.png

Instore Merchants Endpoint

In-Store Merchants API Endpoint

Overview

This API retrieves a curated list of merchants tied to in-store offers. It accounts for member-specific data and preferences, ensuring the merchant list is targeted and relevant. The merchants returned by this API are filtered based on the offers available, member activity, and other bespoke criteria.

Enhanced Features

  • Adaptive Filtering: It leverages an advanced filtering system that accounts for the latest member activity, such as recently uploaded receipts and offers added to the member's list, to deliver a list that resonates with the user's current shopping behavior.
  • Customized Sorting: Merchants are sorted by a bespoke set of criteria that elevates member favorites and popular or featured stores, ensuring that the most relevant and preferred merchants are highlighted.
  • Comprehensive Merchant Data: Each merchant entry is enriched with detailed information, from offer counts and loyalty account linkage to customized tutorial texts and image URLs, providing a full spectrum of data that can enhance user experience.

Sorting Logic

The API sorts merchants with a multi-tiered logic that prioritizes:

  1. User-favorited merchants, ensuring personalized experiences are at the forefront.
  2. Merchants popular in the user's location, enhancing relevance based on geographical trends.
  3. Featured merchants, highlighting those with special offers or prominence on the platform.
  4. Alphabetical order, providing a systematic and familiar navigation through the merchant list.

HTTP Request

curl \
-X GET https://receipts.bitlabs.ai/api/instore-merchants \
-H "Authorization: Bearer <token>"

Request Parameters

  • medium (String): Specifies the medium of the offers, either "online" or "instore".
  • getUploadList (Boolean): If true, returns only the merchants associated with offers clipped to the member's list.
  • getRecent (Boolean): If true, returns only the merchants where the member has uploaded receipts recently.

Response

The response is a JSON object containing an array of merchant items. Each InstoreMerchantListItem includes:

Merchant Information Fields

NameTypeDescription
dealCountintegerThe total number of active deals or offers currently available for the merchant.
externalIDintegerAn identifier for the merchant used in external systems or databases.
hasOfferOnMyListbooleanIndicates whether any of the merchant's offers are saved to the user's personal list.
isFavoritebooleanShows whether the merchant is marked as a favorite by the user within the platform.
isFeaturedbooleanWhether the merchant is highlighted in a featured section of the platform.
isLoyaltyAccountLinkedbooleanSpecifies if the user has a loyalty account linked with the merchant.
logoUrlstringThe URL to the merchant's logo image.
loyaltyLinkingInfoobjectDetails about the merchant's loyalty program offering.
mediumsarrayThe types of platforms through which the merchant's offers can be accessed.
merchantIDintegerThe internal unique identifier for the merchant.
merchantNamestringThe official name of the merchant.
orderStatusstringThe status of an order with the merchant, if applicable.
shopMerchantIDintegerAn identifier used within the shopping interface of the platform for the merchant.
shopMerchantUrlstringThe relative URL to the merchant's section on the platform for additional offers or coupons.

Loyalty Linking Information Fields

NameTypeDescription
loyaltyLinkingEnabledbooleanIndicates whether loyalty account linking is enabled for the merchant.
registrationLinkstringThe URL where users can sign up for the merchant's loyalty program.
tutorialText1stringInstructional text providing guidance on using the loyalty program.
tutorialText2stringAdditional instructional text related to the loyalty program.
bgImageURLstringThe URL for the background image associated with the merchant for the loyalty program.
blinkMerchantIDintegerThe Blink system's identifier for the merchant, related to the loyalty program.
loyaltyAccountMerchantIDintegerThe unique identifier for the merchant within the loyalty linking system.

Example Response

{  
    "data": \[  
        {  
            "merchantID": 106,  
            "merchantName": "7-Eleven",  
            "logoUrl": "<https://ucontent.prdg.io/img/instore/logos/logo-106.png?v=1694019930000">,  
            "mediums": \[  
                "INSTORE"  
            \],  
            "orderStatus": "",  
            "shopMerchantID": 31339,  
            "shopMerchantUrl": "/shop/7eleven-coupons",  
            "externalID": 78,  
            "loyaltyLinkingInfo": {  
                "loyaltyLinkingEnabled": false,  
                "registrationLink": null,  
                "tutorialText1": null,  
                "tutorialText2": null,  
                "blinkMerchantID": 0,  
                "loyaltyAccountMerchantID": 0,  
                "bgImageURL": null  
            },  
            "dealCount": 42,  
            "hasOfferOnMyList": true,  
            "isFeatured": false,  
            "isFavorite": false,  
            "isLoyaltyAccountLinked": false  
        },  
        {  
            "merchantID": 4,  
            "merchantName": "Costco Wholesale Corp.",  
            "logoUrl": "<https://ucontent.prdg.io/img/instore/logos/logo-4.png?v=1694019932000">,  
            "mediums": \[  
                "INSTORE"  
            \],  
            "orderStatus": "completed",  
            "shopMerchantID": 29941,  
            "shopMerchantUrl": "/shop/costco.com-coupons",  
            "externalID": 14,  
            "loyaltyLinkingInfo": {  
                "loyaltyLinkingEnabled": false,  
                "registrationLink": "<https://signin.costco.com/e0714dd4-784d-46d6-a278-3e29553483eb/B2C\_1A\_SSO\_WCS\_signup\_signin\_467/api/CombinedSigninAndSignup/unified?local=signup&csrf\_token=VUFvTDlyVHNsaXo1bjVMQ1FXaW83YTFhSFd6RGo0UTI3UkFwL1JlZmtMRFhWTkx1ZU1CUk5RYmlBKzQvREc5NDdtUDc3ZksxMGE5WllFNmRiMEpCd1E9PTsyMDIxLTEyLTE2VDIzOjE3OjAzLjg3OTQ2MTVaOzIrTjUwZGxoVkhtMXBQS2cyNzZiTGc9PTt7Ik9yY2hlc3RyYXRpb25TdGVwIjo0fQ==&tx=StateProperties=eyJUSUQiOiJjMDFlNDBkYS05NDljLTQ2YjAtODI2Yi01MWVhNzI5OTgzZDcifQ&p=B2C\_1A\_SSO\_WCS\_signup\_signin_467">,  
                "tutorialText1": null,  
                "tutorialText2": null,  
                "blinkMerchantID": 2,  
                "loyaltyAccountMerchantID": 4,  
                "bgImageURL": null  
            },  
            "dealCount": 145,  
            "hasOfferOnMyList": true,  
            "isFeatured": false,  
            "isFavorite": false,  
            "isLoyaltyAccountLinked": false  
        },  
        ... additional merchants  
    \]  
}

Sample Instore Merchants Display:

All Merchants

image-20240209-190411.png image-20240209-190620.png

Shop By Merchant

This is after clicking on one merchant and seeing only offers for that merchantID and categoryID

image-20240209-190509.png

Instore Receipt Upload Enabled

Receipt Upload Enabled Check API Endpoint

Overview

This API endpoint checks if the receipt upload feature is enabled for the Magic Receipts program and retrieves the configuration settings related to the receipt upload process.

HTTP Request

curl \
-X GET https://receipts.bitlabs.ai/?cmd=mp-instore-receipt-upload-enabled \
-H "Authorization: Bearer <token>"

Response Object

NameTypeDescription
maxManualReviewForUploadintegerThe maximum number of manual reviews that can be requested per receipt upload.

This is also internal and likely won’t be used.
maxOfferUploadsintegerThe maximum number of offers that can be uploaded at one time.
dataShareOptInBonusAmountintegerThe bonus amount awarded for opting into data sharing during the receipt upload process.

This is internal and likely won’t be used.
enabledbooleanIndicates whether the receipt upload feature is currently enabled.

Example Response

{  
   "maxManualReviewForUpload":10,  
   "maxOfferUploads":10,  
   "dataShareOptInBonusAmount":10,  
   "enabled":true  
}

Description

The response provides the client with essential configuration settings that govern the receipt upload process:

  • maxManualReviewForUpload: Clients can use this value to inform users how many items on their receipt can be reviewed manually if automatic processing does not recognize them.
  • maxOfferUploads: This value can be used to validate the number of offers a user is attempting to upload and to enforce limits within the client application.
  • dataShareOptInBonusAmount: If there is a bonus associated with opting into data sharing, this value can be displayed to the user as an incentive.
  • enabled: The client application can use this boolean flag to enable or disable the receipt upload functionality dynamically, without requiring an update or release.

Notes

  • This endpoint should be called before attempting to upload a receipt to ensure the feature is available and to retrieve the current operational parameters.
  • The provided settings should be used to set up client-side validations and to inform the user of the receipt upload process's rules and potential benefits.

Instore Receipt Upload/Validation

Receipt Upload API Endpoint

Overview

The Receipt Upload API allows members to upload their shopping receipts to claim offers listed under the Magic Receipts program. The API processes the uploaded receipt image, evaluates the eligibility for cashback, and returns the status of each claimed offer.

HTTP Request

curl \
-X POST https://receipts.bitlabs.ai/api/magic-receipts/upload-receipt \
-H "Authorization: Bearer <token>"

Request Parameters

NameTypeDescription
merchantIDintegerThe ID of the merchant where the purchase was made.
imageCountintegerThe number of receipt images attached to the upload.
offerIDsinteger[]An array of offer IDs that the member wants to claim.
dataShareAdvertiserIdsinteger[]An array of advertiser IDs for data sharing purposes.
mediumstringThe medium of shopping, e.g., "INSTORE" or "ONLINE". Defaults to empty.
receiptstringThe text representation of the receipt, if applicable. Defaults to empty.

Form Data Parameters

NameTypeDescription
img0binaryThe binary data of the receipt image.
imgName0stringThe file name of the receipt image.
image-20240209-230706.png

Main Response

NameTypeDescription
statusintegerThe HTTP status code of the response.
dataobjectThe main data object containing the details of the processed receipt.

Data Object Fields

NameTypeDescription
rejectedobjectContains information about any offers that were rejected during processing.
manualReviewobjectContains information about offers that require manual review.
confirmedobjectContains information about the offers that were automatically awarded
awardPendingobjectContains information about the offers that are now in an award pending state, i.e. they will be awarded in a couple of days unless CS rejects them.
barcodeScanEligibleDeviceCodesarrayAn array of device codes that are eligible for barcode scanning.
barcodeScanEnabledbooleanIndicates if barcode scanning is enabled for the receipt upload.

Rejected and Manual Review Objects

NameTypeDescription
offersarrayAn array of offers with their respective processing status.
awardBonusesarrayAny bonus awards applicable to the receipt.
unusedLineItemsarrayLine items on the receipt that were not used for any offers.
totalAwardCashbackstringThe total cashback amount awarded for the receipt.
totalAwardstringThe total award points (SB) earned for the receipt.

Offers Array Object

NameTypeDescription
maxLinesForManualReviewintegerThe maximum number of lines allowed for manual review.
offerIDintegerThe ID of the offer.
imageUrlstringThe URL of the image related to the offer.
pendingDaysintegerThe number of days the offer is pending for.
uploadOfferIDintegerThe ID of the uploaded offer.
statestringThe processing state of the offer (e.g., "rejected").
awardstringThe award points (SB) for the offer.
awardCashbackstringThe cashback amount for the offer.
surveyUrlstringThe URL to a survey related to the offer, if applicable.
shortErrorStrstringA short description of any error encountered.
errorStrstringA full description of the error.
errorCodeintegerA code representing the error encountered.
isBarcodeScanEligiblebooleanIndicates if the offer is eligible for barcode scanning.
offerTitlestringThe title of the offer.
addedToListbooleanIndicates if the offer was added to the user's list.
isUnselectedOfferbooleanIndicates if the offer was not originally selected by the user

Unused Line Items Object Fields

NameTypeDescription
receiptLineIDintegerThe unique identifier for the line item on the receipt.
rsdstringThe recognized shopping description or item name extracted from the receipt.
pricedecimalThe price of the item as captured from the receipt.

Error Handling

  • The method includes comprehensive error handling, providing clear error messages and codes for various failure scenarios such as invalid merchant ID, image count, offer IDs, receipt data, and upload progress state.
  • It also ensures that if a receipt upload is already in progress, it will not start another, preserving the integrity of the member's upload queue.

Sample Receipt Upload Request Display:

On the main screen there is a Submit Receipt button that allows the member to start the upload process

image-20240209-214506.png

Clicking on that button makes a call to the merchants api above to retrieve all the merchants that a member could choose they shopped at for their receipt.

image-20240209-214701.png

after selecting a merchant and clicking Continue a call is made to the offers-short api above with sortType=0 and merchantID=?? whatever the id of the merchant is, that will return to you all the offers relevant for this merchant that the member could upload for.

image-20240209-215142.png

choose which offers are on your receipt and how many of them you bought for offers that have multiple goals (buying options) attached to them, i.e. buy 1 get this amount, buy 2 get this award.

image-20240209-215426.png

After clicking Continue you’re taken to this screen that allows you to upload a file which is a picture of your receipt.

image-20240209-215454.png

A member can attach multiple pictures to capture the entire receipt if it’s long

image-20240209-215630.png

Then when clicking Submit Receipt we make the upload-receipt call to the api to do the validation, while we are validating we have an upload screen.

image-20240209-215731.png

Depending on the result from the upload we display accordingly

image-20240209-215841.png image-20240209-215920.png

there can be multiple reasons the offers were rejected, as can be seen here 3 different reasons: date, matching, duplicate

image-20240209-220026.png

From there you can click Contact Customer Support to request manual review (see above API doc), or click Review Your Receipt Photos and either resubmit the same photo or choose different ones.

Instore Manual Review

In-Store Manual Review API Endpoint

Overview

This API endpoint is dedicated to handling the manual review process for members who have submitted receipts and believe certain offers should be awarded post-rejection. It provides a mechanism for members to flag specific rejected offers for further review by customer service (CS) teams, potentially leading to offer approval.

HTTP Request

curl \
-X POST https://receipts.bitlabs.ai/api/instore-manual-review \
-H "Authorization: Bearer <token>"

Request Parameters

NameTypeDescription
uploadOfferIdsarrayAn array of IDs representing the offers that the member requests to be reviewed manually.

Response

The response will include a status code and may also return an array of uploadOfferIds that have been successfully submitted for manual review.

Example Request

POST https://receipts.bitlabs.ai/api/instore-manual-review?uploadOfferIds=151012867,151012868,151012869,151012870

Example Response

{  
   "manualReview":\[  
      151012867,  
      151012868,  
      151012869,  
      151012870  
   \],  
   "status":200  
}

Sample Manual Review Request Display:

Immediately after the upload a user gets a display with the offer they chose to upload for showing that they weren’t awarded for them, and the choice to click Contact Customer Support, which brings you to the next screen.

image-20240209-202711.png

The user now can choose which offers they think they should have been awarded for, i.e. that they should be manually reviewed.

image-20240209-202742.png

Then when the user clicks Send For Review is when we make the API call above using the uploadOfferIDs of these selected offers (these ids are passed back after the receipt upload call).

image-20240209-202759.png

Then we display a message conveying that their review request has been received, or an error request if it wasn’t received.

  • If upload offer IDs were sent back, that means it was received
  • If no upload offer IDs were sent back, then the request didn’t work
  • If an error message (noted above) was sent back then either they requested too many offers (the limit is 10), or an error happened deserializing the JSON.
image-20240209-202822.png

Processing Logic

Upon submission, the endpoint performs the following actions:

  1. Validates the eligibility of the upload offers for manual review based on certain rejection statuses and the offer's manual review eligibility.
  2. Changes the status of eligible upload offers to PENDING_MANUAL_REVIEW_USER_REQUESTED.
  3. Allows CS teams to subsequently approve or reject the offers in the admin panel.

Error Handling

  • If the request fails, an error status code and message will be provided.
    • {"status": 400, "message", "error"}
  • Common errors include:
    • invalid offer IDs
    • offers that are not eligible for manual review.
    • Only a configurable amount of manual review submissions are allowed per upload, if it exceeds this number the error response is returned

Best Practices

It is recommended to handle the response gracefully in the UI, providing users with clear feedback on the submission's success or failure.