Adding Products to Your eBay Store with the Trading API

Share this article

In this third and final part of our eBay Trading API series, we’ll be building the product adding functionality into our application.

Creating new Products

Now that we’re done with the store settings, we can begin with writing the code for the controller that would handle the creation of products. Under the controllers directory, create a new file and name it Product.php.

<?php
class Product extends \SlimController\SlimController{
    
}

Next, create the newAction method. This will render the new.twig file under the templates/product directory. This is the view that renders the form for creating new products.

public function newAction(){   
    $page_data = array(
        'is_productpage' => 'true'
    );
    $this->render('product/new', $page_data);       
}

Next create the view:

{% extends "/base.twig" %}
{% block content %}
{{ parent() }}
<div class="row">
  <div class="col-md-4">  
    <div class="alert alert-{{ flash.message.type }}">
      {{ flash.message.text }}

      {% for r in flash.message.data %}
      <li>{{ r[0] }}</li>
      {% endfor %}
    </div>
  </div>
</div>
<div class="row">
  <div class="col-md-6">
    <form class="form-horizontal" method="POST" action="{{ baseUrl }}/products/create">
      <fieldset>
        <legend>Create new Product</legend>
        <div class="form-group">
          <label for="title" class="col-lg-2 control-label">Title</label>
          <div class="col-lg-10">
            <input type="text" class="form-control" id="title" name="title" value="{{ flash.form.title }}">
          </div>
        </div>
        <div class="form-group">
          <label for="category" class="col-lg-2 control-label">Category</label>
          <div class="col-lg-10" id="categories-container">
            
          </div>
        </div>
        <div class="form-group">
          <label for="price" class="col-lg-2 control-label">Price</label>
          <div class="col-lg-10">
            <input type="text" class="form-control" id="price" name="price" value="{{ flash.form.price }}">
          </div>
        </div>
        <div class="form-group">
          <label for="quantity" class="col-lg-2 control-label">Quantity</label>
          <div class="col-lg-10">
            <input type="text" class="form-control" id="quantity" name="quantity" value="{{ flash.form.quantity }}">
          </div>
        </div>      
        <div class="form-group">
          <label for="brand" class="col-lg-2 control-label">Brand</label>
          <div class="col-lg-10">
            <input type="text" class="form-control" id="brand" name="brand" value="{{ flash.form.brand }}">
          </div>
        </div>
        <div class="form-group">
          <label for="description" class="col-lg-2 control-label">Description</label>
          <div class="col-lg-10">
            <textarea class="form-control" rows="3" id="description" name="description" value="{{ flash.form.description }}">{{ flash.form.description }}</textarea>
          </div>
        </div>
        
        <div class="form-group">
          <div class="col-lg-10 col-lg-offset-2">
            <button type="submit" class="btn btn-primary">Add Product</button>
          </div>
        </div>
      </fieldset>
    </form>
  </div>

  <div class="col-md-6">
    <h5>Upload Photos</h5>
    <form action="{{ baseUrl }}/upload" method="POST" class="dropzone" id="photosdropzone" enctype="multipart/form-data"></form>
  </div>
</div>


{% include 'partials/categories.html' %}
{% endblock %}

Breaking it down, at the beginning is where we output the alert message. We’ll pass along the values for this later on when we add the code for creating products. flash is a global variable where session data that we pass along is temporarily saved:

<div class="alert alert-{{ flash.message.type }}">
    {{ flash.message.text }}
    {% for r in flash.message.data %}
    <li>{{ r[0] }}</li>
    {% endfor %}
</div>

Next is the product title and other required product details. Take note that only the product title, description, quantity, price, and a product image are required in most cases. Here, we’ve added brand because in some cases it’s required. The general term for this kind of field is a conditional field. It usually depends on the category of the product whether it’s required or not. Some categories require more fields than others so be sure to check the documentation on the AddItem API Call to make sure you’re not missing anything.

<input type="text" class="form-control" id="title" name="title" value="{{ flash.form.title }}">

For the product category, we’re going to load it later on via AJAX since it will depend on the product title entered by the user.

<label for="category" class="col-lg-2 control-label">Category</label>
<div class="col-lg-10" id="categories-container">
                
</div>

Next is the form that the user will use for uploading the product images:

<form action="{{ baseUrl }}/upload" method="POST" class="dropzone" id="photosdropzone" enctype="multipart/form-data"></form>

This uses the /upload route for processing the uploaded files. Declare the method for processing this route in the Product class:

public function uploadAction(){

    $storage = new \Upload\Storage\FileSystem('uploads');
    $file = new \Upload\File('file', $storage);

    $new_filename = uniqid();
    $file->setName($new_filename);

    $_SESSION['uploads'][] = $new_filename . '.' . $file->getExtension();

    $file->addValidations(array(
        new \Upload\Validation\Mimetype(array('image/png', 'image/gif', 'image/jpg')),
        new \Upload\Validation\Size('6M')
    ));

    $errors = array();

    try{
        $file->upload();
    }catch(Exception $e){
        $errors = $file->getErrors();
    }

    $response_data = array(
        'errors' => $errors
    );

    echo json_encode($response_data);

}

Breaking the uploadAction() method down, first we specify the upload path. In this case we’re using the uploads directory. Make sure you give it the necessary directory permissions so we can actually upload files to it:

$storage = new \Upload\Storage\FileSystem('uploads');

Next, we specify the field we use for uploading files. Going back to the form for uploading, we didn’t specify any <input type="file"> fields in there. That’s because we don’t need to. By default dropzone uses file as the default field name for uploading files so we specify it as the first argument for the File method, the second argument is the storage which we created earlier:

$file = new \Upload\File('file', $storage);

Next, we give the file a unique name. You can be creative here if you want, but if you’re not feeling creative then just use the uniqid() method to generate a unique file name:

$new_filename = uniqid();
$file->setName($new_filename);

Push the file name into the uploads session item so we can use it later on.

$_SESSION['uploads'][] = $new_filename . '.' . $file->getExtension();

Next, we add some file validation. We just tell it to only accept png, gif, and jpg images, and the max file size should only be 6Mb.

$file->addValidations(array(
        new \Upload\Validation\Mimetype(array('image/png', 'image/gif', 'image/jpg')),
        new \Upload\Validation\Size('6M')
    ));

Lastly, we try to upload the file and assign any errors we get and return them to the client side. But we won’t really be making use of this error on the client side since dropzone already has us covered. It displays an x mark for the uploaded file if the file didn’t pass the validation:

$errors = array();

try{
  $file->upload();
}catch(Exception $e){
  $errors = $file->getErrors();
}

$response_data = array(
  'errors' => $errors
);

echo json_encode($response_data);

Going back to the template for adding new products, we include a partial. This is the template that will be used for showing the suggested product categories.

{% include 'partials/categories.html' %}

It contains the following:

{% raw %}
<script id="categories-template" type="text/x-handlebars-template">
{{#each categories}}
<div class="radio">
  <label>
    <input type="radio" name="category_id" id="category_id" value="{{id}}">
    {{name}}
  </label>
</div>
{{/each}}
</script>
{% endraw %}

In the above template, we’re using Handlebars. Its syntax collides with twig syntax so we have to wrap it in {% raw %} tags to make sure twig doesn’t parse it.

Next, create the dropzone-options.js file under the /assets/js directory and add the following:

(function(){

  Dropzone.options.photosdropzone = {

    acceptedFiles: "image/*",
    autoProcessQueue: true,
    uploadMultiple: false,
    maxFiles: 5
  };

})();

That allows us to specify the options for the dropzone. Here’s a breakdown of each option:

  • acceptedFiles – the type of file that can be uploaded.
  • autoProcessQueue – a boolean value for specifying whether to process the queue immediately or not.
  • uploadMultiple – a boolean value for specifying whether to allow multiple file uploads. In this case we selected false but it doesn’t mean we can’t upload more than one image. It means that we can’t upload more than one image at the same time.
  • maxFiles – an integer value for specifying the max number of files which can be uploaded.

Next, create the new-product.js file and add the following:

(function(){
  var categories_template = Handlebars.compile($("#categories-template").html());

  $('#title').blur(function(){
    var title = $(this).val();
    $.post(
      '/tester/ebay_trading_api/categories', 
      {
        'title' : title
      },
      function(response){
        var categories = JSON.parse(response);
        var html = categories_template({'categories' : categories});
        
        $('#categories-container').html(html);
      }
    );
  });
})();

What the code above does is make a POST request every time the user tabs out of the product title field. The request then returns an array of objects containing the suggested categories based on the product title. The method which is used in this call is in the Product class. What it does is call the getSuggestedCategories() method in the Ebay class, passing in the product title as the argument. The response is then converted into a JSON string and echoed out:

public function categoriesAction(){
    $suggested_categories = $this->app->ebay->getSuggestedCategories($_POST['title']);
    echo json_encode($suggested_categories);
}

Open up the Ebay class and add the following method:

public function getSuggestedCategories($title){

  $requestBody = '<?xml version="1.0" encoding="utf-8"?>
    <GetSuggestedCategoriesRequest xmlns="urn:ebay:apis:eBLBaseComponents">
    <RequesterCredentials>
        <eBayAuthToken>' . $this->user_token . '</eBayAuthToken>
      </RequesterCredentials>
      <Query>' . $title . '</Query>
    </GetSuggestedCategoriesRequest>';

  $response = $this->request('GetSuggestedCategories', $requestBody);

  $suggested_categories = array();
  if($response->Ack == 'Success'){

    foreach($response->SuggestedCategoryArray->SuggestedCategory as $category){
      $suggested_categories[] = array(
        'id' => json_decode(json_encode($category->Category->CategoryID), true)[0],
        'name' => json_decode(json_encode($category->Category->CategoryName), true)[0]
      );
    }
  }

  return $suggested_categories;
}

What the method above does is make a request to the GetSuggestedCategories API method. This call accepts the product title as its argument, as passed in the Query field. If the call is successful, it returns an array of suggested categories. We just need to extract the category id and category name from the result it returns.

Now we’re ready to write the createAction method. This is where we save the product details into the database and create the product on ebay.

public function createAction(){
    
    $v = new Valitron\Validator($_POST);
    $v->rule('required', array('title', 'category_id', 'price', 'quantity', 'brand', 'description'));
    $v->rule('numeric', 'price');
    $v->rule('integer', 'quantity');
    if($v->validate()){
       
        if($query = $this->app->db->prepare("INSERT INTO products SET title = ?, category_id = ?, price = ?, qty = ?, brand = ?, description = ?")){

            $store_settings_result = $this->app->db->query("SELECT payment_profile, return_profile, shipping_profile, out_of_stock_control, get_it_fast, category_prefill,
                category_mapping, condition_type, country_code_type, currency_code, dispatch_time, optimal_picturesize,
                listing_duration, listing_type, item_location, postal_code, store_name, county,
                street, ebay_website, shippingservice_priority, shipping_service, shippingservice_cost, shippingservice_additionalcost
                FROM store_settings WHERE id = 1");
            $store_settings = $store_settings_result->fetch_object();

            $response = $this->app->ebay->addItem($store_settings, $_POST);

            if($response->Ack == 'Success'){

                $title = $_POST['title'];
                $category_id = $_POST['category_id'];
                $price = $_POST['price'];
                $qty = $_POST['quantity'];
                $brand = $_POST['brand'];
                $description = $_POST['description'];

                $query->bind_param("ssdiss", $title, $category_id, $price, $qty, $brand, $description);
                $query->execute();

                $this->app->flash('message', array('type' => 'success', 'text' => 'Product was created!'));
            }else{

                $long_message = json_decode(json_encode($response->Errors->LongMessage), true);
                $this->app->flash('message', array('type' => 'danger', 'text' => $long_message[0]));

            }

        }
        
        
    }else{
        
        $this->app->flash('form', $_POST);
        $this->app->flash('message', array(
            'type' => 'danger', 
            'text' => 'Please fix the following errors', 
            'data' => $v->errors())
        );
        
    }  

    $this->app->redirect('/tester/ebay_trading_api/products/new'); 
}

Breaking it down. First, we declare a new instance of valitron, passing in all the values that are currently stored in the $_POST global variable:

$v = new Valitron\Validator($_POST);

Next we add the rules. Basically all the fields are required, the price should be a numeric value, and the quantity should be an integer. We specified that using the rule method which takes up the actual rule as the first argument, and the name of the field as the second argument:

$v->rule('required', array('title', 'price', 'quantity', 'brand', 'description'));
$v->rule('numeric', 'price');
$v->rule('integer', 'quantity');

Next we validate using the validate() method. If this returns true then the validation passed, otherwise it didn’t. If it returns false then we take all the POST data and save it into the session along with the error messages returned by valitron.

$this->app->flash('form', $_POST);
$this->app->flash('message', array(
  'type' => 'danger', 
  'text' => 'Please fix the following errors', 
  'data' => $v->errors())
);

If the validation passes, we retrieve the store settings from the database and supply them as an argument for the addItem() method along with the contents of the $_POST variable. The addItem() method creates the product on eBay. If the call is successful, we create a prepared statement for adding the details of the product in the database. Once that’s done we flash a message into the session saying that the product was created. If the call is not successful then we pass the response returned from the API along with a message that the product was not created.

$store_settings_result = $this->app->db->query("SELECT payment_profile, return_profile, shipping_profile, out_of_stock_control, get_it_fast, category_prefill,
    category_mapping, condition_type, country_code_type, currency_code, dispatch_time, optimal_picturesize,
    listing_duration, listing_type, item_location, postal_code, store_name, county,
    street, ebay_website, shippingservice_priority, shipping_service, shippingservice_cost, shippingservice_additionalcost
    FROM store_settings WHERE id = 1");
$store_settings = $store_settings_result->fetch_object();

$response = $this->app->ebay->addItem($store_settings, $_POST);

if($response->Ack == 'Success'){

    if($query = $this->app->db->prepare("INSERT INTO products SET title = ?, category_id = ?, price = ?, qty = ?, brand = ?, description = ?")){

        $title = $_POST['title'];
        $category_id = $_POST['category_id'];
        $price = $_POST['price'];
        $qty = $_POST['quantity'];
        $brand = $_POST['brand'];
        $description = $_POST['description'];

        $query->bind_param("ssdiss", $title, $category_id, $price, $qty, $brand, $description);
        $query->execute();

    }

    $this->app->flash('message', array('type' => 'success', 'text' => 'Product was created!'));
}else{
    $this->app->flash('message', array('type' => 'danger', 'response' => $response, 'text' => 'Product was not created!'));
}

$this->app->redirect('/tester/ebay_trading_api/products/new');

Next, we’ll define the addItem method in the Ebay class. Define 2 parameters: $store_settings and $item_data. Inside the method declare a variable called $boolean_value. This allows us to convert the integer value 0 to a string false and the integer value 1 to a string true. We need this because the API only accepts either true or false for boolean parameters.

Next, assign the uploads session item to a variable. If you remember from earlier, this session item is where we pushed the filenames of the images that the user uploaded. Next is the $baseupload_url, this contains the base URL in which all uploaded images can be found. We need this because the UploadSiteHostedPictures API method only accepts a URL for uploading to ebay. This also means that you need to have an actual server that’s accessible via public internet. The UploadSiteHostedPictures method only accepts a single URL at a time so we have to loop through all the images and supply the actual URL as the value for the ExternalPictureURL field. If the request is successful we just append the new image URL that’s returned to the $picture_details variable. This will be used as one of the arguments passed to the call for actually creating the product on eBay.

Next, we make the request for adding the product to eBay. This can be done via either the AddItem method or the VerifyAddItem method. The AddItem method is the one that you would want in production, since it adds the product to ebay. If there are any fees, those are also applied. VerifyAddItem on the other hand acts like a sandbox method, it doesn’t actually add the item on ebay. You can use it if you want to test the AddItem call. No fees are applied when you call it, but it lets you know how much of a fee will be applied or if the request would actually be successful. Note that you don’t need to use the sandbox version of the API in order to call the VerifyAddItem method. You can use it even on the live version of the API.

public function addItem($store_settings, $item_data){

  $boolean_value = array('false', 'true');

  $product_images = $_SESSION['uploads'];

  $baseupload_url = 'http://somewhere.com/uploads/';

  $picture_details = '';
  if(!empty($product_images)){
    foreach($product_images as $img){

      $requestBody = '<?xml version="1.0" encoding="utf-8"?>
      <UploadSiteHostedPicturesRequest xmlns="urn:ebay:apis:eBLBaseComponents">
        <RequesterCredentials>
          <eBayAuthToken>' . $this->user_token . '</eBayAuthToken>
        </RequesterCredentials>
        <ExternalPictureURL>' . $baseupload_url . '' . $img . '</ExternalPictureURL>
      </UploadSiteHostedPicturesRequest>';


      $response = $this->request('UploadSiteHostedPictures', $requestBody);
      
      if(!empty($response->Ack) && $response->Ack != 'Failure'){
        $uploaded_img = json_decode(json_encode($response->SiteHostedPictureDetails->PictureSetMember[3]->MemberURL), true);
        $picture_details .= '<PictureURL>' . $uploaded_img[0] . '</PictureURL>';
      }
    }   
  }
  
  $requestBody = '<?xml version="1.0" encoding="utf-8"?>
    <AddItemRequest xmlns="urn:ebay:apis:eBLBaseComponents">
      <RequesterCredentials>
        <eBayAuthToken>' . $this->user_token . '</eBayAuthToken>
      </RequesterCredentials>
      <Item>
        <SellerProfiles> 
          <SellerPaymentProfile>
            <PaymentProfileID>' . $store_settings->payment_profile . '</PaymentProfileID>
          </SellerPaymentProfile>
          <SellerReturnProfile>
            <ReturnProfileID>' . $store_settings->return_profile . '</ReturnProfileID>
          </SellerReturnProfile>
          <SellerShippingProfile>
            <ShippingProfileID>' . $store_settings->shipping_profile . '</ShippingProfileID>
          </SellerShippingProfile>
        </SellerProfiles> 
        <OutOfStockControl>' . $store_settings->out_of_stock_control . '</OutOfStockControl>
        <GetItFast>' . $boolean_value[$store_settings->get_it_fast] . '</GetItFast>
        <CategoryBasedAttributesPrefill>' . $boolean_value[$store_settings->category_prefill] . '</CategoryBasedAttributesPrefill>
        <CategoryMappingAllowed>' . $boolean_value[$store_settings->category_mapping] . '</CategoryMappingAllowed>
        <ConditionID>' . $store_settings->condition_type . '</ConditionID>
        <Country>' . $store_settings->country_code_type . '</Country>
        <Currency>' . $store_settings->currency_code . '</Currency>
        <Description>' . $item_data['description'] . '</Description>
        <DispatchTimeMax>' . $store_settings->dispatch_time . '</DispatchTimeMax>
        <ListingDesigner>
          <OptimalPictureSize>' . $boolean_value[$store_settings->optimal_picturesize] . '</OptimalPictureSize>
        </ListingDesigner> 
        <ListingDuration>' . $store_settings->listing_duration . '</ListingDuration>
        <ListingType>' . $store_settings->listing_type . '</ListingType>
        <Location>' . $store_settings->item_location . '</Location>
        <PictureDetails>'
          . $picture_details . 
        '</PictureDetails>
        <PostalCode>' . $store_settings->postal_code . '</PostalCode>
        <PrimaryCategory>
          <CategoryID>' . $item_data['category_id'] . '</CategoryID>
        </PrimaryCategory>
        <Quantity>' . $item_data['quantity'] . '</Quantity>
        <SellerContactDetails>
          <CompanyName>' . $store_settings->store_name . '</CompanyName>
          <County>' . $store_settings->county . '</County>
          <Street>' . $store_settings->street . '</Street>
        </SellerContactDetails>
        <Site>' . $store_settings->ebay_website . '</Site>
        <StartPrice currencyID="' . $store_settings->currency_code . '">' . $item_data['price'] . '</StartPrice>
        <Title>' . $item_data['title'] . '</Title>
        <ShippingDetails>
        <ShippingServiceOptions>
          <ShippingServicePriority>' . $store_settings->shippingservice_priority . '</ShippingServicePriority>
          <ShippingService>' . $store_settings->shipping_service . '</ShippingService>
          <ShippingServiceCost currencyID="' . $store_settings->currency_code . '">' . $store_settings->shippingservice_cost . '</ShippingServiceCost>
          <ShippingServiceAdditionalCost currencyID="' . $store_settings->currency_code . '">' . $store_settings->shippingservice_additionalcost . '</ShippingServiceAdditionalCost>
        </ShippingServiceOptions>
        </ShippingDetails>
      </Item>
    </AddItemRequest>';

  $response = $this->request('AddItem', $requestBody);

  return $response; 
  
}

To make things clearer, here’s a breakdown of the parameters we passed to the AddItem request. Here we’re passing in the seller profiles. The only requirement for each seller profile is the profile ID. We already got those earlier when we fetched the store settings, so we simply get them from the database.

<SellerProfiles> 
  <SellerPaymentProfile>
    <PaymentProfileID>' . $store_settings->payment_profile . '</PaymentProfileID>
  </SellerPaymentProfile>
  <SellerReturnProfile>
    <ReturnProfileID>' . $store_settings->return_profile . '</ReturnProfileID>
  </SellerReturnProfile>
  <SellerShippingProfile>
    <ShippingProfileID>' . $store_settings->shipping_profile . '</ShippingProfileID>
  </SellerShippingProfile>
</SellerProfiles>

OutOfStockControl is a boolean value for specifying whether to keep the listing alive after it reaches a quantity of 0. Setting this to true excludes the listing from search results and from being viewed.

<OutOfStockControl>' . $store_settings->out_of_stock_control . '</OutOfStockControl>

GetItFast is a boolean value for specifying whether the “get it fast” shipping is enabled or not.

<GetItFast>' . $boolean_value[$store_settings->get_it_fast] . '</GetItFast>

CategoryBasedAttributesPrefill is a boolean value for specifying whether to prefill some of the item data based on the selected category.

<CategoryBasedAttributesPrefill>' . $boolean_value[$store_settings->category_prefill] . '</CategoryBasedAttributesPrefill>

CategoryMappingAllowed is a boolean value for specifying whether eBay will look up the current category ID that is mapped to the same category and use the new Category ID for the listing or not.

<CategoryMappingAllowed>' . $boolean_value[$store_settings->category_mapping] . '</CategoryMappingAllowed>

ConditionID allows you to specify the item condition. eBay has assigned numeric values to every possible item condition. Check the table on this page.

<ConditionID>' . $store_settings->condition_type . '</ConditionID>

Country allows you to specify the country in which the item is located. You can check out a list of country codes and their corresponding country from this page.

<Country>' . $store_settings->country_code_type . '</Country>

Currency allows you to specify the currency in which the price of the product is expressed.

<Currency>' . $store_settings->currency_code . '</Currency>

Description is the description of the item. You can also pass in HTML to this field.

<Description>' . $item_data['description'] . '</Description>

DispatchTimeMax is the max number of days in which the item will be dispatched or mailed to the customer. Specifying 0 means that the item is mailed to the customer as soon as the order is received.

<DispatchTimeMax>' . $store_settings->dispatch_time . '</DispatchTimeMax>

OptimalPictureSize is a boolean value for specifying whether the the product image will be enlarged to fit the description of the item or not.

<ListingDesigner>
  <OptimalPictureSize>' . $boolean_value[$store_settings->optimal_picturesize] . '</OptimalPictureSize>
</ListingDesigner>

ListingDuration allows you to specify the number of days you want the listing to be active. Valid values can be found on this page.

<ListingDuration>' . $store_settings->listing_duration . '</ListingDuration>

ListingType allows you to specify the type of listing. Valid values can be found on this page. The usual value for this field is either Auction or FixedPriceItem.

<ListingType>' . $store_settings->listing_type . '</ListingType>

Location is the location of the item. This is a conditional field; if you don’t know the value for the PostalCode then you can just specify the value for this field.

<Location>' . $store_settings->item_location . '</Location>

PictureDetails is where we put in the URL’s of the product images that we have uploaded to eBay.

<PictureDetails>'
 . $picture_details . 
'</PictureDetails>

PostalCode is the postal code of the area where the item is located. You can use the Location or this field to specify the location of the item.

<PostalCode>' . $store_settings->postal_code . '</PostalCode>

CategoryID is the ID of the main category of the item.

<PrimaryCategory>
  <CategoryID>' . $item_data['category_id'] . '</CategoryID>
</PrimaryCategory>

Quantity is an integer value of how many units of a specific item you have on your inventory.

<Quantity>' . $item_data['quantity'] . '</Quantity>

SellerContactDetails is where you specify the contact details of the seller. This is an optional field, it uses the seller information by default. But you can use this to override the settings.

<SellerContactDetails>
  <CompanyName>' . $store_settings->store_name . '</CompanyName>
  <County>' . $store_settings->county . '</County>
  <Street>' . $store_settings->street . '</Street>
</SellerContactDetails>

Site is the ID of the eBay website where the product is listed. Examples include US for United States, and UK for United Kingdom. A list of valid values for this field can be found on this page.

<Site>' . $store_settings->ebay_website . '</Site>

StartPrice is the starting price of the item when it is listed for the first time, or when revised or relisted.

<StartPrice currencyID="' . $store_settings->currency_code . '">' . $item_data['price'] . '</StartPrice>

Title is the title of the product.

<Title>' . $item_data['title'] . '</Title>

ShippingDetails is where you specify the shipping details for the product, such as the shipping service to be used, and additional costs if any.

<ShippingDetails>
  <ShippingServiceOptions>
    <ShippingServicePriority>' . $store_settings->shippingservice_priority . '</ShippingServicePriority>
      <ShippingService>' . $store_settings->shipping_service . '</ShippingService>
      <ShippingServiceCost currencyID="' . $store_settings->currency_code . '">' . $store_settings->shippingservice_cost . '</ShippingServiceCost>
      <ShippingServiceAdditionalCost currencyID="' . $store_settings->currency_code . '">' . $store_settings->shippingservice_additionalcost . '</ShippingServiceAdditionalCost>
  </ShippingServiceOptions>
</ShippingDetails>

Conclusion

That’s it! In this tutorial we went through eBay’s Trading API. We have learned that we can talk to their API by acquiring a token for the user. We also walk through fetching the user settings, uploading images and adding products using the API. But that’s not all you can do with Ebay’s Trading API. It’s a pretty huge API and almost anything that you can think of that you can do with eBay with regards to selling products, you can also do with the API. So be sure to check the docs if you’re curious. You can check out the source code of the project we’ve built in this github repository.

Feedback appreciated!

Frequently Asked Questions (FAQs) about Adding Products to eBay Store using Trading API

What is the eBay Trading API and how does it work?

The eBay Trading API is a powerful tool that allows developers to create applications that can perform various operations related to eBay trading. These operations include listing items for sale, managing user information, handling orders, and more. The API works by sending HTTP requests to eBay’s servers, which then respond with the requested data. This data is typically returned in XML format, which can be parsed and used by the application.

How can I add products to my eBay store using the Trading API?

Adding products to your eBay store using the Trading API involves several steps. First, you need to create an application on eBay’s Developer Program website and obtain your API credentials. Then, you can use these credentials to send AddItem requests to the API, specifying the details of the product you want to list. The API will then return a response indicating whether the listing was successful.

What are the common errors when using the eBay Trading API and how can I troubleshoot them?

Common errors when using the eBay Trading API include invalid API credentials, incorrect item details, and issues with the API endpoint. To troubleshoot these errors, you can check the error message returned by the API, which usually provides information about the cause of the error. You can also refer to eBay’s API documentation for more detailed troubleshooting information.

How can I manage my eBay store inventory using the Trading API?

The eBay Trading API provides several operations for managing your store inventory. For example, you can use the ReviseItem operation to update the details of an existing listing, or the EndItem operation to end a listing before its scheduled end time. You can also use the GetSellerList operation to retrieve a list of your active listings.

Can I use the eBay Trading API to handle orders in my eBay store?

Yes, the eBay Trading API provides several operations for handling orders. You can use the GetOrders operation to retrieve information about your orders, the CompleteSale operation to mark an order as shipped or paid, and the LeaveFeedback operation to leave feedback for a buyer.

How can I ensure the security of my eBay Trading API transactions?

To ensure the security of your eBay Trading API transactions, you should always use HTTPS when sending requests to the API. You should also keep your API credentials confidential and store them securely. Additionally, you should regularly review your API usage for any unusual activity.

What are the limitations of the eBay Trading API?

The eBay Trading API has some limitations, such as the number of API calls you can make per day, the number of items you can list per day, and the amount of data you can retrieve in a single API call. These limitations vary depending on your eBay account type and your API usage history.

Can I use the eBay Trading API with other programming languages besides PHP?

Yes, the eBay Trading API can be used with any programming language that supports HTTP and XML. This includes languages like Java, Python, Ruby, and more. However, the specific implementation details may vary depending on the language.

How can I handle errors and exceptions when using the eBay Trading API?

When using the eBay Trading API, you should always check the response for any errors or warnings. These are usually returned in the Errors container of the response. You can then handle these errors or exceptions in your code as appropriate.

Can I use the eBay Trading API to automate my eBay store operations?

Yes, the eBay Trading API is designed to automate various eBay store operations. By integrating the API into your application, you can automate tasks like listing items, managing inventory, handling orders, and more. This can save you time and effort, and help you manage your eBay store more efficiently.

Wern AnchetaWern Ancheta
View Author

Wern is a web developer from the Philippines. He loves building things for the web and sharing the things he has learned by writing in his blog. When he's not coding or learning something new, he enjoys watching anime and playing video games.

apiBrunoSebayOOPHPPHPtrading api
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week