Guide: How to use the Walmart Affiliate API with NodeJS

●3 MIN READ

Guide: How to use the Walmart Affiliate API with NodeJS

As I explained in my post “On Making Price Trackers”, I prefer to only make a price tracker for a shop if it has an API for me. And luckily, Walmart has one, so I decided to build Waltrack.net, the first free Walmart Price Tracker.

However, the road from making my Walmart developer account to actually making my first API call was a bumpy one. The API requires you to create a keypair and use the secret key to sign the request. Something I haven’t done before.

Luckily I managed to get it working and hopefully with this blogpost you won’t have to spend as much time figuring things out as I did.

Assuming you already have your Walmart.io developer account, the first step is to create an application and create an RSA keypair.

Walmart’s guide on this is solid, so you can just follow it.

When you copy-and-pasted the public key to the upload page on Walmart.io you are ready to make your first API call

Making your first API call to Walmart.io

If you want to comment on this code, you can do so on the Github Gist I created.


import NodeRSA from "node-rsa";

const keyData = {
    consumerId: "CONSUMER_ID",
    privateKey: `-----BEGIN RSA PRIVATE KEY-----
MY PRIVATE KEY
-----END RSA PRIVATE KEY-----`,
  keyVer: 1,
  impactId: "YOUR IMPACT AFFILIATE ID" // not required
},
    
    
const generateWalmartHeaders = () => {
  const { privateKey, consumerId, keyVer } = keyData;
  const hashList = {
    "WM_CONSUMER.ID": consumerId,
    "WM_CONSUMER.INTIMESTAMP": Date.now().toString(),
    "WM_SEC.KEY_VERSION": keyVer,
  };

  const sortedHashString = `${hashList["WM_CONSUMER.ID"]}\n${hashList["WM_CONSUMER.INTIMESTAMP"]}\n${hashList["WM_SEC.KEY_VERSION"]}\n`;
  const signer = new NodeRSA(privateKey, "pkcs1");
  const signature = signer.sign(sortedHashString);
  const signature_enc = signature.toString("base64");

  return {
    "WM_SEC.AUTH_SIGNATURE": signature_enc,
    "WM_CONSUMER.INTIMESTAMP": hashList["WM_CONSUMER.INTIMESTAMP"],
    "WM_CONSUMER.ID": hashList["WM_CONSUMER.ID"],
    "WM_SEC.KEY_VERSION": hashList["WM_SEC.KEY_VERSION"],
  };
};



export const getProductById = async (productId) => {
  const options = {
    method: "GET",
    headers: generateWalmartHeaders(),
  };

  const res = await fetch(
    `https://developer.api.walmart.com/api-proxy/service/affil/product/v2/items/${productId}?publisherId=${keyData.impactId}`,
    options
  );
  
  return await res.json()
};

Note: If you get an error saying thate node-rsa Expected 0x2: got 0x30, you can try to convert your key. I am not that proficient with SSL/RSA and keys and all that, but using this tool to transform my PKCS#8 to PKCS#1 did the trick.

Also make sure you don’t have any wrong indentation.

This will work:

const keyData = {
    consumerId: "CONSUMER_ID",
    privateKey: `-----BEGIN RSA PRIVATE KEY-----
MY PRIVATE KEY
-----END RSA PRIVATE KEY-----`,
  keyVer: 1,
  impactId: "YOUR IMPACT AFFILIATE ID" // not required
},
    

This won’t work:

const keyData = {
    consumerId: "CONSUMER_ID",
    privateKey: `-----BEGIN RSA PRIVATE KEY-----
                 MY PRIVATE KEY
                 -----END RSA PRIVATE KEY-----`,
  keyVer: 1,
  impactId: "YOUR IMPACT AFFILIATE ID" // not required
},
    

This won’t work either:

const keyData = {
    consumerId: "CONSUMER_ID",
    privateKey: `-----BEGIN RSA PRIVATE KEY-----MY PRIVATE KEY-----END RSA PRIVATE KEY-----`,
  keyVer: 1,
  impactId: "YOUR IMPACT AFFILIATE ID" // not required
},
    

Explaining how to make Walmart API Headers


const generateWalmartHeaders = () => {
  const { privateKey, consumerId, keyVer } = keyData;
  const hashList = {
    "WM_CONSUMER.ID": consumerId,
    "WM_CONSUMER.INTIMESTAMP": Date.now().toString(),
    "WM_SEC.KEY_VERSION": keyVer,
  };

  const sortedHashString = `${hashList["WM_CONSUMER.ID"]}\n${hashList["WM_CONSUMER.INTIMESTAMP"]}\n${hashList["WM_SEC.KEY_VERSION"]}\n`;
  const signer = new NodeRSA(privateKey, "pkcs1");
  const signature = signer.sign(sortedHashString);
  const signature_enc = signature.toString("base64");

  return {
    "WM_SEC.AUTH_SIGNATURE": signature_enc,
    "WM_CONSUMER.INTIMESTAMP": hashList["WM_CONSUMER.INTIMESTAMP"],
    "WM_CONSUMER.ID": hashList["WM_CONSUMER.ID"],
    "WM_SEC.KEY_VERSION": hashList["WM_SEC.KEY_VERSION"],
  };
};

To create the headers we need 4 things:

  1. The private key
  2. The Consumer ID from the Walmart IO Dashboard
  3. The Key Version, also from the Walmart IO Dashboard (see screenshot below)
  4. A NodeJS library to read and sign the private key – I used node-rsa ( yarn add node-rsa )

Basically what you have to do with the headers is concatenate the Consumer ID, the Timestamp and the Key Version with new lines between them.

Then sign that string with your private key and convert it to base64. Then append this base64 string in the headers, so Walmart on their side can check with the public key you uploaded before if it’s actually you. It’s kinda how SSL certificates work as well.


That’s in a nutshell how to create API calls to the WalmartIO API. All in all it’s not that hard, but it’s kinda unusual to use a secret key to sign an API request.

For any questions or problems you run into, you can comment on the Github gist here.

Happy Walmart API hacking!

Jelle

More polaroids I want to share

CLICK OR DRAG THE TOP ONE ASIDE

You've reached the end of the shoebox. More polaroids and other posts live on my Instagram.

@GMJELLE →
Polaroid of a calm lake at dusk reflecting pink clouds and dark hills, at a wild campsite near Adana, Turkey
Polaroid of Josip Broz Tito's marble tomb seen through plant leaves in Belgrade, Serbia
Polaroid of a motorcycle parked at a Soviet-era bus stop decorated with a flower mosaic in Moldova
Polaroid of a large stone statue of a bearded man in a long coat on a hillside near Buzludzha, Bulgaria
Polaroid of the saucer-shaped Buzludzha Monument on a distant hilltop above the trees in Bulgaria
Polaroid of a man standing in front of the Buzludzha Monument and its tower in Bulgaria
Polaroid of a valley of pale, cone-shaped rock formations in Cappadocia, Turkey
Polaroid of hot air balloons silhouetted against the dawn sky in Cappadocia, Turkey
Polaroid of the brutalist Cosmos Hotel tower in Chisinau, Moldova
Polaroid of the Tomb of Cyrus the Great on its stepped stone base at Pasargadae, Iran
Polaroid of a close view of the Tomb of Cyrus the Great at Pasargadae, Iran
Polaroid of a converted red fire truck camper and a motorcycle at a campsite on the west coast of Turkey
Polaroid of a mosque minaret and domes silhouetted against a cloudy sky in Edirne, Turkey
Polaroid of the Mimar Sinan statue in front of the Selimiye Mosque in Edirne, Turkey
Polaroid of the courtyard of a historic house with a fountain and colored-glass windows in Isfahan, Iran
Polaroid of a man standing next to an Isfahan city emblem sign on a sidewalk in Isfahan, Iran
Polaroid of the tiled dome and entrance portal of the Sheikh Lotfollah Mosque in Isfahan, Iran
Polaroid of the tiled entrance portal and twin minarets of the Shah Mosque in Isfahan, Iran
Polaroid of a columned palace silhouetted at sunset behind a fountain pool on Naqsh-e Jahan Square, Isfahan, Iran
Polaroid of a dark interior lit through colorful stained-glass windows in a historic house in Isfahan, Iran
Polaroid of rocky ridges and rock formations under a cloudy sky near Goreme, Cappadocia, Turkey
Polaroid of a loaded motorcycle parked by a desert road with mountains behind it in Iran
Polaroid of a loaded motorcycle with a helmet on the mirror, parked on a coastal road near Izmir, Turkey
Polaroid of a Soviet-era mosaic of workers and a motorcyclist on a building wall in Lutsk, Ukraine
Polaroid of a Soviet-era mosaic of a crowned woman holding scales, framed by tree leaves in Lviv, Ukraine
Polaroid of the Lviv Opera House facade with a fountain in front in Lviv, Ukraine
Polaroid of a Soviet WWII memorial column with a stork's nest on top in northern Moldova
Polaroid of a large Soviet-era mural of figures on a wall beside a tree in Moldova
Polaroid of royal tombs carved into the cliff face at Naqsh-e Rustam near Persepolis, Iran
Polaroid of a stone relief of a Persian soldier holding a spear at Persepolis, Iran
Polaroid of the Gate of All Nations with its winged bull statues and columns at Persepolis, Iran
Polaroid of four men sharing dinner at a table in a traditional hostel in Shiraz, Iran
Polaroid of the tiled courtyard and reflecting pool of the Nasir al-Mulk (Pink) Mosque in Shiraz, Iran
Polaroid of two men smiling at a restaurant table in Tabriz, Iran
Polaroid of the mirrored hall of Golestan Palace lit by large chandeliers in Tehran, Iran
Polaroid of the bronze statue of Leonidas raising a spear at the Thermopylae monument, Greece
Polaroid of a man looking up at the wooden Trojan Horse from the Troy film in Canakkale, Turkey
Polaroid of a backgammon board on a table overlooking the sea at a campsite in Turkey
Polaroid of a Soviet-era mosaic of a woman in traditional dress under a Ukrainian coat of arms in Ukraine
Polaroid of a motorcycle parked at a bus stop with a mosaic of three knights in Ukraine
Polaroid of a man standing on a boardwalk in front of the stairway of the Ziggurat of Ur, Iraq
Polaroid looking up the brick stairway of the Ziggurat of Ur, Iraq
Polaroid of eroded mud-brick ruins with a small sign in front at Uruk, Iraq
Polaroid of a man and two boys crouching by a freshly slaughtered sheep on grass on the road to Van, Turkey
Polaroid looking up at the curved glass Zlota 44 skyscraper in Warsaw, Poland
Polaroid of the Palace of Culture and Science lit at dusk in Warsaw, Poland
Polaroid of the Zoroastrian Fire Temple with a round reflecting pool in Yazd, Iran