Retrieve Products

To be able to look for products in your catalogue, you need, as a prerequisite, to get an access token.
The steps to get a token are described in the Authentication and tokens page.

Once you are authenticated, you are able to look for your products in your catalogue

Retrieve your first Product

Now that you are authenticated, to get your first product, take one of the gtin of your SupplierXM catalog.

# Get product
filter_payload = {
    "filter_gtins_in": ["03036811359935"], # update with one of your gtin
    "filter_source_include": ["gtin", "nameLegal"], # retrieve only 2 fields
}

# Call the products API
response = requests.post(
  "https://apis.supplierxm.salsify.com/public/v1/products/list",
  data=json.dumps(filter_payload),
  headers=headers # previously set with authentication token
)

# Response contains:
# {"data": [{"gtin": "03036811359935", "nameLegal":[{"expressedIn": {"code": "eng-GB"}, "data": "My first product"}]}]}

# Iterate on the product list
for product in response.json()['data']:
    # Retrieve the data in english
    nameLegal = next((n['data'] for n in product.get('nameLegal', []) if n['expressedIn']['code'] == 'eng-GB'), None)
    print '%r -> %r' % (product.get('gtin'), nameLegal)

# >> '03036811359935' -> 'My first product'
>> replace 03036811359935 with your own gtin :)
>> add your access token to the HTTP header 

curl 'https://apis.alkemics.com/public/v1/products/list' -XPOST -d'{"filter_gtins_in":["03036811359935"],"filter_source_include": ["gtin", "nameLegal"]}' \
-H 'Authorization: Bearer {your access token}'

>> {
  "totalResults": 1,
  "data": [
    {
      "nameLegal": [
        {
          "expressedIn": {
            "code": "eng-GB",
          },
          "data": "My first product"
        }
      ],
      "gtin": "03036811359935",
    }
  ],
  "offset": 0
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class AlkClientPost {
	public static void main(String[] args) {
	  try {
		URL url = new URL("https://apis.supplierxm.salsify.com/public/v1/products/list");
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setDoOutput(true);
		conn.setRequestMethod("POST");
		conn.setRequestProperty("Content-Type", "application/json");
		conn.setRequestProperty("Authorization", "Bearer SALSIFY_TOKEN");
      
		String input = "{\"filter_gtins_in\":[\"03036811359935\"],\"filter_source_include\": [\"gtin\", \"nameLegal\"]}";
		/* Print the HTTP response code */
    System.out.println(conn.getResponseCode());
		
    BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
		String output;
    /** Print the API call response 
    /* Response contains:
		/* {"data": [{"gtin": "03036811359935", "nameLegal":[{"expressedIn": {"code": "eng-GB"}, "data": "My first product"}]}]}
    **/
		while ((output = br.readLine()) != null) {
			System.out.println(output);
		}
      
		conn.disconnect();
	  } catch (MalformedURLException e) {
		e.printStackTrace();
	  } catch (IOException e) {
		e.printStackTrace();
	 }
	}
}

Retrieve recent Products

You can also retrieve Products updated after a specific timestamp

# Get product
filter_payload = {
    "filter_source_include": ["gtin", "nameLegal", "updatedAt"], # retrieve only 3 fields
    "updated_at_from": "1659312000" # retrieve only the products updated from 01/08/2022 00:00:00
}

# Call the products API
response = requests.post(
  "https://apis.supplierxm.salsify.com/public/v1/products/list",
  data=json.dumps(filter_payload),
  headers=headers # previously set with authentication token
)

# Response contains:
# {"data": [{"gtin": "03036811359935", "nameLegal":[{"expressedIn": {"code": "eng-GB"}, "data": "My first product"}], "updatedAt": "2022-08-08T12:14:48"},
# {"gtin": "03036811359936", "nameLegal":[{"expressedIn": {"code": "eng-GB"}, "data": "My second product"}], "updatedAt": "2022-08-06T10:46:24"}]}

# Iterate on the product list
for product in response.json()['data']:
    # Retrieve the data in english
    nameLegal = next((n['data'] for n in product.get('nameLegal', []) if n['expressedIn']['code'] == 'eng-GB'), None)
    print('%r -> %r updated at %r' % (product.get('gtin'), nameLegal, product.get('updatedAt')))

# >> '03036811359935' -> 'My first product' updated at '2022-08-08T12:14:48'
# >> '03036811359936' -> 'My second product' updated at '2022-08-06T10:46:24'
>> replace 1659312000 with the timestamp you want :)
>> add your access token to the HTTP header 

curl 'https://apis.alkemics.com/public/v1/products/list' -XPOST -d'{"filter_source_include": ["gtin", "nameLegal", "updatedAt"], "updated_at_from": "1659312000"}' \
-H 'Authorization: Bearer {your access token}'

>> {
  "totalResults": 2,
  "data": [
    {
      "gtin": "03036811359935", 
      "nameLegal":[
        {
          "expressedIn": {
            "code": "eng-GB"
          },
          "data": "My first product"
        }
      ], 
      "updatedAt": "2022-08-08T12:14:48"
    }, 
    {
      "gtin": "03036811359936", 
      "nameLegal":[
        {
          "expressedIn": {
            "code": "eng-GB"
          },
          "data": "My second product"
        }
      ], 
      "updatedAt": "2022-08-06T10:46:24"
    }
  ],
  "offset": 0
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

public class AlkClientPost {
	public static void main(String[] args) {
	  try {
		URL url = new URL("https://apis.supplierxm.salsify.com/public/v1/products/list");
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setDoOutput(true);
		conn.setRequestMethod("POST");
		conn.setRequestProperty("Content-Type", "application/json");
		conn.setRequestProperty("Authorization", "Bearer SALSIFY_TOKEN");
      
    /* Retrieve only 3 fields of the products updated from 01/08/2022 00:00:00 */
		String input = "{\"filter_source_include\": [\"gtin\", \"nameLegal\", \"updatedAt\"], \"updated_at_from\": \"1659312000\"}";
		/* Print the HTTP response code */
    System.out.println(conn.getResponseCode());
		
    BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
		String output;
    /** Print the API call response 
    /* Response contains:
		/* {"data": [{"gtin": "03036811359935", "nameLegal":[{"expressedIn": {"code": "eng-GB"}, "data": "My first product"}], "updatedAt": "2022-08-08T12:14:48"},
		/* {"gtin": "03036811359936", "nameLegal":[{"expressedIn": {"code": "eng-GB"}, "data": "My second product"}], "updatedAt": "2022-08-06T10:46:24"}]}
		**/
		while ((output = br.readLine()) != null) {
			System.out.println(output);
		}
      
		conn.disconnect();
	  } catch (MalformedURLException e) {
		e.printStackTrace();
	  } catch (IOException e) {
		e.printStackTrace();
	 }
	}
}

List/search/filter Products

Two methods are available to retrieve products according to the use case:

  • GET: to retrieve one or more products: List Product
    For this method, a limit is set to 500 products if there is no filtering on fields, and to 4000 products if there is filtering (filter_source_include)

  • POST: to retrieve a large number of products: Search Product

In order to filter the products on a specific organization, you need to use the services with additional filters:

filter_owners_in allows you to specify the organization identifier

filter_target_market allows you to request only product sold in France. (market code : 250, see ISO-3166 numeric country codes for more information).

https://apis.supplierxm.salsify.com/public/v1/products?filter_target_market=**250**&filter_owners_in=**ORG_ID**

limit allows you to set the maximum number of products you want to retrieve. By default the limit parameter is set to 20. The max value is 500. To optimize performances we advise you to use a limit of 50 and then make multiple consecutive calls using offset parameter for pagination.

filter_source_include allows you to retrieve only some fields by specifying the list of fields. We strongly encourage you to use this filter to have better response times by restricting the amount of data returned to what is really necessary

Using the Pagination system

You can paginate the API using the parameters limit and offset if you don't have a lot of products (<10000).
To retrieve more than 10K elements you need to use "scroll search" by doing the following:

  • On the first call, set next_page to "" (empty string in double quotes for POST request, nothing for GET request) and set the limit (50 for instance).
  • On the following calls, pass the next_page parameter with the value returned by the previous call (next_page can change after each call but don't necessarily do). You still need to pass a limit parameter (you can actually change it after each call, but it's recommended not to change it).
  • You have 2 minutes between each calls to make the following call, after this, the next_page will be invalid and you will have to restart from the beginning (ie: set next_page to "").

📘

Choose the best pagination method

In order to choose the best pagination method you should use, you can make a first call to get the number of products matching your request.

Make a first call with all the filters to apply for the products you want to retrieve and set the parameters limit to 1 and filter_source_include with 1 specific field like UUID (to optimize the call).

curl --request GET \
  --url 'https://apis.supplierxm.salsify.com/public/v1/products?filter_target_market=250&filter_product_languages=fr&limit=1&offset=0&filter_tags_in=exportable&filter_source_include=uuid' \
  --header 'Accept: application/json' \
  --header 'Accept-language: fr' \
  --header 'Authorization: Bearer AUTHORIZATION_TOKEN'

In the response, you will get a totalResults field showing you how many products matches your request and be able to choose the suited pagination method.

{
  "offset":0
  "data":[
    {
      "id":"123456"
      "uuid":"12345678-aaaa-bbbb-cccc-1234567890ab"
    }
  ]
  "totalResults":12345
}

Here is a code example to use the two different pagination methods

# Get nb of products
filter_payload = {
  "filter_source_include": ["gtin"],  # retrieve only 1 field
  "limit": "1",  # retrieve 1 product at a time
  "offset": "0"  # set the offset to paginate the results
}
# Call the products API
response = requests.post(
  "https://apis.supplierxm.salsify.com/public/v1/products/list",
  data=json.dumps(filter_payload),
  headers=headers  # previously set with authentication token
)
offset = 0
limit = 50
next_page = ""
nb_products = response.json()['totalResults']
nb_products_retrieved = 0

if nb_products < 10000:
  while nb_products_retrieved < nb_products:
    # Get products
    filter_payload = {
      "filter_source_include": ["gtin", "nameLegal"],  # retrieve only 2 fields
      "limit": limit,  # retrieve 50 products at a time
      "offset": offset  # set the offset to paginate the results
    }
    # Call the products API
    response = requests.post(
      "https://apis.supplierxm.salsify.com/public/v1/products/list",
      data=json.dumps(filter_payload),
      headers=headers  # previously set with authentication token
    )
    nb_products_retrieved += len(response.json()['data'])
    offset += limit

    # Process your products' data here
    print('%r products processed' % nb_products_retrieved)
else:
  limit = 500
  while nb_products_retrieved < nb_products:
    # Get products
    filter_payload = {
      "filter_source_include": ["gtin", "nameLegal"],  # retrieve only 2 fields
      "next_page": next_page,  # on the first call, set next_page to "", on the following calls, pass the next_page parameter with the value returned by the previous call 
      "limit": limit,  # retrieve 500 products at a time
    }
    # Call the products API
    response = requests.post(
      "https://apis.supplierxm.salsify.com/public/v1/products/list",
      data=json.dumps(filter_payload),
      headers=headers  # previously set with authentication token
    )
    nb_products_retrieved += len(response.json()['data'])
    next_page = response.json()['next_page']

    # Process your products' data here
    print('%r products processed' % nb_products_retrieved)

Set the language

By default, every labels in the payload are in US English.

To retrieve the labels in another language, you have to add the parameter accept-language in the header of your request.

The value of this parameter is a 2 letter base language tag that indicates a language, optionally followed by additional subtags separated by '-'. For example, if you want to retrieve the labels in UK English, you will use en-UK.

--header 'Accept-language: en-UK'

For French, it will be fr-FR.

Retrieve assets

All media information can be retrieved in the payload in the "assets" key.
It contains information for each media type:

  • Images information are in the pictures key
  • Document information is in the document key
  • Video information is in the videos key

For each media, metadata are provided to describe it: angle, face, tags, main picture, etc…

Link to media documentation: Media assets

Retrieve logistical hierarchies

The logistical hierarchies can be retrieved by looping through the logisticalHierarchies array. All the logistical hierarchies which have the attribute activeListing set to true are the logistical hierarchies shared via a listing. This means they can be found in the sharingUnits array. Also, they can be identified via their product_key_id attribute. The other ones are the logistical hierarchies that are not referenced anymore.

API References

public/v1/products: Retrieve Products