0

I'm currently working on fetching customer data from cdon, it's an e-commerce platform. They have their API documentation here:

CDON Api Docu

First let me show you my code:

myToken = '<token here>'
myUrl = 'https://admin.marketplace.cdon.com/api/reports/d8578ef8-723d-46cb-bb08-af8c9b5cca4c'
head = {'Authorization': 'token {}'.format(myToken),
'Status':'Online',
'format':'json'}
filters = '?filter={"Status":["Online"],"format": ["json"] }}'
response = requests.get(myUrl + filters, headers=head)
report = response.json()
print(report.products)

This is returning only the parameters. like for example at at this JSON: CDON Github

Status has a value Online this online is a group of itemsthat I only want to get.

What I'm trying to get is a response like this:

{

  "Products": [

    {

      "SKU": "322352",

      "Title": "Fabric Cover",

      "GTIN": "532523626",

      "ManufacturerArticleNumber": "",

      "StatusCDON": "Online",

      "ExposeStatusCDON": "Buyable",

      "InStock": 0,

      "InStockCDON": 0,

      "CurrentPriceSE": null,

      "OrdinaryPriceSE": null,

      "CurrentPriceCDONSE": 299.0000,

      "OrdinaryPriceCDONSE": null,

      "CurrentPriceDK": null,

      "OrdinaryPriceDK": null,

      "CurrentPriceCDONDK": null,

      "OrdinaryPriceCDONDK": null,

      "CurrentPriceNO": null,

      "OrdinaryPriceNO": null,

      "CurrentPriceCDONNO": null,

      "OrdinaryPriceCDONNO": null,

      "CurrentPriceFI": null,

      "OrdinaryPriceFI": null,

      "CurrentPriceCDONFI": null,

      "OrdinaryPriceCDONFI": null

    },

Which means the full list of the items that are Online

How should I put this... among all the API's I tried this one is very confusing, is this even RestFul? If I can achieve the python equivalent of this C# sample code:

public string Post(Guid repordId, string path)
{
  var filter = new JavaScriptSerializer().Serialize(new
  {
         States = new[] { "0" } // Pending state
  });

  var content = new FormUrlEncodedContent(new[]
  {
         new KeyValuePair("ReportId", repordId.ToString()),
         new KeyValuePair("format", "json"),
         new KeyValuePair("filter", filter)
  });

  var httpClient = new HttpClient() { BaseAddress = new Uri("https://admin.marketplace.cdon.com/") };
  httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("api", ApiKey);
  var response = httpClient.PostAsync(path, content).Result;
  response.EnsureSuccessStatusCode();

  return response.Content.ReadAsStringAsync().Result;
}

I may be able to undestand how this API works, the response that I got was taken manually from their report function in JSON format.

Image

I made many attempts and at that code ( my code ) I stopped, being on this for 4 hours made me give up and ask. Trust that I have searched as many references as I could. It's really confusing.

How do I get the response that I want? Filtering via url? or via header? is this even restful? Help T_T

btslove
  • 11
  • 1
  • 3
  • Possible duplicate of [Making a request to a RESTful API using python](https://stackoverflow.com/questions/17301938/making-a-request-to-a-restful-api-using-python) – Tomalak Jun 10 '18 at 11:46

1 Answers1

0

The documentation states in the first line, emphasis mine:

In order to generate a report you perform a POST call to the reports API with the parameters you wish to use for the report.

Your Python code does not make a POST request, you are trying a GET request. The documentation goes on

[...] to filter on Swedish orders you set the CountryCodes attribute to “Sweden” and to get returned and cancelled orders you set the States attribute to 2 and 3. So in the end the filter would look like this:

{
    "CountryCodes": [ "Sweden" ],
    "States": ["2", "3"]
}

So you need to prepare a filter object (a dictionary in Python) with the filters you want. Luckily the Python syntax for dictionaries is equivalent (Python is flexible and also allows single-quoted strings):

filter = {
    'CountryCodes': [ 'Sweden' ],
    'States': [ '0' ]
}

The documentation goes on

You then post the parameters as form data (content-type: application/x-www-form-urlencoded) so the request body would look like this:

ReportId=d4ea173d-bfbc-48f5-b121-60f1a5d35a34&format=json&filter={"CountryCodes":["Sweden"],"States":["2","3"]}

application/x-www-form-urlencoded is the default for HTTP post, the requests module knows that and does this for you automatically. All you need to do is to prepare a data dict which will contain the data you want to post.

data = {
    'ReportId': 'd4ea173d-bfbc-48f5-b121-60f1a5d35a34',
    'format': 'json'
    'filter': json.dumps(filter)
}

The filter parameter is supposed to be in JSON format. You must encode that yourself via json.dumps().

import json

head = { ... as above }
filter = { ... as above }
data = { ... as above }

response = requests.post(url, data, header=head)

I'll leave figuring out setting the Authorization header properly as an exercise for you. Partly because it isn't hard, partly because I have no intention of creating an API key with this website just for testing this and partly because it's entirely possible that your current header already works.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
  • Thank you very much, really understood your explanation. I guess next time I should read more before diving more. – btslove Jun 10 '18 at 12:29
  • I hope you get the header to work, too! The main take-away should be: Always work with the data structures that are native to your programming language. In case of Python the basic ones are *dicts* and *lists*. Converting those data structures to URL-encoded format or JSON format is very easy, and HTTP libraries normally do it all for you. Never try to build query strings or JSON manually, like you did with your `filters` variable - this is inflexible, error-prone and typically also harder than using built-in facilities like `json.dumps()` – Tomalak Jun 10 '18 at 12:47
  • I made it work, but my im working on the filters, it says invalid, {'Message': 'Invalid filter'} but yeah, I'm close, maybe its the paramters that are wrong or the syntax perhaps. Even with the syntax you have shown its showing invalid. I have postfields `'Statuses'` which has Values with displaynames `Online` and `Offline` I try fetching it via `{'Statuses':['Online']}` but still in valid – btslove Jun 10 '18 at 19:17
  • "Invalid filter" doesn't sound too bad, should be easy to fix now that the server is talking to you. I'm pretty sure it's `States` and not `Statuses`, but the docs will explain how the filter is supposed to look like, go over them again. – Tomalak Jun 11 '18 at 06:48