amz-tools / amazon-sp-api

Amazon Selling Partner API Client
MIT License
237 stars 121 forks source link

putListingsItem example, to create/update offer for an ASIN #68

Open IonicaBizau opened 2 years ago

IonicaBizau commented 2 years ago

I am trying to use the putListingsItem operation which was added by @altruer in amzn/selling-partner-api-models#724.

const res = await sellingPartner.callAPI({
  operation: "putListingsItem",
  endpoint: "listingsItems",
  path: {
    sellerId: process.env.AMAZON_SELLER_ID,
    sku: PRODUCT_SKU
  },
  query: {
    marketplaceIds: [MARKETPLACE_ID],
  },
  body: {
    productType: "COMPUTER_DRIVE_OR_STORAGE",
    requirements: "LISTING_OFFER_ONLY",
    attributes: {
      "condition_type": [{
        "value": "new_new",
        "marketplace_id": MARKETPLACE_ID
      }],
      "external_product_id": [{
        "value": "B07FP5L3ZQ", // < This is the ASIN
        "marketplace_id": MARKETPLACE_ID
      }],
      "external_product_type": [{
        "value": "ASIN",
        "marketplace_id": MARKETPLACE_ID
      }],
    }
  }
})

The error I am getting is:

...
{ message: 'The attributes are invalid.',
severity: 'ERROR',
attributeName: 'item_sku' }
...

Any help on this would be highly appreciated.

altruer-old commented 2 years ago

Don't see any docs about how attributes should look like But in attributes Amazon returns via GET request there is no item_sku field

IonicaBizau commented 2 years ago

I just thought I should follow the same fields like in the spreadsheet used to upload the data to Amazon.

Indeed, the docs are very unclear... Any ideas whom we should ask for docs/solution, @altruer?

I have been trying to contact Amazon support and they only sent me canned/generated responses which is frustrating... 😭

altruer-old commented 2 years ago

Let's wait for their answers, we can try to check different body alternatives, but it sound like reverse engineering😀

IonicaBizau commented 2 years ago

@amz-tools Any help on this would be really welcome... It has been a couple of weeks/months since I am have been struggling with this.

amz-tools commented 2 years ago

@IonicaBizau, @altruer

Haven't worked with it yet, but some things that might be helpful if you haven't already checked that. First of all there's a Listings Items Guide that might be helpful.

Then there's the productTypeDefinitions endpoint, which will return a link to the schema which is quite extensive, but should be very helpful in finding the right structure to pass.

In order to get the schema link for the example above you would call it like this:

let res = await sellingPartner.callAPI({
  operation:'productTypeDefinitions.getDefinitionsProductType',
  path:{
    productType:'COMPUTER_DRIVE_OR_STORAGE'
  },
  query:{
    sellerId:process.env.AMAZON_SELLER_ID,
    requirements:'LISTING_OFFER_ONLY',
    marketplaceIds:[MARKETPLACE_ID]
  }
});

At least for us, when I search the schema, I can't find external_product_id or external_product_type as values, only something called externally_assigned_product_identifier.

IonicaBizau commented 2 years ago

That was helpful to see the schema, but I am still wondering how to pass the ASIN that we want to pot the offer for. Any ideas on that? In the spreadsheet it would be under the external_product_id column.

IonicaBizau commented 2 years ago

Even the item_name which appears in the example from the docs it not present in the schema...

Btw, thanks for adding the getDefinitionsProductType! The schema helps a lot.

amz-tools commented 2 years ago

@IonicaBizau,

if I read the schema of getDefinitionsProductType right the ASIN must be passed as merchant_suggested_asin. As an alternative to the ASIN you could use one of UPC/EAN/GTIN as externally_assigned_product_identifier. But either merchant_suggested_asin or externally_assigned_product_identifier must be used as an identifier.

IonicaBizau commented 2 years ago

Exactly! This is the almost working version of the code, which actually creates the offer, but the country of origin is incomplete. I am not sure if that is required, but the offer is marked as Incomplete/Inactive in the inventory:

const res = await sellingPartner.callAPI({
  operation: "putListingsItem",
  endpoint: "listingsItems",
  path: {
    sellerId: process.env.AMAZON_SELLER_ID,
    sku: "581286-B21-7-3"
  },
  query: {
    marketplaceIds: ['A1F83G8C2ARO7P'],
  },
  body: {
    productType: "COMPUTER_DRIVE_OR_STORAGE",
    requirements: "LISTING_OFFER_ONLY",
    attributes: {
      merchant_suggested_asin: [{
        "value": "B07FP5L3ZQ",
        "marketplace_id": MARKETPLACE_ID
      }],
      "condition_type": [{
        "value": "used_like_new",
        "marketplace_id": MARKETPLACE_ID
      }],
      "purchasable_offer": [{
        "currency": "GBP",
        "our_price": [{
          "schedule": [{
            "value_with_tax": 74.98
          }]
        }],
        "marketplace_id": MARKETPLACE_ID
      }],
      "fulfillment_availability": [{
        "fulfillment_channel_code": "DEFAULT",
        quantity: 7
      }]
    }
  }
})

I also tried the tutorial using the feeds api, and have the same problem: how to pass the country of origin in the flat file?

amz-tools commented 2 years ago

Not quite sure if "DEFAULT" really is a valid fulfillment_channel_code. Have you tried AMAZON_EU (if UK stilll counts as EU :-) )? If you do FBM instead of FBA then the description says the fulfillment_channel_code should be left empty...whatever thats supposed to mean. Empty string? Or skipping the field completely?

IonicaBizau commented 2 years ago

@amz-tools The country of origin refers to where the product was made from what I understand (so it can be, let's say, China). I am not quite sure if it required at all, but even with DEFAULT, the country of origin is not filled into the product form.

The schema dictates that the fulfillment_channel_code field is required and mentions the DEFAULT value.

Do you have experience of updating the inventory in Amazon either using putListItem or the feeds API, without user interaction (e.g. approval request etc)? That is what I am trying to do and if possible, it would be great to connect to help me.


        "fulfillment_availability": {
            "type": "array",
            "minItems": 1,
            "minUniqueItems": 1,
            "maxUniqueItems": 1,
            "selectors": ["fulfillment_channel_code"],
            "items": {
                "type": "object",
                "required": ["fulfillment_channel_code"],
                "properties": {
                    "fulfillment_channel_code": {
                        "$comment": "For those merchants using Amazon fulfillment services, this designates which fulfillment network will be used. Specifying a value other than DEFAULT will cancel the Merchant-fulfilled offering.",
                        "title": "Fulfillment Channel Code",
                        "description": "For those merchants using Amazon fulfillment services, this designates which fulfillment network will be used. Specifying a value other than DEFAULT will cancel the Merchant-fulfilled offering.",
                        "editable": true,
                        "hidden": false,
                        "examples": ["AMAZON_NA"],
                        "type": "string"
                    },
                    "is_inventory_available": {
                        "$comment": "If true the SKU is always available. If false the SKU is not available.",
                        "title": "Inventory Available",
                        "description": "If true the SKU is always available. If false the SKU is not available.",
                        "editable": true,
                        "hidden": false,
                        "examples": ["True"],
                        "type": "boolean",
                        "enum": [true, false],
                        "enumNames": ["Yes", "No"]
                    },
                    "lead_time_to_ship_max_days": {
                        "$comment": "Indicates the time, in days, between when you receive an order for an item and when you can ship the item.",
                        "title": "Handling Time",
                        "description": "Provide the time, in days, between when you receive an order for an item and when you can ship the item",
                        "editable": true,
                        "hidden": false,
                        "examples": ["5"],
                        "type": "integer"
                    },
                    "quantity": {
                        "$comment": "Enter the quantity of the item you are making available for sale. This is your current inventory commitment (as a whole number)",
                        "title": "Quantity",
                        "description": "Enter the quantity of the item you are making available for sale. This is your current inventory commitment (as a whole number)",
                        "editable": true,
                        "hidden": false,
                        "examples": ["152"],
                        "type": "integer"
                    },
                    "restock_date": {
                        "$comment": "Date that product will be restocked",
                        "title": "Restock Date",
                        "description": "Date that product will be restocked",
                        "editable": true,
                        "hidden": false,
                        "examples": ["5/5/20"],
                        "type": "string",
                        "oneOf": [{
                            "type": "string",
                            "format": "date"
                        }, {
                            "type": "string",
                            "format": "date-time"
                        }]
                    }
                },
                "additionalProperties": false
            }
        },
amz-tools commented 2 years ago

@IonicaBizau We are not yet using the listingsItem operations, but we do use the feeds operations to update various things like quantities, but I am not aware of what exactly we are updating via feeds. I would have to ask in our team what exactly is being updated, but I am sure it doesn't require additional user interaction.

We are planning to have a closer look at the listingsItem operations and see what feeds operations can be replaced by it, but for now I am afraid we are not too much into it in order to help.

Maybe there's somebody else around here who is already using the listingsItem endpoint and got it working?

amz-tools commented 2 years ago

@IonicaBizau Two more things that just came to me: Are you having the write permissions for the ASIN you are trying to update? And is maybe patchListingsItem what you want to use instead of putListingsItem? I just saw that putListingsItem creates or fully updates a listing, whereas patchListingsItem allows you to only update some parts of it.

This looks like a decent example: https://github.com/amzn/selling-partner-api-models/issues/2061

Roman991 commented 1 year ago
...
attributes: {
          country_of_origin: [
            {
              value: 'UK',
              marketplace_id: MARKETPLACE_ID,
            },
          ],
...

btw the new items are created only as DISCOVERABLE and not BUYABLE ....

Edogusma commented 1 year ago

This attribute is invalid:

...
"external_product_type": [{
        "value": "ASIN",
        "marketplace_id": MARKETPLACE_ID
 }]
...

"external_product_id" is defined as:

...
"external_product_id": [{
      "value": "B07FP5L3ZQ", 
      "type": "asin", // < Identifier MUST be lowercase
      "marketplace_id": MARKETPLACE_ID
 }]
...

with "type" property required.

jawagalsrinath commented 8 months ago

is that any one is familiar with how to convert one JSON to another JSON structure in TypeScript