Receipt Upload 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/?cmd=mp-mr-api-upload-receipt&offerIDs=191405%2C143787&merchantID=7 \
-H "Authorization: Bearer <token>"
Request Parameters
Name | Type | Description |
---|---|---|
merchantID | integer | The ID of the merchant where the purchase was made (optional). |
offerIDs | integer[] | An array of offer IDs that the member wants to claim. |
receipt | string | The text representation of the receipt, if applicable. Defaults to empty. |
Form Data Parameters
Name | Type | Description |
---|---|---|
img0 | binary | The binary data of the receipt image. |
imgName0 | string | The file name of the receipt image. |

Main Response
Name | Type | Description |
---|---|---|
status | integer | The HTTP status code of the response. |
data | object | The main data object contains the details of the processed receipt. |
Data Object Fields
Name | Type | Description |
awardPending | object | Contains 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. |
confirmed | object | Contains information about the offers that were automatically awarded |
confirmedAndAwardPending | object | Contains both offers there were confirmed + award pending |
manualReview | object | Contains information about offers that require manual review. If an offer was rejected but it's eligible for manual review it will appear here. There's a request to request manual review and you would pull the eligible list from this object |
rejected | object | Contains information about any offers that were rejected during processing. |
pending | object | It contains information about offers that were automatically sent for manual review. Sometimes, this happens if your receipt is flagged for fraud. This offer will be manually approved/denied. |
barcodeScanEligibleDeviceCodes | array | An array of device codes that are eligible for barcode scanning. unknown: -1, iPad: 1, androidTablet: 2, iOsMobile: 3, androidMobile: 4 |
barcodeScanEnabled | boolean | Indicates if barcode scanning is enabled for the receipt upload. |
Rejected and Manual Review Objects
Name | Type | Description |
---|---|---|
offers | array | An array of offers with their respective processing status. |
awardBonuses | array | Any bonus awards applicable to the receipt. |
unusedLineItems | array | Line items on the receipt that were not used for any offers. |
totalAwardCashback | string | The total cashback amount awarded for the receipt. |
totalAward | string | The total award in currency earned for the receipt. |
Offers Array Object
Name | Type | Description |
---|---|---|
maxLinesForManualReview | integer | The maximum number of lines allowed for manual review. |
offerID | integer | The ID of the offer. |
imageUrl | string | The URL of the image related to the offer. |
pendingDays | integer | The number of days the offer is pending for. |
uploadOfferID | integer | The ID of the uploaded offer. |
state | string | The processing state of the offer (e.g., "rejected"). |
award | string | The award points (SB) for the offer. |
awardCashback | string | The cashback amount for the offer. |
surveyUrl | string | The URL to a survey related to the offer, if applicable. |
shortErrorStr | string | A short description of any error encountered. |
errorStr | string | A full description of the error. |
errorCode | integer | A code representing the error encountered. |
isBarcodeScanEligible | boolean | Indicates if the offer is eligible for barcode scanning. |
offerTitle | string | The title of the offer. |
addedToList | boolean | Indicates if the offer was added to the user's list. |
isUnselectedOffer | boolean | Indicates if the user did not originally select the offer |
Unused Line Items Object Fields
Name | Type | Description |
---|---|---|
receiptLineID | integer | The unique identifier for the line item on the receipt. |
rsd | string | The recognized shopping description or item name extracted from the receipt. |
price | decimal | The price of the item as captured from the receipt. |
Sample JSON Returned
Example 1: Successful Receipt Upload with Confirmed Offers Only
{
"status": 200,
"data": {
"confirmed": {
"offers": [
{
"maxLinesForManualReview": 5,
"offerID": 101,
"imageUrl": "http://example.com/image101.png",
"pendingDays": 0,
"uploadOfferID": 501,
"state": "confirmed",
"award": "$100.00",
"awardCashback": "$10.00",
"surveyUrl": null,
"shortErrorStr": null,
"errorStr": null,
"errorCode": 0,
"isBarcodeScanEligible": true,
"offerTitle": "Buy One Get One Free",
"addedToList": true,
"isUnselectedOffer": false
}
],
"awardBonuses": [],
"unusedLineItems": [],
"totalAward": "$100.00",
"totalAwardCashback": "$10.00"
}
}
}
Explanation:
- Status Code: The HTTP status code is 200, indicating a successful request.
- Confirmed Offers:
- Under the
"confirmed"
key, one offer is present that has been automatically awarded. - Each offer contains all required details (such as
offerID
,award
,awardCashback
, etc.) with no errors.
- Under the
- Totals: The
totalAward
andtotalAwardCashback
represent the computed totals for confirmed offers.
Example 2: Receipt Upload with Rejected Offers
{
"status": 200,
"data": {
"rejected": {
"offers": [
{
"maxLinesForManualReview": 5,
"offerID": 102,
"imageUrl": "http://example.com/image102.png",
"pendingDays": 0,
"uploadOfferID": 502,
"state": "rejected",
"award": "$0.00",
"awardCashback": "$0.00",
"surveyUrl": null,
"shortErrorStr": "Invalid Offer",
"errorStr": "Offer does not meet criteria",
"errorCode": 100,
"isBarcodeScanEligible": false,
"offerTitle": "Discount on Shoes",
"addedToList": false,
"isUnselectedOffer": false
}
],
"awardBonuses": [],
"unusedLineItems": [],
"totalAward": "$0.00",
"totalAwardCashback": "$0.00"
}
}
}
Explanation:
- Rejected Offers:
- The
"rejected"
key contains one offer that failed processing. - Error fields (
shortErrorStr
,errorStr
, anderrorCode
) are populated to indicate why the offer was rejected.
- The
- Totals: Both award and cashback totals are zero, reflecting the rejection outcome.
Example 3: Receipt Upload with Manual Review Offers
{
"status": 200,
"data": {
"manualReview": {
"offers": [
{
"maxLinesForManualReview": 5,
"offerID": 103,
"imageUrl": "http://example.com/image103.png",
"pendingDays": 1,
"uploadOfferID": 503,
"state": "manualReview",
"award": "$50.00",
"awardCashback": "$5.00",
"surveyUrl": "http://example.com/survey",
"shortErrorStr": null,
"errorStr": null,
"errorCode": 0,
"isBarcodeScanEligible": true,
"offerTitle": "Manual Review Offer",
"addedToList": true,
"isUnselectedOffer": false
}
],
"awardBonuses": [],
"unusedLineItems": [
{
"receiptLineID": 1,
"rsd": "Item A",
"price": "12.34"
},
{
"receiptLineID": 2,
"rsd": "Item B",
"price": "45.67"
}
],
"totalAward": "$50.00",
"totalAwardCashback": "$5.00"
}
}
}
Explanation:
- Manual Review:
- Offers under
"manualReview"
indicate that they require human intervention (e.g., due to a rejection that might be reversed). - The offer includes a survey URL which might be used to collect additional user input.
- Offers under
- Unused Line Items:
- The response also includes an array of unused receipt line items, meaning parts of the receipt were not applied toward any offer.
- Totals: The totals reflect the manual review award amounts.
Example 4: Receipt Upload with Award Pending Offers
{
"status": 200,
"data": {
"awardPending": {
"offers": [
{
"maxLinesForManualReview": 5,
"offerID": 104,
"imageUrl": "http://example.com/image104.png",
"pendingDays": 2,
"uploadOfferID": 504,
"state": "awardPending",
"award": "$75.00",
"awardCashback": "$7.50",
"surveyUrl": null,
"shortErrorStr": null,
"errorStr": null,
"errorCode": 0,
"isBarcodeScanEligible": true,
"offerTitle": "Award Pending Offer",
"addedToList": true,
"isUnselectedOffer": false
}
],
"awardBonuses": [],
"unusedLineItems": [],
"totalAward": "$75.00",
"totalAwardCashback": "$7.50"
}
}
}
Explanation:
- Award Pending:
- The
"awardPending"
key indicates that the offer is not immediately confirmed but will be processed (typically in a couple of days). - The
pendingDays
value shows how long the offer will remain in this state.
- The
- Totals: The computed award and cashback totals for pending offers are shown.
Example 5: Receipt Upload with Combined Confirmed and Award Pending Offers
{
"status": 200,
"data": {
"confirmedAndAwardPending": {
"offers": [
{
"maxLinesForManualReview": 5,
"offerID": 105,
"imageUrl": "http://example.com/image105.png",
"pendingDays": 0,
"uploadOfferID": 505,
"state": "awardPending",
"award": "$75.00",
"awardCashback": "$7.50",
"surveyUrl": null,
"shortErrorStr": null,
"errorStr": null,
"errorCode": 0,
"isBarcodeScanEligible": true,
"offerTitle": "Combined Award Pending Offer",
"addedToList": true,
"isUnselectedOffer": false
},
{
"maxLinesForManualReview": 5,
"offerID": 106,
"imageUrl": "http://example.com/image106.png",
"pendingDays": 0,
"uploadOfferID": 506,
"state": "confirmed",
"award": "$100.00",
"awardCashback": "$10.00",
"surveyUrl": null,
"shortErrorStr": null,
"errorStr": null,
"errorCode": 0,
"isBarcodeScanEligible": true,
"offerTitle": "Combined Confirmed Offer",
"addedToList": true,
"isUnselectedOffer": false
}
],
"awardBonuses": [],
"unusedLineItems": [],
"totalAward": "$175.00",
"totalAwardCashback": "$17.50"
}
}
}
Explanation:
- Combined Response:
- Here the
"confirmedAndAwardPending"
key groups both confirmed and pending awards together. - Two offers are included—one still pending and one already confirmed.
- Here the
- Totals: The total award and cashback values are the sums of both offers.
Example 6: Receipt Upload with Pending Offers (Flagged for Fraud)
{
"status": 200,
"data": {
"pending": {
"offers": [
{
"maxLinesForManualReview": 5,
"offerID": 107,
"imageUrl": "http://example.com/image107.png",
"pendingDays": 3,
"uploadOfferID": 507,
"state": "pending",
"award": "$60.00",
"awardCashback": "$6.00",
"surveyUrl": null,
"shortErrorStr": "Fraud Suspected",
"errorStr": "The receipt was flagged for potential fraud.",
"errorCode": 200,
"isBarcodeScanEligible": false,
"offerTitle": "Fraud Flagged Offer",
"addedToList": false,
"isUnselectedOffer": false
}
],
"awardBonuses": [],
"unusedLineItems": [],
"totalAward": "$60.00",
"totalAwardCashback": "$6.00"
}
}
}
Explanation:
- Pending Offers:
- The
"pending"
key is used when an offer is automatically sent for manual review due to issues such as fraud detection. - Error messages explain why the offer is pending.
- The
- Totals: Reflect the pending award amounts.
Example 7: Receipt Upload with Barcode Scanning Enabled
{
"status": 200,
"data": {
"confirmed": {
"offers": [
{
"maxLinesForManualReview": 5,
"offerID": 108,
"imageUrl": "http://example.com/image108.png",
"pendingDays": 0,
"uploadOfferID": 508,
"state": "confirmed",
"award": "$120.00",
"awardCashback": "$12.00",
"surveyUrl": null,
"shortErrorStr": null,
"errorStr": null,
"errorCode": 0,
"isBarcodeScanEligible": true,
"offerTitle": "Barcode Eligible Offer",
"addedToList": true,
"isUnselectedOffer": false
}
],
"awardBonuses": [],
"unusedLineItems": [],
"totalAward": "$120.00",
"totalAwardCashback": "$12.00"
},
"barcodeScanEligibleDeviceCodes": [1, 3],
"barcodeScanEnabled": true
}
}
Explanation:
- Barcode Scanning Details:
- In addition to a confirmed offer, this response includes two extra fields:
"barcodeScanEligibleDeviceCodes"
provides a list of device codes that are allowed to perform barcode scanning."barcodeScanEnabled"
indicates that barcode scanning is active for this receipt upload.
- In addition to a confirmed offer, this response includes two extra fields:
- Offer Details: The confirmed offer is similar to previous examples.
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

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.

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.

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.

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

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

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.

Depending on the result from the upload we display accordingly


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

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.
Updated 6 days ago