Fyndiq API v1 - documentation

This page describes how to connect to Fyndiq API v1 using an existing merchant account.

Please note that API v1 is no longer being actively maintained and integrating for API v1 is discouraged.

API tokens

All calls to Fyndiq API must be authenticated by providing a username and an API token as query string parameters on the URL.
Username is the username of a Fyndiq Merchant account - the same value used to login to Fyndiq Merchant Panel.
API token is a unique key generated for the account, specifically designed to be used with the API.
It's possible to create as many API tokens as you want on the API tab in the Fyndiq Merchant Panel.

Example:

$ curl https://fyndiq.se/api/v1/product/4711/?user=nisse&token=uf834jf4uwn45

Introduction to REST

Fyndiq's API is a so called REST API, meaning (among other things) that resources are a central concept.
A resource provides data objects representing items in our system.
In Fyndiq's case it is quite straight forward, since we have a limited amount of resources available.
What you as a merchant/platform mainly will be doing is modifying objects on the resources account, product, and order.

For example, all products in an account can be found under fyndiq.se/api/v1/product/.
If you call this address you will get back a list of all products in the account.
If you want to access a specific object, simply add the product ID at the end.

Here is an example of getting the data from a specific product by its ID number.
(All examples in this document uses the command line tool curl, which is a very useful tool for testing APIs).

$ curl https://fyndiq.se/api/v1/product/4711/?user=nisse&token=uf834jf4uwn45

What if you want to change data on an object in a resource? Or deleting an object in a resource? Adding a new object in a resource?
It's simple! In the REST world you use the same URL, but switch to a different HTTP method, so instead of GET, you would use PUT, DELETE, or POST.

HTTP Method Description
GET Get data from an object, or a collection of objects.
POST Add new object in a resource.
PUT Replace data in an object with the provided data in the request body.
DELETE Delete an object from a resource.

In summary:
To read data, use GET.
To create a new object, use POST (currently only supported for products).
To update data in an object, use PUT.
To delete an object, use DELETE (currently only supported for products).

Rate limit

Note that all api/v1 requests have a rate limit. You can make up to 300 requests / minute. This limit is across all methods (GET, POST, PUT, DELETE) and resources. So if you made 10 GET requests against a product, followed by 10 PUT requests to product and 10 GET requests to order, that is 30 requests.

Filtering and Pagination

Filtering

For some resources, it's possible to filter the list of objects returned by GET.
This is done by adding a field name as a part of the query string.
For instance, if you want to get all orders that are marked, you can add marked=true to the query string.

A complete example can look something like this:

$ curl https://fyndiq.se/api/v1/order/?user=nisse&token=uf834jf4uwn45&marked=true

For every resource in this documentation, there is a list of all the fields that are possible to use for filtering.

Pagination

If a list contains more than 100 objects, the response will be paginated.
To retrieve a different page in the list, use the offset parameter.
offset=0 will give the first page, offset=1 will give the second page, etc.

You can see if there are more pages available, by checking the response's meta field.
The meta field in the response looks like this, in JSON:

{
    "meta": {
        "limit": 100,
        "next": null,
        "offset": 0,
        "previous": null,
        "total_count": 3
    },
    "objects": [
        ...
    ]
}

The limit fields tells you how many objects are returned on every page.
In this case there are 100 objects per page.
The fields next and prev contains link to the next and previous page of the list.
If there is no next or previous page, these fields will be null.
The field total_count tells you the total number of objects available on the whole result set, across all pages.

The following example shows how the meta field looks when there are 173 objects in total:

{
    "meta": {
        "limit": 100,
        "next": "/api/v1/product/?user=nisse&token=uf834jf4uwn45&offset=1&format=json",
        "offset": 0,
        "previous": null,
        "total_count": 173
    },
    "objects": [
        ...
    ]
}

Here you can see that next is the same URL as the original request, except with the difference offset=1.
This points to page 1, since this example response is currently for page 0.

Data format

Fyndiq API v1 support JSON as the data format. All examples in this document will also be in JSON unless otherwise specified.

Resource: Product

Property Value
URL https://fyndiq.se/api/v1/product/
Methods GET, POST, PUT, DELETE

The core of Fyndiq is the products that we sell. Using our API you can freely create, read, update, and delete products.
Some useful functionality that can be built around this is keeping stock amounts in sync, or add products in an automated way from your platform into Fyndiq.

NB: All product data, such as titles and descriptions of products and articles, must be well formatted plain text.
No HTML or other codes are allowed.

Update flow for products

It's important to know that on Fyndiq, we will always manually review products before the are put out for sale.
This means that there will be a delay, between when the API call is made - and the product is available on the site.

When a product is updated, it might require a review by Fyndiq, depending on which fields are updated.
Please see the column "Review required" in the table below, to see which fields will trigger re-validation or not.
If you have made an update that requires a review, the product will enter state submitted again.
Again, this means that there will be a delay until the product is available on the site.

Fields

Product
Field name Description Required? Data type Example value Review required
title Product title Required String, 5-64 chars "Sverigeklänningen för flickor" Yes
description Product description Required String, 10-4096 chars "En härlig klänning för alla dess festligheter. Ett traditionellt plagg som blir allt populärare att bära nu när det finns en enklare variant. Exempel på tillfällen är midsommar, bröllop, kalas, och härliga sommardagar." Yes
oldprice Original price incl. VAT Required, must be greater than 0 Decimal "345.00" No
price Price on Fyndiq incl. VAT Required, must be greater than 0 Decimal "199.00" No
moms_percent VAT percent Required Integer 25 Yes
num_in_stock Amount in stock Required (if the product has articles, set this to 0, maximum value allowed is 100000) Integer 42 No
state The state the product is in.
Possible values are: "submitted", "proposed", "for_sale", "paused", "sold_out", "rejected", "deleted".
Read only String "for_sale" N/A
is_blocked_by_fyndiq Product is blocked and is not for sale Read only Boolean false N/A
item_no (when reading: merchant_item_no) Merchant's article number Optional String, 0-64 chars "ART24442" No
platform_item_no Platform's internal article ID Optional String, 0-64 chars "4711" No
location (when reading: merchant_location) Merchant's warehouse location Optional String, 0-64 chars "Hylla 35" No
url URL to product page Read only String "https://fyndiq.se/barn/barnklader/naturgummistovel-barn/" N/A
variation_group Article group Optional See definition of article group. When writing:
{ "name":"Storlek", "variations": [{"name":"1-3 år", "num_in_stock":12, "location":"Hylla 12", "item_no":"Svkl 1-3"}, {"name":"4-6 år", "num_in_stock":21, "location": "Hylla 13", "item_no": "Svkl 4-6"}] }

When reading:
[{ "name":"Storlek", "variations": [{"name":"1-3 år", "num_in_stock":12, "location":"Hylla 12", "item_no":"Svkl 1-3"}, {"name":"4-6 år", "num_in_stock":21, "location": "Hylla 13", "item_no": "Svkl 4-6"}] }]
N/A
images Product images Required List of strings. Contains a list of image URLs. The images must be publicly accessible on their given URLs. Allowed formats are GIF, JPEG, and PNG. ["https://example.com/product1-1.jpg", "https://example.com/product1-2.jpg"] Yes
Product article group

When writing, only one product article group object should be sent.
When reading, a list of product article group objects will be returned, however, the length of this list will never be larger than 1.

When updating the list of product articles, it's important to know this:

Field Description Required? Data type Example value
name Article group name.
This field is actually not used anymore. It must still be provided for backwards compatibility reasons, but it does not matter what value you put here. We suggest to always provide an empty string for this field.
Required String, 0-30 chars "Storlek"
variations A list of articles Required See definition of product article [{"name":"1-3 år", "num_in_stock":12, "location":"Hylla 12", "item_no":"Svkl 1-3"}, {"name":"4-6 år", "num_in_stock":21, "location": "Hylla 13", "item_no": "Svkl 4-6"}]
Product article

When sending a list of product articles, it's important to know this:

Adding a new article means that the whole product will require review (enter state submitted).
Modifying an existing article might require a review, depending on which fields are updated.
Please see the column "Review required" in the table below, to see which fields will trigger re-validation or not.

Field Description Required? Data type Example value Review required
id Article ID Only on update Integer 9234752 N/A
name Article name Only on create String, 0-30 chars "4-6 år" Yes
num_in_stock Amount in stock Only on create Integer, maximum value allowed is 100000 13 No
location Merchant's warehouse location Optional String, 0-64 chars "Hylla 13" No
item_no Merchant's article number Optional String, 0-64 chars "Svkl 4-6" No
platform_item_no Platform's internal article ID Optional String, 0-64 chars "4711" No

GET (Read products)

To get all products belonging to an account, don't specify a product ID:

$ curl "https://fyndiq.se/api/v1/product/?user=nisse&token=uf834jf4uwn45"

To get a specific product, use the same URL as before, but add a product ID:

$ curl "https://fyndiq.se/api/v1/product/323/?user=nisse&token=uf834jf4uwn45"

POST (Create products)

To create a new product, perform a POST request with the necessary JSON data in the request body:

$ curl -X POST -d "{}" -H "Content-type: application/json" "https://fyndiq.se/api/v1/product/?user=nisse&token=uf834jf4uwn45"

Note that the response body will be empty, but there will be a header "Location" that points to the generated API URL for the product.
This is useful for finding out which product ID was generated for the product.

PUT (Update products)

To make changes in a product, perform a PUT request with necessary JSON data in the request body.
Remember to provide a product ID in the URL.
You only need to include the fields that you actually want to update. Fields that are not mentioned in your request will not be modified.

Example of updating the title field of a product with id 343:

$ curl -X PUT -d '{"title":"ny titel"}' -H "Content-type: application/json" "https://fyndiq.se/api/v1/product/343/?user=nisse&token=uf834jf4uwn45"

DELETE (Delete products)

To delete a product, perform a DELETE request.
Remember to provide a product ID in the URL.

Example of deleteing a product with id 343.

$ curl -X DELETE "https://fyndiq.se/api/v1/product/343/?user=nisse&token=uf834jf4uwn45"

Resource: Order

Property Value
URL https://fyndiq.se/api/v1/order/
Methods GET

GET

Field Description Data type Example value
id Order ID Integer 1732
invoice_firstname First name (invoice) String "Bertil" (If a company name is provided by the customer, it will be returned in this field, and the firstname and lastname will be concatenated into the invoice_lastname field.)
invoice_lastname Last name (invoice) String "Bertilsson"
invoice_address Postal address (invoice) String "Bertilgatan 3B"
invoice_postalcode Postal code (invoice) String "75591"
invoice_city City (invoice) String "Uppsala"
invoice_phone Phone number customer String "0707123123"
invoice_email Email customer
Deprecated. Will always be "order@fyndiq.se"!
String "order@fyndiq.se"
invoice_co C/O String "Nils Nilsson"
delivery_firstname First name (delivery) String "Bertil" (If a company name is provided by the customer, it will be returned in this field, and the firstname and lastname will be concatenated into the delivery_lastname field.)
delivery_lastname Last name (delivery) String "Bertilsson"
delivery_address Postal address (delivery) String "Bertilgatan 3B"
delivery_postalcode Postal code (delivery) String "75591"
delivery_city City (delivery) String "Uppsala"
delivery_co C/O String "Nils Nilsson"
pdf_url URL to delivery note String "https://fyndiq.se/handlare/faktura/1133-223/"
freightback_incl_vat Reimbursed shipment amount incl. VAT
Deprecated. Will always be 0!
Decimal "0.00"
freightback_excl_vat Reimbursed shipment amount excl. VAT
Deprecated. Will always be 0!
Decimal "0.00"
freightback_vat Reimbursed shipment amount VAT
Deprecated. Will always be 0!
Decimal "0.00"
provision_incl_vat Selling fee incl. VAT Decimal "20.00"
provision_excl_vat Selling fee excl. VAT Decimal "16.00"
provision_vat Selling fee VAT Decimal "4.00"
merchantclaim_incl_vat Merchant claim incl. VAT Decimal "125.00"
merchantclaim_excl_vat Merchant claim excl. VAT Decimal "25.00"
marked Order is marked by merchant Boolean true
order_rows Order rows See definition of order row [{"item_no": "3040", "location": "Hylla 2", "product_id": 4323, "quantity": 2, "title": "Brio - Dragleksak Helikopter"}, {"item_no": "3039", "location": "Hylla 3", "product_id": 4355, "quantity": 1, "title": "Brio - Dragleksak Giraff"}]

Order row

Field Description Data type Example value
title Product name (including article, if any) String "Brio - Dragleksak Helikopter"
quantity Amount of items Integer 1
item_no Merchant's article numner String "3039"
location Merchant's warehouse location String "Hylla 3"
product_id Product ID Integer 4355
price_per_item_incl_vat Price per product on order row incl. VAT Decimal "125.00"
price_per_item_excl_vat Price per product on order row excl. VAT Decimal "100.00"
price_per_item_vat Price per product on order row VAT Decimal "25.00"
price_sum_incl_vat Price sum for order row incl. VAT Decimal "125.00"
price_sum_excl_vat Price sum for order row excl. VAT Decimal "100.00"
price_sum_vat Price sum for order row VAT Decimal "25.00"
provision_incl_vat Selling fee for order row incl. VAT Decimal "15.00"
provision_excl_vat Selling fee for order row excl. VAT Decimal "12.00"
provision_vat Selling fee for order row VAT Decimal "3.00"
merchantclaim_incl_vat Merchant claim for order row incl. VAT Decimal "125.00"
merchantclaim_excl_vat Merchant claim for order row excl. VAT Decimal "100.00"
merchantclaim_vat Merchant claim for order row VAT Decimal "25.00"
moms_percent VAT percent for order row Integer 25
platform_item_no Platform's internal article ID String "4711"

PUT

Order can be marked as handled by setting the field marked to true.
This field can be used to filter orders in a GET request, to only show unhandled orders.

Field Description Data type Example value
marked Merchant has marked order Boolean true

Filtering

The following field can be filtered:

Field Possible values
marked true or false

Resource: Account

Property Value
URL https://fyndiq.se/api/v1/account/
Methods GET, PUT, POST

Fields

Field Description Data type Example value
username Username String "bertil4711"
password Password String "w4/!rU#sn"
user_firstname Webshop contact person - first name String "Bertil"
user_lastname Webshop contact person - last name String "Bertilsson"
user_email Webshop contact person - email (this is where order emails are sent!) String "ordermail@example.com"
user_phone Webshop contact person - phone number String "08-12345432"
shop_name Webshop name String "Bertils Mockasinshop"
shop_company Name of the company behind the webshop String "Bertils Mockasiner AB"
shop_url URL to webshop's website String "https://www.bertilsmockasiner.se"
shop_org_num Company Registration Number String "5511229192"
shop_vat_num Company VAT Number String "SE949047822001"
shop_address Company postal address String "Mockasingatan 12"
shop_postal_code Company postal code String "11350"
shop_city Company city String "Stockholm"
shop_phone Company phone String "08-1234567"
id Webshop ID at Fyndiq Integer 236
notify_url URL for notifications String "https://www.bertilsmockasiner.se/notifications/"
notify_answer String identifying that notifiction is successful (may be empty) String "success"

GET (Read account)

To read all data in an account (account being the one that you are using to authenticate with):

$ curl "https://fyndiq.se/api/v1/account/?user=nisse&token=uf834jf4uwn45"

PUT (Update account)

To update data in an account, make sure you know the webshop ID and add it to URL, when doing a PUT request:

$ curl -X PUT -d '{"shop_phone" : "08-6558932"}' "https://fyndiq.se/api/v1/account/45/?user=nisse&token=uf834jf4uwn45"

POST (Create account)

To create an account, perform a POST request to the account resource.
When creating a new account, there is no need to provide the authentication parameters username or API token in the query string.
A URL to create an account should look like this: https://fyndiq.se/api/v1/account/?format=json.
When creating an account, it's important to send all the necessary information.
The following complete JSON example shows all parameters:

{
  "shop_address": "Testgatan 1",
  "shop_city": "Teststaden",
  "shop_company": "Testföretaget AB",
  "shop_name": "Testaffären",
  "shop_org_num": "5533333333",
  "shop_vat_num": "SE949047822001",
  "shop_phone": "020-333 333",
  "shop_postal_code": "33333",
  "shop_url": "http://www.example.com",
  "user_email": "example@example.com",
  "user_firstname": "Testanvändaren",
  "user_lastname": "Testanvändaren",
  "user_phone": "08-111222333",
  "username": "testanvandaren",
  "password": "testlosen"
}

In the response headers, you will find the Location header.
This field contains a URL to the created object.
This URL contains the authentication parameters username and API token in the query string,
making it possible to start using the API directly after creating the account.

Resource: Delivery Notes

Property Value
URL https://fyndiq.se/api/v1/hamta-plocklistor/
Methods POST

This resource provides access to aggregated delivery notes. Input data is an object with an array of order IDs ("orders").
Here is an example: {"orders": [1,2,3,4]}.

The response is a PDF document for all of the given orders.

The documents will by default be ordered by the order ID value in ascending order.
You may also choose to order the documents in the same order that you asked for them in the input arguments, by adding order_by=input to the querystring.

The array of order IDs can't have more than 300 elements. Providing more elements will return error message.

Test mode

When building an API integration it's possible to send an extra parameter on any call, to make the request go into "test mode".
In the test mode, the API will act as normal, except that no changes you make will be stored in our database.
This means that you can safely try out POST-, PUT-, and DELETE-requests, knowing that nothing will be modified in Fyndiq's systems.

Add test=1 to the URL to any request to make that request use the test mode.

Here is a full example, in this case we do a POST to product resource, but since we have test=1, no product will be added.

$ curl -X POST -d "{}" -H "Content-type: application/json" "https://fyndiq.se/api/v1/product/?user=nisse&token=uf834jf4uwn45&test=1"

PHP wrapper

Here follows a simple code example to demonstrate the basics of how to use Fyndiq API v1 in PHP.
The function fyndiq_api_request() can make all types of calls, and could be used as a starting point
for a full API integration.

<?php
/* Note that the following script requires curl for php */

function fyndiq_api_request($resource,       // should be either 'product', 'order' or 'webshop'
                            $username,       // username at Fyndiq
                            $token,          // api-token which can be retrieved via fyndiq.se/handlare/
                            $method = 'GET', // should be 'GET', 'POST', 'PUT' or 'DELETE'
                            $id = 0,         // specify id to affect specific item, 0 means all items
                            $data = null,    // when doing 'POST' or 'PUT' - provide data
                            $test = false )  // set this to true to enable readonly test mode
{
  // Specify that we want to communicate via JSON
  $headers = array(
    'Accept: application/json',
    'Content-Type: application/json',
  );

  // Construct a request URL
  $url = "https://fyndiq.se/api/v1/$resource/";
  if ($id && $id > 0) { $url .= "$id/"; }
  $url .= "?user=$username&token=$token";
  if($test) { $url .= '&test=1'; }

  // Initiate curl and set curl options
  $handle = curl_init();
  curl_setopt($handle, CURLOPT_URL, $url);
  curl_setopt($handle, CURLOPT_HTTPHEADER, $headers);
  curl_setopt($handle, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($handle, CURLOPT_SSL_VERIFYHOST, false);
  curl_setopt($handle, CURLOPT_SSL_VERIFYPEER, false);

  // Set additional method specific options
  switch($method) {
    case 'GET':
      break;
    case 'POST':
      curl_setopt($handle, CURLOPT_POST, true);
      curl_setopt($handle, CURLOPT_POSTFIELDS, $data);
      break;
    case 'PUT':
      curl_setopt($handle, CURLOPT_CUSTOMREQUEST, 'PUT');
      curl_setopt($handle, CURLOPT_POSTFIELDS, $data);
      break;
    case 'DELETE':
      curl_setopt($handle, CURLOPT_CUSTOMREQUEST, 'DELETE');
      break;
  }

  // Make request and return decoded response
  $response = curl_exec($handle);
  $code = curl_getinfo($handle, CURLINFO_HTTP_CODE);
  $decoded_response = json_decode($response, true);
  return $decoded_response;
}
?>

Here are some examples showing different uses of the function fyndiq_api_request().

<?php
print("Retrieving account\n\n");
$resp = fyndiq_api_request('account', 'nisse', 'abcde', $method = 'GET', $id = null, $data = null);
var_dump($resp);

print("Changing username in account\n\n");
$updated_user_data = json_encode(array(
'user_firstname'=> 'Nyttfornamn',
));
$resp = fyndiq_api_request('account', 'nisse', 'abcde', $method = 'PUT', $id = 3, $data = $updated_user_data);
var_dump($resp);

print("Retrieving account again\n\n");
$resp = fyndiq_api_request('account', 'nisse', 'abcde', $method = 'GET', $id = 3, $data = null);
var_dump($resp);

print("Creating new product\n\n");
$new_product_data = json_encode(array(
  'title' => 'En ny produkt!',
  'description' => 'Detta är en beskrivning av produkten.',
  'oldprice' => 500.50,
  'price' => 320.00,
  'num_in_stock' => 33,
  'images' => array("https://example.com/image1.jpg", "https://example.com/image2.jpg"),
  'variation_group' => array('name'=>'Storlek',
                             'variations'=>array(
                                  array('name'=>'Storlek 42', 'num_in_stock'=>44),
                                  array('name'=>'Storlek 45', 'num_in_stock'=>22)) ),
  'moms_percent' => 25
));
$resp = fyndiq_api_request('product', 'nisse', 'abcde', $method = 'POST', $id = null, $data = $new_product_data);
var_dump($resp);

print("Listing all products\n\n");
$resp = fyndiq_api_request('product', 'nisse', 'abcde', $method = 'GET', $id = null, $data = null);
var_dump($resp);

print("Listing all orders\n\n");
$resp = fyndiq_api_request('order', 'nisse', 'abcde', $method = 'GET', $id = null, $data = null);
var_dump($resp);
?>

11. Notification system

Overview

In order to minimize the need to poll the API for changes, there is a notification system.
This means that Fyndiq can notify you when a product or order has changed.
For example, if we modify the description text of a product, or if a new order is created.

You can activate support for notifications by supplying a notify_url and a notify_answer in your account.
This is possible to set in the account resource in the API - or in the API settings tab in the merchant pages.
Once these values has been set, Fyndiq will call the URL provided in notify_url, with a number of parameters detailing the specifics about the event.
This URL should return a HTTP 200 status code, and should contain the string given in notify_answer.

In case a notification request fails, Fyndiq will retry requests multiple times, for up to 24 hours.

However, if the URL is not reachable after this, the notification is lost.
We can not guarantee that notifications will reach their target every single time.

Also note that there is always a risk of network problems that lie out of yours and Fyndiq's control.
This further strengthens the point that it can not be guaranteed that notifications always reach their target.

Also, note boldly that there can be a delay between the event taking place, and a notification being sent.
For example - when a user places an order on Fyndiq, or if we modify the description of a product - there could be several minutes before you receive the notification about this event.

Parameters

A notification request will contain the following query string parameters:

Name Value Description
collection product or order Spefifies which type of object has been changed. Currently, the only possible objects are products and orders.
event updated or created Specifies if the object was created or updated.
id an Integer The object's unique ID.
images true or false Specifies if the event did anything with images (this is only sent for products, not orders).
merchant an Integer Merchant ID (this is only sent for orders, not products).

Example

Assume you have set notify_url to https://example.com/fyndiq-notify.php, and that a product with ID 4711 has been changed, and an image was removed.
Then, Fyndiq will make a request to the following URI:

https://example.com/fyndiq-notify.php?collection=product&event=updated&id=4711&images=true

Published: 01 November 2017