API Programs > Photo Prints: HTML Checkout API

Photo Prints: HTML API


The Walgreens HTML Checkout PhotoPrints API gives the ability for customers of third party mobile photo applications to print photos from their mobile devices and pick them up at their local Walgreens store.

Documentation/Services Highlights: /v1:

  • Added detailed description tables for all the request json body parameters!
  • A REST HTML based photo print checkout
  • Supports callbacks after checkout completion
  • Ability to upload images to Walgreens Storage via REST approach
  • Increased imageURL quantities to 200 images per order!

Below are the technical steps you will need to go through in order to get your integration configured and branded correctly:


The external services listed below make up the complete list of services that are required in order to complete all phases of the PhotoPrints experience. Please note that all of the service endpoints documented below are brand new for this version of the PhotoPrints API.

Checkout

  • Upload:
    POST /api/photo/creds/v3
  • Obatin Landing URL:
    POSTapi/util/v3.0/mweb5url
  • Open:
    POST {LANDING_URL}
  • Callback:
    POST {CALLBACK_URL}

Fetch Upload Credentials

This endpoint can be used to fetch the credentials needed to upload images to the Walgreens Storage server. Take note, when uploading to our storage, the files will not be accessible once uploaded and you should save image data if planning to use later in your checkout flow for previewing the images.

Endpoint URL

Sandbox:
https://services-qa.walgreens.com/api/photo/creds/v3
Production:
https://services.walgreens.com/api/photo/creds/v3

Endpoint Information

Request format JSON
Response format JSON
Authentication? Yes
Rate limited? Yes
Requests Per Minute 300

Request Body

Name Optionality Description Example
apiKey required Your API Key. "AbCdEfGhIjKlMnOpQrStUvWxYz"
affId required Your AffiliateID. "AAAAAAAAAA"
platform required The software platform. "ios" || "android"
transaction required A static value describing the reason for fetching the credentials. "photocheckoutv2"
appVer optional The build version of your application. "1.0"
devInf optional The device manufacturer and version. "iPhone,13.0"

Example Request

curl --request POST \ 
--url https://services-qa.walgreens.com/api/photo/creds/v3  \
--header 'Content-Type: application/json' \
--data '{ \
	"apiKey":"YOUR_API_KEY", \
        "affId":"YOUR_AFFILIATE_ID", \
        "platform":"ios", \
	"transaction":"photocheckoutv2", \ 
	"devInf":"DEVICE,##.#" \
	"appVer":"#.#", \
}' \
						

Example Response

{
    "uploadLimit": 200,
    "template": "default",
    "landingUrl": "https://m5.walgreens.com/photoprints/",
    "cloud": [{
        "sasKeyToken": "https://pstrgqp01.blob.core.windows.net/qpcontainerin?sig=
        BLAHBLAHBLAH&se=YYYY-MM-DDT22%3A53%3A57Z&sv=YYYY-MM-DD&sp=w&sr=c"
    }]
}
						

Generate Upload Token

Before an image can be uploaded, the value for the "sasKeyToken" (looks like a url) must be converted correctly into the "Upload_URL" . This is completed by doing the following:

Step by Step Guide

  • A) Split the "sasKeyToken" value on the "?" character into a string array
  • B) Create a string from the first element of the string array lets call it "blobContainerSplit"
  • C) Create a string from the second element of the string array lets call it "signature"
  • D) Create a string of the imageName, example: "Image-"+ YOUR_AFFILIATE_ID +"-"+ generateUUID() +".jpg" lets call it imageName
  • E) Generate the "Upload_URL" like so: blobContainer +"/"+ imageName +"?"+ signature

Example Code

SWIFT:
let blobContainer:String = sasToken.components(separatedBy: "?").first!
let signature:String = sasToken.components(separatedBy: "?").last!
let imageName:String = "Image-\(affId)-\(UUID().uuidString).jpg"
let Upload_URL:String = "\(blobContainer)/\(imageName)?\(signature)"

KOTLIN:
var blobContainer:String = sasToken.split("?").toTypedArray().first()
var signature:String = sasToken.split("?").toTypedArray().last()
var imageName:String = Image-".plus(affId).plus("-").plus(UUID.randomUUID().toString()).plus(".jpg")
var Upload_URL:String = blobContainer.plus("/").plus(imageName).plus("?").plus(signature)

JAVASCRIPT:
function generateUUID() 
{
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c)
{
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
}
var blobContainer = sasToken.split("?").shift();
var signature = sasToken.split("?").pop();
var imageName = "Image-"+affId+"-"+generateUUID()+".jpg";
var Upload_URL = blobContainer+"/"+imageName+"?"+signature;
		
                    

Example Response

https://pstrgqp01.blob.core.windows.net/qpcontainerin/
Image-YOUR_AFFILIATE_ID-a12b3cd-e4f5-6789-ghi0-1234567j89kl.jpg?
sig=BLAHBLAHBLAH&se=YYYY-MM-DDT22%3A53%3A57Z&sv=YYYY-MM-DD&sp=w&sr=c
					

Upload Images

To upload an image, make a PUT request to the generated "UPLOAD_URL" with the custom HTTP headers. Place the image data to be uploaded in the HTTP body. If multiple images are to be printed, repeat the process above for every single image.

Endpoint URL

The image url is generated using the process above.

Endpoint Information

Request format Binary Data
Response format XML
Authentication? Yes
Rate limited? No

Request Headers

Name Optionality Description Example
Content-Type required The type of image format for the file. We convert the file to JPEG on our side, however we prefer you do this on your side. "img/jpeg"
Content-Length required The count of the bytes of data in the image file. "1073741824"
x-ms-client-request-id required A Universally Unique Identifier (UUID) for each request. "a12b3cd-e4f5-6789-ghi0-1234567"
x-ms-blob-type required A static value describing the request upload type. "BlockBlob"

Request Body

The binary data of the image file.

Example Request

curl -X PUT \
'https://pstrgqp01.blob.core.windows.net/qpcontainerin/Image-YOUR_AFFILIATE_ID-a12b3cd-e4f5-6789-ghi0-1234567j89kl.jpg?sig=BLAHBLAHBLAH&se=YYYY-MM-DDT22%3A53%3A57Z&sv=YYYY-MM-DD&sp=w&sr=c' \
-H 'Content-Length: 1073741824' \
-H 'Content-Type: image/jpeg' \
-H 'x-ms-blob-type: BlockBlob' \
-H 'x-ms-client-request-id: a12b3cd-e4f5-6789-ghi0-1234567' --upload-file image.jpeg
						

Example Response


HTTP STATUS CODE: 201
                        
						

Custom Upload Images

You are absolutely able to use your own url for images uploaded to another server then the Walgreens server. Please ensure the url is accessible for at least 36 hours (due to delays at store level) with a simple HTTP Get Request and that as that is how our image downloader will get the file to the store.

Obtain the LandingURL:

The landing URL can be obtained from the findURL web service, this url allows the customer to do the Photo Print Checkout.

Endpoint URL

Sandbox:
https://services-qa.walgreens.com/api/util/v3.0/mweb5url
Production:
https://services.walgreens.com/api/util/v3.0/mweb5url

Name Optionality Description Example
apiKey required Your API Key. "AbCdEfGhIjKlMnOpQrStUvWxYz"
affId required Your AffiliateID. "AAAAAAAAAA"
productGroupId optional Used to differentiate product groups. "Standard Prints (STDPR) vs Square Prints (SQR01)"
publisherId optional Used to associate the order to your publisher account Sign up here
channelInfo optional The channelInfo is used to pass the type of integration. Only set this as "web" if your integration is a website. If you integration is a mobile application pass an empty string. "web" || " "
callBackLink optional The callBackLink is used to pass URL we callback to after order submission/cancellation. "Only set this if your integration is a website. DO NOT PASS IF YOUR APPLICATION IS A MOBILE APP."
expiryTime required The expiryTime is obtained from the expiryTime used to generate your uploaded photos, or, 36 hours from right now. "0000"
images required The images parameter is an array of all your uploaded photos ["URL1","URL2",etc...]
lat required The Latitude coordinate of the user. "42.138199"
lng required The Longitude coordinate of the user. ""-87.945799"
customer required The customer object contains (the next 4 parameters) all the info needed to pre-populate the order submission pages. "firstName"
firstName required The customers first name. "firstName"
lastName required The customers last name. "lastName"
email required The email value is the email address of the customer. "email@domain.tld"
phone required The customers phone number. "##########"
transaction required The Transaction is a value that invokes our internal service. "photoCheckoutv2"
act required The Action is a value that invokes our internal service. "mweb5UrlV2"
view required The View is a value that invokes our internal service. "mweb5UrlV2JSON"
devInf required The device manufacturer and version. "iPhone,13.0"
appVer required The build version of your application. "1.0"

Example Request

curl --request POST \ 
--url https://services-qa.walgreens.com/api/photo/creds/v3  \
--header 'Content-Type: application/json' \
--data '{ \
    "apiKey": "YOUR API KEY",
    "affId": "YOUR AFFILIATE ID",
    "productGroupId": "PRODUCT GROUP ID",
    "publisherId": "YOUR PUBLISHER ID",
    "channelInfo": "CHANNEL INFO: web or ''",
    "callBackLink": "IF CHANNEL INFO IS web: YOUR CALLBACK URL",
    "expiryTime": "IMAGE EXPIRATION TIME",
    "images": [
        "URL1",
        "URL2",
        "URL3",
        "etc..."
    ],
    "lat": "CUSTOMER LATITUDE",
    "lng": "CUSTOMER LONGITUDE",
    "customer": {
        "firstName": "CUSTOMER FIRST NAME",
        "lastName": "CUSTOMER LAST NAME",
        "email": "CUSTOMER EMAIL ADDRESS",
        "phone": "CUSTOMER PHONE NUMBER"
    },
    "transaction": "photoCheckoutv2",
    "act": "mweb5UrlV2",
    "view": "mweb5UrlV2JSON",
    "devinf": "THE DEVICE INFO",
    "appver": "THE APP VERSION",
    "affNotes": "TRACKING ID / NOTES"
}' \
						

Example Response

{
    "landingUrl": "CHECKOUT_LANDING_URL",
    "template": "TEMPLATE_FOR_CUSTOM_TEMPLATES",
    "uploadLimit": "UPLOAD_LIMIT_FOR_YOUR_ACCOUNT",
    "token": "ACCESS_TOKEN_FOR_CHECKOUT",
    "err": "ERROR_CODE_NUMBER"
}
					

Open the LandingURL:

Once a LandingURL has been obtained, the URL should be loaded in a WebView/Browser Window.

To properly open the URL you must append the value of "token" to queryString of the "landingUrl".

Example Response

{GET:landingUrl+"&token="+token}
                    

Handling Callbacks:

Once the user has loaded the checkout page there are some button interactions that must be handled by the callback URL passed in generating the checkout:

Possible Callback Scenarios:

  • When the user taps the "Cancel" button on the landing page
  • When the user taps the "Back" button on the landing page
  • When the user taps the "Done" button on the landing page

Error Codes

Error Codes & Messages for Photo Prints Service:

Obviously we don't want any errors to happen, but sometimes they do and as a result we respond the following error codes. The table below helps explain why each of the error codes could occur:

Code Type Message
143 ERROR If there is any exception in web service.
500 ERROR If the Affiliate ID is invalid.
501 ERROR If the operation is not supported.
502 ERROR If there is an error in getting Affiliate Info.
503 ERROR If the request is not made in secure mode.
504 ERROR If the session is not secure.
505 ERROR If the view is not found.
506 ERROR If the service action is not found
507 ERROR If there is no mapping in droplet.
508 ERROR If the required parameter is missing.
509 ERROR If the view parameter is missing.
510 ERROR If there is an exception.
511 ERROR If there is no mapping in droplet.
512 ERROR If the required view parameter is missing.
513 ERROR If the Token is invalid.
524 ERROR If there is an exception in the findURLV2 service.
525 ERROR If Image URL list is invalid.
527 ERROR For affiliate notes exceeding more than 240 characters.
654 ERROR Missing Product ID.
659 ERROR If there is no match for the vendor.
691 ERROR If internal services are down while validating Single Use Coupons.
2003 ERROR When the credentials are invalid then it will give this Exception.
2009 ERROR Service Unavailable Exception.
2010 ERROR For any Exception in Service.
6002 ERROR Order already placed.
6003 ERROR Order Cancelled Error code.
6004 ERROR Repeated order cancelled.
6006 ERROR If multiimgqty attribute is empty for Creative Products.
6007 ERROR If Creative Product Indicator is empty for Creative Orders.
6008 ERROR MIQ and CPI are invalid.

Finding mweb5 URL:

Code Type Message
111 ERROR For any Exception with the service.
112 ERROR Your affiliateID is setup incorrectly.
632 ERROR If required parameters are missing.

Price List Errors:

Code Type Message
659 ERROR AffiliateID setup is invalid.
991 ERROR Product Details Not Found.
9111 ERROR Exception when fetching Price List.
9112 ERROR Exception in Price List Service.

Coupon Discount Errors:

Code Type Message
656 ERROR Coupon Code is empty.
661 ERROR Coupon code is invalid.
682 ERROR If coupon is already used.
683 ERROR If coupon or promotion is expired.
684 ERROR If coupon code is not found.
685 ERROR Web service System Error while coupon service validation.
686 ERROR If store Number is empty.
687 ERROR If Coupon redemption date is invalid.
688 ERROR If coupon RFN number is empty.
689 ERROR If invalid amount or null amount.
690 ERROR If Barcode is null or empty.
1006 ERROR If the input parameters are invalid.
9100 ERROR If the Product details are missing.
9102 ERROR If there is an internal exception occurred.
9103 ERROR If there is a JSON exception.
9107 ERROR If the quantity is missing.

Store List Errors:

Code Type Message
651 ERROR Invalid Search.
652 ERROR No Stores Available.
653 ERROR No Search Parameter Given.
851 ERROR One or many of the Mandatory fields are empty.
1601 ERROR If the ProductID is missing.
1602 ERROR If the Quantity is missing.
9100 ERROR If the Product details are missing.
9104 ERROR If there is an Internal Exception
9105 ERROR If there is a JSON exception.
9106 ERROR If there is an Internal Exception.

Submit Order Errors:

Code Type Message
527 ERROR If the Affiliate Notes at maximum length.
630 ERROR If the phone number is invalid.
631 ERROR If the promise time is invalid.
632 ERROR If any of the mandatory fields is null.
633 ERROR Exception in service.
634 ERROR If the order is not successful.
640 ERROR If the coupon code is invalid.
660 ERROR If the quantity is invalid.
664 ERROR If Number of Images is greater then 200.
665 ERROR If Number of Prints Per Image is > 10.
851 ERROR One or many of the Mandatory fields are empty.
1016 ERROR If Invalid Image URLs are passed.
9104 ERROR If the image quantity is not with the range.