Skip to main content

Send Store and Forward (SAF) Transaction

POST 

/client/users/:correlation_id/activity/saf/v2

Sends a "finalized" activity (that is, transaction details) associated with a user where the data was stored and forwarded.

If ES Loyalty and the client POS or e-Commerce storefront lose connectivity, all finalized calls should be converted to SAF for forwarding at a later date. SAF cannot process redemptions, so redemptions will be processed once connectivity is restored. SAF transactions still qualify for rewards but the transaction date will be backdated to when the offers occurred to maintain reporting accuracy.

If a purchase made by a non-loyalty account is delayed being sent into the system with this call until after the user was registered, no points are awarded since the user was not associated with a Loyalty Account when the purchase was made.

In some cases, points can only be awarded after payment or fulfillment of the order have taken place, resulting in delayed transactions. Adding the following object to the end of the call supports a delayed transaction that requires confirmation.

"confirmation": {
"mode": "CART"
}

The response includes information about the confirmation status.

"ConfirmationDetails": {
"confirmed": true,
"mode": "CART"
}

Note: For a single members or in a household, if a redemption transaction begins, but one or more of the cards are subsequently set to a non-active state such as Suspended, Lost or Stolen, Fraud/Abuse, Cancelled, or Damaged before the redemption transaction is completed, then to prevent fraud, the redemption amount is still withdrawn from the single member or proportionally from all household members who had active cards before the redemption transaction began.

Request

For information about requests, view the documentation for the Send Finalize Transaction request.

Body

AttributeDefinitionFormatNotes
actionIdentifies purchase transactionStringAlways "PURCHASE"
channelIdentifies through which channel the transaction was invokedEnum: "STORE", "POS", "WEBSITE", "APP", "PARTNER"
localeThe locale of the member from the POS system.StringOptional. Currently "en-CA" or "fr-CA". If locale is set by the POS system in the Start Session request, this overrides locale set in the member provide and as the system default.
reservationTokenUsed for purchases that include redemption.StringThis attribute is optional.
transactionDateFull date and time of the transaction.StringDate of the Transaction (Full Date and Time) must be in an ISO-8601-compliant format, for example: 2022-01-17T13:48:59-04:00.
retailBannerA store grouping or type.StringTransactions will default if a single BU or banner exists (configuration). OAuth token controls how we process. This attribute is optional.
storeNumberUsed for targeting, analytics and support.String
tillNumberUse for analytics and support.NumberThis attribute is optional.
employeeCodeCSR of the transaction.NumberThis attribute is optional for operations, but required for analytics.
loyaltyIdUnique identifier for each member.NumberThis can be captured in the Start Session. This attribute is optional.
externalTransactionIDUnique identifier for transaction used by the client.StringOptional.
priceMatrixDesignates whether the transaction is retail or an employee purchase.Enum: "R" or "E"R = Retail
E = Employee
localeUsed to change the receipt message language response for this transaction. Defaults to the client's chosen language when not present.String"en-CA" for english.
"fr-CA" for french.
callIdRequest identifier.StringCan be auto-generated if none provided. Supports tracking specific calls to be captured within a specific session for analytics. (Secondary Correlation ID). This attribute is optional.
cartContaining array of saleLineItemsObjectJSON Object containing array of saleLineItems.
saleLineItemsInformation for one item in the transaction.ArrayArray of JSON Objects.
subCategorySame subcategory as in Product feed.NumberCan be blank to force system to grab subcategory from product data. This is an optional attribute.
skuThe product identifier.NumberFor instance, this may be scanned at the Point of Sale.
quantityMeasure of product amount sold.NumberCan be partial value for unit of measure calculations where there is no directly-applicable SKU (for instance, rope sold by the foot).
originalSaleAmountThe Manufacturer's Suggested Retail Price for a product.NumberSingle-unit MSRP in pennies.
saleAmountMSRP less the discount, the actual sale price.NumberMSRP minus item discount in pennies.
storeCouponStore-based coupon.NumberThis is informational only, no active discounting occurs in ESL. This attribute is optional.
itemDiscountAmount discounted.NumberThis attribute is optional. In pennies.
mnfCouponManufacturer Coupon.NumberThis is informational only, no active discounting occurs in ESL. This attribute is optional.
promoCouponFlyer coupon.NumberThis is informational only, no active discounting occurs in ESL. This attribute is optional.
itemTaxTax on the item.NumberTax on the line item in pennies.
finalSaleAmountTotal sale amount for a specific product, the discounted price times the quantity purchased.Numberquantity * saleAmount
tagsProvides additional transaction information.StringRequired, but can be empty.
itemCostTotal cost for a specific product, the cost per unit times the quantity purchased.Numbercost per unit * quantity. This attribute is optional.
totalSaleAmountTotal of all items sold on this transaction, including tax.NumberSummed up, tax included, total of all saleLineItems. In pennies.
couponCodesPurchase-level coupons.StringThis attribute is optional.
extendedDataClient keys needed for analytics at the transaction.ObjectMaximum 1KB, 1 level deep, 10 keys maximum. This is an optional attribute.
tenderJSON Object containing transaction tender used.ObjectContains one or more type of tender and details of each (as required).
prefixPrefix of the card identifier.NumberUsually the BIN or first 6 numbers of the card. Used for partner-based offers. This attribute is optional.
idTypeType of the card identifier being passed in.String"TOKEN". This attribute is optional.
suffixSuffix of the card identifier.NumberUsually the last 4 digits. Used for partner-based offers. This attribute is optional.
amountTotal amount of the tender.NumberTotal amount of the tender that was spent using this specific card/tender.
loyaltyReserved key that denotes in cents the dollars spent by exchanging for loyalty points.NumberUsed for redemption-based actions. This attribute is optional.
confirmationUsed to indicate delayed transaction status.ObjectSee introduction to documentation for this request above for more information.
modeInclude source of confirmation required in the requestString: "CART"
cartObject containing array of saleLineItemsObjectRequired. JSON Object containing array of saleLineItems.
saleLineItemsContains details of one transaction item.ArrayRequired. JSON Object containing line items. See saleLineItems Details below this table
subcategorySame subcategory as in Product feed.NumberOptional. Can be blank to force system to grab subcategory from product data.
skuThe product identifier scanned at POS.NumberRequired
quantityMeasure of product amount sold.Number; for some clients, may include values confirmed to be as low as 0.000001Required. Can be partial value for unit of measure calculations where there is no directly-applicable SKU (for instance, rope sold by the foot).
originalSaleAmountThe Manufacturer's Suggested Retail Price for a product.NumberRequired. Single-unit MSRP in pennies.
subCategoryIdentifier for the sub-category associated with the product.String
productNameUnique product name.String
saleAmountMSRP less the discount, the actual sale price.NumberRequired. MSRP minus item discount in pennies.
storeCouponStore-based coupon.NumberOptional. This is informational only, no active discounting occurs in ESL. This attribute is optional.
itemDiscountAmount discounted.NumberOptional. This attribute is optional. In pennies.
mnfCouponManufacturer Coupon.NumberOptional. This is informational only, no active discounting occurs in ESL. This attribute is optional.
promoCouponFlyer coupon.NumberOptional. This is informational only, no active discounting occurs in ESL. This attribute is optional.
itemTaxTax on the item.NumberRequired. Tax on the line item in pennies.
finalSaleAmountTotal sale amount for a specific product, the discounted price times the quantity purchased.NumberRequired. quantity * saleAmount
tagsTo provide additional informationStringRequired, but can be empty.
rewardTagsTo provide additional information about specified rewards.ObjectRequired, but can be empty. Contains offer name(s) and associated reward(s) as key:value pairs.
itemCostTotal cost for a specific product, the cost per unit times the quantity purchased.NumberOptional. cost per unit * quantity. This attribute is optional.
couponCodesPurchase-level coupons.StringOptional.
extendedDataClient keys needed for analytics of the transaction.Optional. Maximum 1KB, 1 level deep, 10 keys maximum.
totalSaleAmountTotal of all items sold on this transaction, including tax.NumberRequired. Summed up, tax included, total of all saleLineItems. In pennies.
tenderJSON Object containing transaction tender used.ObjectRequired. Contains one or more type of tender and details of each (as required).
{tender_type}Array containing one or more objects for a particular type of tender (such as "VISA" which replaces {tender_type}).String for tender type name, then array containing an object for each instance of that tender type.Contains idType to amount below. Possible values for {tender_type}: "CASH", "COUPON" (flyer coupon), "REWARDS" (non-points rewards), "AMEX", "MSTCARD", "VISA", "GWCOUP", "MCOUPON" (manufacturer's coupon), "LOYALTY" (points)

Response

To view the hierarchy, see the example Response.

AttributeDefinitionFormatNotes
earnedContains points earned on all applicable programs.ObjectBesides "loyalty," there may be other programs such as a partner program (and related object) with additional points awarded.
loyaltyContains points earned on the loyalty program.ObjectThe attributes would be the same for other programs (if any).
baseThe number of base rewards earned on the transaction.NumberBase points = points for any transaction based on spend.
bonusThe number of bonus rewards earned on the transaction.NumberBonus points = points for completing particular behaviour.
targetedThe number of points attributable to targeted offers.NumberTargeted points = points derived from targeted offer.
totalThe total of all points earned on the transaction.Number= base + bonus + targeted points
loyaltyIDLoyalty Card number for the session.NumberIf loyaltyId was not provided in the request, then this is the primary card number on the account
pointsRedeemedThe number of points redeemed.NumberAlways 0 for this type of request. To redeem points, use Send Finalize Transaction (with Redemption).
pointsEarnedTotalThe total of points earned after redemptions.Numbertotal minus pointsRedeemed
offerRewardsContains details of one or more offer rewards.Array
offerDescriptionGeneral description of offer.StringFor instance, "Spend $20 and get 500 points."
offerDescription2Additional details of offer.StringFor instance, "Offer good through March 22."
promotionHeadlineHeadline under which offer is promoted.StringFor example: "Spend $20 and get 500 points."
offerCodeUnique code identifying offer.String
pointsEarnedPoints earned for this offer.Number
isTargetedFlags whether the transaction results from a targeted offer.Boolean
isDiscretionaryFlags whether the transaction is discretionary.Boolean
stackingUsed to provide data about reward groups and the winning group for rewards when one or more of the rewards are based on units.ObjectContains rewardGroups and winningGroup
rewardGroupsAll possible reward groups for this reward.ArrayContains one or more reward groups
winningGroupWinning reward group, the one used for this reward.StringContains one reward group from the array in rewardGroups
partnerIDIdentification of a partner.StringUsed only with partner offerRewards, if relevant.
receiptMessageMessage to show on the receipt.StringThe message may differ depending on points earned, redeemed, both, or neither.
messageDetails of transaction not shown to consumer.StringProvides information about the transaction and any redemptions.
pointsBalanceTotal number of points currently attributed to this account.NumberRewards balance in points.
redeemableBalanceMaximum currency that can currently be redeemed.NumberAn increment of a standard redemption amount. For instance, with a pointsBalance of 120000 and currency rewards of $10 per 25000 points, this value would be 40, or four increments of 10.
redeemablePointBalanceMaximum number of points that can currently be redeemed.NumberAn increment of a standard redemption amount. For example, with a pointsBalance of 110000, the user may be able to redeem 100000, or four increments of 25000.
householdObject containing information about the household to which the member belongs.ObjectOnly returned if the member is a member of a household.
idUnique identifier for the household.String
roleThe member's role in the household.Enum: "PRIMARY" or "SECONDARY"
balanceObject containing data about the balances available to the household.Object
totalPointsBalanceThe total points balance of the household.NumberThe sum of all member balances.
totalDollarBalanceThe total dollar balance of the household.NumberThe sum of all member balances.
totalAvailablePointBalanceThe total points available to the household.Number
totalAvailableDollarBalanceThe total dollars available to the household.Number
totalRedeemablePointBalanceThe total number of points that can currently be redeemed by the household members.Number
totalRedeemableDollarBalanceThe total number of dollars that can currently be redeemed by the household members.Number
minRedeemPointsThe minimum number of points that can be redeemed by the household.Number
maxRedeemPointsThe maximum number of points that can be redeemed by the household.Number
minRedeemDollarsThe minimum number of dollars that can be redeemed by the household.Number
maxRedeemDollarsThe maximum number of dollars that can be redeemed by the household.Number
cartObject containing array of saleLineItemsObjectRequired. JSON Object containing array of saleLineItems.
saleLineItemsContains details of one transaction item.ArrayRequired. JSON Object containing line items. See saleLineItems Details below this table
subcategorySame subcategory as in Product feed.NumberOptional. Can be blank to force system to grab subcategory from product data.
skuThe product identifier scanned at POS.NumberRequired
quantityMeasure of product amount sold.Number; for some clients, may include values confirmed to be as low as 0.000001Required. Can be partial value for unit of measure calculations where there is no directly-applicable SKU (for instance, rope sold by the foot).
originalSaleAmountThe Manufacturer's Suggested Retail Price for a product.NumberRequired. Single-unit MSRP in pennies.
subCategoryIdentifier for the sub-category associated with the product.String
productNameUnique product name.String
saleAmountMSRP less the discount, the actual sale price.NumberRequired. MSRP minus item discount in pennies.
storeCouponStore-based coupon.NumberOptional. This is informational only, no active discounting occurs in ESL. This attribute is optional.
itemDiscountAmount discounted.NumberOptional. This attribute is optional. In pennies.
mnfCouponManufacturer Coupon.NumberOptional. This is informational only, no active discounting occurs in ESL. This attribute is optional.
promoCouponFlyer coupon.NumberOptional. This is informational only, no active discounting occurs in ESL. This attribute is optional.
itemTaxTax on the item.NumberRequired. Tax on the line item in pennies.
finalSaleAmountTotal sale amount for a specific product, the discounted price times the quantity purchased.NumberRequired. quantity * saleAmount
tagsTo provide additional informationStringRequired, but can be empty.
rewardTagsTo provide additional information about specified rewards.ObjectRequired, but can be empty. Contains offer name(s) and associated reward(s) as key:value pairs.
itemCostTotal cost for a specific product, the cost per unit times the quantity purchased.NumberOptional. cost per unit * quantity. This attribute is optional.
couponCodesPurchase-level coupons.StringOptional.
extendedDataClient keys needed for analytics of the transaction.Optional. Maximum 1KB, 1 level deep, 10 keys maximum.
totalSaleAmountTotal of all items sold on this transaction, including tax.NumberRequired. Summed up, tax included, total of all saleLineItems. In pennies.
tenderJSON Object containing transaction tender used.ObjectRequired. Contains one or more type of tender and details of each (as required).
{tender_type}Array containing one or more objects for a particular type of tender (such as "VISA" which replaces {tender_type}).String for tender type name, then array containing an object for each instance of that tender type.Contains idType to amount below. Possible values for {tender_type}: "CASH", "COUPON" (flyer coupon), "REWARDS" (non-points rewards), "AMEX", "MSTCARD", "VISA", "GWCOUP", "MCOUPON" (manufacturer's coupon), "LOYALTY" (points)
totalTotal of the sale transaction.ObjectContains subTotal, totalSaleAmount, and taxAmount within each sale object type
{transaction status type}Status of transaction.StringFor example, "final"; contains totalSaleAmount, subTotal, and taxAmount below
totalSaleAmountThe total amount of the sale including tax.String
subTotalThe total amount of the sale before tax.String
taxAmountThe tax generated on the sale.String

Error Responses

statusCodeerrorMessageerrorCodeDefinition
400 Bad RequestSession correlation ID does not exist--create it first.INVALID_REQUESTMust send request with an existing correlation ID
400 Bad RequestSession ClosedINVALID_REQUESTThe session was closed, so this request cannot be made
400 Bad RequestSession ExpiredINVALID_REQUESTThe session has expired, so this request cannot be made
400 Bad RequestCart cannot contain zero-quantity line itemsINVALID_REQUESTLine items in the cart must have a quantity of 1 or more
400 Bad RequestInvalid extended data: Exceeded data size limit for extended data: {dataSize} BytesINVALID_REQUESTWhen extendedData size exceeds the size limit. See the limit on ConfigType = EXTENDED_DATA, on Platform.DataSizeLimitInKb.
400 Bad RequestInvalid Extended data : Exceeded root level key limit for extended data : {numberOfKeys} keysINVALID_REQUESTWhen extendData exceeds number of attributes/keys limit. See the limit on ConfigType = ‘EXTENDED_DATA’, on Platform.TopLevelKeysLimit.
400 Bad RequestChannel should be a string value.INVALID_REQUESTCannot use data type other than string value for channel attribute. For example, channel attribute value cannot be a Boolean (rue, false, or null).
409 ConflictToo many simultaneous requests for the same accountINVALID_REQUESTReduce number of simultaneous requests

Request

Responses

200 - Store and Forward

Response Headers
    Date
    Example: Fri, 02 Oct 2020 18:59:20 GMT
    Content-Length
    Example: 922
    Connection
    Example: keep-alive
    x-amzn-RequestId
    Example: d6ebe9ad-39e4-474b-a3f3-5f39e7e7bb17
    Referrer-Policy
    Example: no-referrer
    X-XSS-Protection
    Example: 1;mode=block
    Access-Control-Allow-Origin
    Example: *
    Expect-CT
    Example: max-age=86400
    Strict-Transport-Security
    Example: max-age=31536000
    Feature-Policy
    Example: vibrate 'none'; geolocation 'none'
    X-Frame-Options
    Example: sameorigin
    Content-Security-Policy
    Example: connect-src 'none';object-src https://*.cloudfront.net;script-src https://*.cloudfront.net
    x-amz-apigw-id
    Example: Ty_FPGchoAMF4Ag=
    cache-control
    Example: no-cache, no-store, must-revalidate
    X-Content-Type-Options
    Example: nosniff
    X-Amzn-Trace-Id
    Example: Root=1-5f777887-1018d63f53d5cba41cdd578b;Sampled=0