MyCashflow REST API Use Cases

Here you will find practical examples on using various features of the MyCashflow REST API.

For further information about the features of the MyCashflow REST API, see our reference documentation.

Before trying any of these examples out yourself, see the introductory documentation of the API reference page. There we cover important prerequisites for working with the API, including allowed media types, protocols and authentication methods.

In this example we perform the following tasks:

  • Add a product
  • Attach an image to the product
  • Make the product visibile in one version
  • Modify some details of the product.

You can add new products via the API by sending a POST request to the endpoint /api/v1/products. The body of the request must contain at least the name of the product. See example request and JSON body below:

POST /api/v1/products
{
    "name": "Apple 80 GB iPod Video",
    "description": "",
    "information": "* Black iPod with 80 GB hard drive for songs, podcasts, videos, games, and more\r\n* Large, 2.5-inch, 320 x 240 pixel color display screen is 60 percent brighter\r\n* Holds up to 20,000 songs, thousands of photos, and hours of video\r\n* Search function lets you type name of song with Click Wheel for instant results\r\n* Measures 2.4 x 4.1 x 0.55 inches (W x H x D); 1-year limited warranty",
    "keywords": "apple, ipod, mp3 player",
    "price": 332.66,
    "purchase_price": 0,
    "vat_rate": 24,
    "weight": 0.2,
    "brand_id": 13
}

Notice that at the same time we assign the product to the brand with the ID 13.

If the product was added successfully, you will receive a 200 OK response. After adding the product itself, we add a new image to the store's file system and attach it to the product.

Images are added by sending a POST request to the endpoint /api/v1/images. The image can be sent to the in three different ways:

  1. In base64 encoded format
  2. By specifying the local path of an image file
  3. By specifying a remote path of an image file

See further details about adding images in the reference documentation.

Below is an example of a POST body, where we specify the local path of an image:

{
    "filename": "/path/to/image.png"  
}

Again, you will receive a 200 OK response, if the image was added succesfully. After adding the image, we will attach it to the product.

First, find and store the product ID by doing a GET /api/v1/products request. Then create a new image link by sending a POST request to the endpoint /api/v1/products/{productID}/image-links with the following body:

{
    "filename": "image.png",
    "caption": "Uuden tuotteeen ensimmäinen tuotekuva"
}

Once the image link has been created, you will receive a 200 OK response.

Now we make the product visible in one of the store's versions. By default, products – and other resources – created through the API are hidden, so they need to be made visible with a separate PATCH request.

PATCH /api/v1/products/{productId}/visibilities
{
    "version_id": 5,
    "is_visible": true
}

In this example we make the product visible in the version, with the ID 5.

Finally, we make some changes to the product's details. Use the product ID you stored earlier to do a PATCH request to the endpoint /api/v1/products/{productID}. Include any details in the body that you wish to edit:

{
    "name": "Apple 80 GB iPod Video player"
    "purchase_price": 280.00
}

If succesful, fhis request will also return a 200 OK response.

The stock balances of products and variations are defined in stock items, which are attached to them.

An example of a valid PATCH request and JSON body is provided below. Notice that stock items are always identified by the product code of the product or variation they belong to, and not the ID.

PATCH /api/v1/stock/{productCode}
{
  "sku": "A76543456",
  "barcode": "5678987654",
  "location": "Hylly 6, paikka 8",
  "enabled": true,
  "quantity": 6,
  "reserved": 5,
  "balance": 43,
  "balance_alert": true,
  "balance_limit": 3,
  "backorder_enabled": true,
  "backorder_estimate": "2–4 viikkoa"
}

Currently it is not possible to create new stock items via the API, but a new stock item is always created, when you create a new product or variation.

If you need to update the stock balance of a large number of items, we suggest you do not do this one product at a time, instead:

  1. Keep a local copy of the store's stock balances in your API client.
  2. Retrieve the stock items by using GET /api/v1/stock.
  3. Update the stock balances of any required stock items locally.
  4. Once you have updated the stock balances, send the udpated data to the store by doing PATCH /api/v1/stock/{productCode} for each stock item.

This will save a lot of time especially if the store's selection is large (> 10 000 products).

If you need to attach a stock item to a new product or variation, you can change the value of the stock item's code property:

PATCH /api/v1/stock/{productCode}
{
    "code": "245"
}

Notice that the stock item will no longer be available with the previous code, after this request.

Products are added to categories by creating category links. Contrary to brands, a product can have several categories.

Category links are created by sending a POST request to the endpoint /api/v1/category-links or, alternatively, to the endpoint /api/v1/products/{productID}/category-links.

When making the request to /api/v1/category-links, you need to specify the product and the category, which will be linked. In this example we also sort the product to the category's 2nd position:

POST /api/v1/category-links
{
    "product_id": 6,
    "category_id": 5,
    "category_sort": 2
}

When creating a category link in the endpoint /api/v1/products/{productID}/category-links, you only need to specify the category, to which you add the product:

POST /api/v1/products/{productID}/category-links
{
    "category_id": 5,
    "category_sort": 2
}

Both of these requests will return a 200 OK response upon success.

If you need to remove a product from a category, send a DELETE request to the endpoint /api/v1/products/{productID}/category-links/{categoryId}.

You can add translated content to products, variations, and categories through the MyCashflow API. You can also include the translations of any multilingual fields in GET responses.

When you are creating content – in this example products – you can include translated content in the POST body in the translations array:

POST /api/v1/products
{
    "product_code": "AE-12345-89",
    "supplier_code": "876567890",
    "price": 159.95,
    "purchase_price": 120,
    "vat_rate": 24,
    "weight": 0.8,
    "warranty": 12,
    "keywords": "mekot, juhlamekot, puuvilla, pellava",
    "available_from": "2014-08-28",
    "available_to": "2014-08-29",
    "brand_id": 3,
    "supplier_id": 5,
    "translations": [
        {
            "language": "fi",
            "name": ""Leveäolkaiminen juhlamekko, vihreä",
            "description": "<p>Näyttävä ja tyylikäs iltajuhlien timantti! Valmistettu kestävästä puuvillan ja pellavan sekoituksesta. Ajaton ja klassinen muotoilu. Leveät olkaimet tekevät mekosta myös mukavan yllä. Värinä keväinen kirkas vihreä.</p>",
            "information": "<p><strong>pituus</strong>: pitkä<br />\n<strong>kuosi</strong>: yksivärinen<br />\n<strong>kokonaispituus</strong>: 160 cm koossa M<br />\n<strong>päällikankaan materiaali</strong>: 50 % puuvilla, 50 % pellava<br />\n<strong>hoito-ohje</strong>: ei rumpukuivausta, konepesu 30°C</p>",
        },
        {
            "language": "en",
            "name": "Wide strap evening dress, green",
            "description": "<p>Näyttävä ja tyylikäs iltajuhlien timantti! Valmistettu kestävästä puuvillan ja pellavan sekoituksesta. Ajaton ja klassinen muotoilu. Leveät olkaimet tekevät mekosta myös mukavan yllä. Värinä keväinen kirkas vihreä.</p>",
            "information": "<p><strong>pituus</strong>: pitkä<br />\n<strong>kuosi</strong>: yksivärinen<br />\n<strong>kokonaispituus</strong>: 160 cm koossa M<br />\n<strong>päällikankaan materiaali</strong>: 50 % puuvilla, 50 % pellava<br />\n<strong>hoito-ohje</strong>: ei rumpukuivausta, konepesu 30°C</p>",
        }
    ]
}

Notice that when you are adding translated content in a POST / PATCH request, you only need to include the translated fields inside of the translations array.

If you need to modify translated content, you can do so with a PATCH request. In this example we only modify the content in one language. Any other translatations of the same fields will not be affected:

PATCH /api/v1/products/{productID}
{
    "translations": [
        {
            "language": "en",
            "name": "Apple 80 GB iPod Video",
            "information": "* Black iPod with 80 GB hard drive for songs, podcasts, videos, games, and more\r\n* Large, 2.5-inch, 320 x 240 pixel color display screen is 60 percent brighter\r\n* Holds up to 20,000 songs, thousands of photos, and hours of video\r\n* Search function lets you type name of song with Click Wheel for instant results\r\n* Measures 2.4 x 4.1 x 0.55 inches (W x H x D); 1-year limited warranty",
        }
    ]
}

By using the GET parameter expand=translations, you can include translations in GET requests – both when fetching lists and individual objects:

GET /api/v1/products/{productID}?expand=translations
{
    "data": {
        "id": 2,
        "created_at": "2007-04-25T11:35:24+03:00",
        "updated_at": "2013-03-22T10:41:20+02:00",
        "product_code": "",
        "supplier_code": "",
        "name": "Apple 80 GB iPod Video",
        "description": "",
        "information": "* Black iPod with 80 GB hard drive for songs, podcasts, videos, games, and more\r\n* Large, 2.5-inch, 320 x 240 pixel color display screen is 60 percent brighter\r\n* Holds up to 20,000 songs, thousands of photos, and hours of video\r\n* Search function lets you type name of song with Click Wheel for instant results\r\n* Measures 2.4 x 4.1 x 0.55 inches (W x H x D); 1-year limited warranty",
        "keywords": "",
        "price": 332.66,
        "purchase_price": 0,
        "vat_rate": 24,
        "weight": 0.2,
        "warranty": 0,
        "brand_id": 13,
        "supplier_id": 0,
        "available_from": null,
        "available_to": null,
        "barcode": null,
        "translations": [
            {
                "language": "fi",
                "name": "Apple 80 GB iPod Video",
                "description": "",
                "information": "* Black iPod with 80 GB hard drive for songs, podcasts, videos, games, and more\r\n* Large, 2.5-inch, 320 x 240 pixel color display screen is 60 percent brighter\r\n* Holds up to 20,000 songs, thousands of photos, and hours of video\r\n* Search function lets you type name of song with Click Wheel for instant results\r\n* Measures 2.4 x 4.1 x 0.55 inches (W x H x D); 1-year limited warranty"
            },
            {
                "language": "jp",
                "name": "",
                "description": "",
                "information": ""
            },
            {
                "language": "en",
                "name": "",
                "description": "",
                "information": ""
            }
        ]
    }
}

You can use the MyCashflow API to control the visibility of products and categories in the store's versions.

By default, products – and other resources – created through the API are hidden, so they need to be made visible with a separate PATCH request.

Below is an example of making a product visible in one of the store's versions:

PATCH /api/v1/products/{productId}/visibilities
{
    "version_id": 5,
    "is_visible": true
}

If you need to hide a product or category in a version, simply reverse the value of the is_visible key to false:

PATCH /api/v1/products/{productId}/visibilities
{
    "version_id": 5,
    "is_visible": false
}

You can use the MyCashflow API to add images to the store's file system, and to attach images to products.

Images are added to the store's file system by sending a POST request to the endpoint /api/v1/images.

There are 3 alternative ways of adding an image to the store's file system:

  • By providing the file path of a locally stored image
  • By providing the URL of a remotely stored image
  • By providing the image in a base64 encoded format as part of the request body

Below is an example of sending an image from your own computer to the store's file system:

POST /api/v1/images
{
  "filename":"/path/to/image.png"
}

The following request would fetch an image from a remote source, and send it to the store:

POST /api/v1/images
{
  "url":"http://www.domain.fi/image.png"
}

And finally, the following request would send an image to the store in base64 encoded format. The image will be automatically decoded and placed in the product image folder:

POST /api/v1/images
{
  "image":
      {
         "filename":"image.png",
         "data":"[base64 encoded file contents]"
      }
}

Images are automatically assigned a numeric ID, which you can find by fetching a list of the store's images with GET /api/v1/images.

You can use either the image ID or the image filename to attach images to products. Below is an example of attaching an image based on its ID:

POST /api/v1//products/{productId}/image-links
{
  "product_id": 5,
  "image_id": "1",
  "sort": 1,
  "caption": "Kuva tuotteesta"
}

In this request we also sort the image to the top of the product's image list and provide the image with a caption.

You can fetch all the images of a single product with a GET /api/v1/products/{productId}/image-links request.

You can also deattach an image from a product with a DELETE request. When you do this, you need to specify either the filename or the ID of the image as part of the request URL:

DELETE /api/v1/products/{productId}/image-links/filename={fileName}
DELETE /api/v1/products/{productId}/image-links/image_id={imageId}

The orders API is currently in beta testing, and available only under /api/v0/orders.

Using the MyCashflow API, you can perform the following tasks related to orders:

Order lists are retrieved with a GET /api/v0/orders request. You can also use filter parameters to limit the order list to a specific time.

GET /api/v0/orders?updated_at-from=2017-06-14T20:45:52
{
  "data": [
    {
      "id": 101,
      "created_at": "2016-12-31T23:59:59+02:00",
      "updated_at": "2016-12-31T23:59:59+02:00",
      "status": "OPEN",
      "external_id": null,
      "version_id": 1,
      "language": "fi",
      "customer_id": null,
      "shipping_method_id": 1,
      "shipping_costs": 5,
      "payment_method_id": 1,
      "payment_costs": 0,
      "subtotal": 79.9,
      "discount": null,
      "total": 79.9,
      "customer_information": {
        "company": "Yritys Oy",
        "vat_code": "",
        "first_name": "Matti",
        "last_name": "Virtanen",
        "street_address": "Katuosoite 123",
        "postal_code": "00100",
        "city": "Helsinki",
        "country": "FI",
        "phone": "+358 40 1234 567",
        "email": "email@example.com"
      },
      "different_shipping_address": false,
      "shipping_address": {
        "company": "Pulse247 Oy",
        "first_name": "Matti",
        "last_name": "Virtanen",
        "street_address": "Katuosoite 123",
        "postal_code": "00100",
        "city": "Helsinki",
        "country": "FI",
        "phone": "+358 40 1234 567",
        "email": "email@example.com"
      },
    },
    ...
  ],
  "meta": {
    "page": 2,
    "page_size": 100,
    "page_count": 3,
    "item_count": 245,
    "next": "?page=3&page_size=100",
    "previous": "?page=1&page_size=100"
  }
}

The above example would retrieve all orders that have been updated after the provided datetime 2017-06-14T20:45:52.

You can retrieve individual orders by specifying the order ID in the request path: GET /api/v0/orders/{orderId}.

The retrieve commands are expandable, meaning that you can include selected data about the order in the response body. The below example includes the order's product list to the response:

GET /api/v0/orders/{orderId}?expand=products
{
    "data": {
        "id": 57,
        "created_at": "2016-06-14T13:38:56+03:00",
        "updated_at": "2016-06-14T13:48:11+03:00",
        "archived_at": null,
        "external_id": null,
        "version_id": 1,
        "language": "fi",
        "customer_id": null,
        "shipping_method_id": 4,
        "payment_method_id": 5,
        "customer_information": {
            "company": "",
            "vat_code": "",
            "first_name": "Testi",
            "last_name": "Mies",
            "street_address": "Testikatu 10",
            "postal_code": "28100",
            "city": "PORI",
            "country": "FI",
            "phone": "0401234567",
            "email": "example@domain.fi"
        },
        "shipping_address": {
            "company": "",
            "first_name": "Testi",
            "last_name": "Mies",
            "street_address": "Testikatu 10",
            "postal_code": "28100",
            "city": "PORI",
            "country": "FI",
            "phone": "0401234567",
            "email": "example@domain.fi"
        },
        "different_shipping_address": false,
        "subtotal": 843.75,
        "shipping_costs": 3.8999999999999999,
        "payment_costs": 0,
        "discount": {
            "type": "CAMPAIGN",
            "coupon_id": null,
            "campaign_id": 5,
            "code": null,
            "value": 169.53
        },
        "total": 678.12,
        "status": "COMPLETED",
        "receipt_url": "http:\/\/KAUPPA.mycashflow.fi\/orderstatus\/57\/receipt\/588675950264fe8f3989b0eec418b5f6",
        "return_document_url": "http:\/\/KAUPPA.mycashflow.fi\/orderstatus\/57\/returndocument\/fe78501ce807ba1b59558a75c7d5a5ff",
        "dispatch_note_url": "http:\/\/KAUPPA.mycashflow.fi\/orderstatus\/57\/dispatchnote\/cdd461f821623e9c469d63aad089c22a",
        "products": [
            {
                "id": 95,
                "created_at": "2016-06-14T13:38:56+03:00",
                "updated_at": "2016-06-14T13:48:11+03:00",
                "delivered_at": "2016-06-14T13:48:11+03:00",
                "order_id": 57,
                "product_id": 189,
                "variation_id": 952,
                "download_id": null,
                "download_time_ends": null,
                "download_times_left": null,
                "download_url": null,
                "customizations": null,
                "vat_rate": 24,
                "bundle_id": null,
                "campaign_id": null,
                "unit_price": 99.900000000000006,
                "quantity": 5,
                "product_code": "OMAKOODI1234-S",
                "product_name": "Testituotteen nimi",
                "model_name": "Koko: S",
                "warranty": "12"
            },
            ...
        ]
    }
}

New orders are created by sending a POST request to the endpoint /api/v0/orders.

POST /api/v0/orders
{
    "external_id": 1,
    "version_id": 3,
    "shipping_method_id": 6,
    "shipping_costs": 8,
    "payment_method_id": 1,
    "language": "fi",
    "customer_information": {
      "email": "nimi@domain.fi",
      "first_name": "Testi",
      "last_name": "Asiakas",
      "street_address": "Katu 123",
      "postal_code": "33100",
      "city": "Tampere",
      "country": "Suomi",
      "phone": "05012312312"
    },
    "shipping_address": {
      "email": "nimi@domain.fi",
      "company": "Yritys Oy",
      "first_name": "Toinen",
      "last_name": "Testi",
      "street_address": "Katu 345",
      "postal_code": "33100",
      "city": "Tampere",
      "country": "Suomi",
      "phone": "05032132132"
    },
    "products": [
      {
        "product_id": 4,
        "quantity": 2,
        "unit_price": 10.99
      },
      {
        "product_id": 5,
        "variation_id": 2,
        "quantity": 1,
        "unit_price": 4.99
      },
      {
        "product_id": 5,
        "variation_id": 3,
        "quantity": 1,
        "unit_price": 4.99
      }
    ]
}

The above example creates an order with separate billing and shipping addresses and three products (two variations of the same product).

For existing orders, you can create new order comments with a POST /api/v0/orders/{orderId}/comments request.

POST /api/v0/orders/{orderId}/comments
{
    "text": "Kommentin sisältö",
    "visibility": "PUBLIC",
    "update_timestamp": true
}

You can also use the quick processing feature through the API. Simply send a POST request to the endpoint /api/v0/orders/{orderId}/quick-process. The request will return a 200 OK response upon success.

POST /api/v0/orders/{orderId}/quick-process
{
    "ignore_payment_activation_errors": true,
    "send_emails": true,
    "tracking_code": "98765rdcvbnjki7"
}

If the order has payment transactions using Klarna and the payments have been processed in Klarna Online, you may want to set ignore_payment_activation_errors to true, so that the request is not interrupted by errors.

The send_emails parameter determines, whether to send an automatic shipping confirmation upon successful processing.

If the order can be tracked using an online tracking service (such as with Posti and Matkahuolto), you can enter the tracking code for the order in the tracking_code field.

Read more about shipments and tracking codes in the API ›

You can also use the API to mark certain payments as paid or unpaid, and to cancel payments and activate Klarna payments.

Only payments made using the in-built payment services of MyCashflow (invoice, pre-payment and payment on receipt) can be marked paid or unpaid.

First, to find out the ID's of any required payments, you need to retrieve a list of payments by using GET /api/v0/orders/{orderId}?expand=payments or a specific payment by using GET /api/v0/orders/{orderId}/payments/{paymentId}.

Mark payments as paid with a POST /api/v0/orders/{orderId}/payments/{paymentId}/mark-as-paid request.

Similarly, you can mark payments as unpaid with a POST /api/v0/orders/{orderId}/payments/{paymentId}/mark-as-unpaid request.

The activation of Klarna payments is done with the request POST /api/v0/orders/{orderId}/payments/{paymentId}/activate/.

The cancellation of payments is done with a POST /orders/{orderId}/payments/{paymentId}/mark-as-cancelled request.

All of the above requests are made with an empty request body.

The requests handling payments will return a 200 OK response upon success with the payment details included in the response body:

POST /api/v0/orders/{orderId}/payments/{paymentId}/mark-as-paid
{
    "data": {
        "id": 3,
        "created_at": "2014-08-28T21:15:55+03:00",
        "updated_at": "2015-03-17T11:11:50+02:00",
        "order_id": 3,
        "payment_method_id": 1,
        "reference": "201408280030",
        "external_id": null,
        "amount": 130.40000000000001,
        "currency": "EUR",
        "exchange_rate": 1,
        "is_confirmed": false,
        "is_paid": false,

        /* Status is only available for Klarna payments */
        "status": "<<OPEN | PAID | PENDING_ACTIVATION | REFUNDED | CANCELLED>>",
        "invoice_url": "http:\/\/KAUPPA.mycashflow.fi\/orderstatus\/3\/invoice\/6561daba8e878e2c94989ce99156a0c3"
    }
}

Finally, you can also register shipments by using the API. By registering a shipment you get the address label and tracking code (which you can enter in the quick processing request) for the order.

You can retrieve a list of an order's shipments by using the expand=shipments URL parameter:

GET /api/v0/orders/{orderId}?expand=shipments
{
    "data": {
        "id": 57,
        "created_at": "2016-06-14T13:38:56+03:00",
        "updated_at": "2016-06-14T13:48:11+03:00",
        "archived_at": null,
        "external_id": null,
        "version_id": 1,
        "language": "fi",
        "customer_id": null,
        "shipping_method_id": 4,
        "payment_method_id": 5,
        "customer_information": {
            "company": "",
            "vat_code": "",
            "first_name": "Testi",
            "last_name": "Mies",
            "street_address": "Testikatu 10",
            "postal_code": "28100",
            "city": "PORI",
            "country": "FI",
            "phone": "0401234567",
            "email": "example@domain.fi"
        },
        "shipping_address": {
            "company": "",
            "first_name": "Testi",
            "last_name": "Mies",
            "street_address": "Testikatu 10",
            "postal_code": "28100",
            "city": "PORI",
            "country": "FI",
            "phone": "0401234567",
            "email": "example@domain.fi"
        },
        "different_shipping_address": false,
        "subtotal": 843.75,
        "shipping_costs": 3.8999999999999999,
        "payment_costs": 0,
        "discount": {
            "type": "CAMPAIGN",
            "coupon_id": null,
            "campaign_id": 5,
            "code": null,
            "value": 169.53
        },
        "total": 678.12,
        "status": "COMPLETED",
        "receipt_url": "http:\/\/KAUPPA.mycashflow.fi\/orderstatus\/57\/receipt\/588675950264fe8f3989b0eec418b5f6",
        "return_document_url": "http:\/\/KAUPPA.mycashflow.fi\/orderstatus\/57\/returndocument\/fe78501ce807ba1b59558a75c7d5a5ff",
        "dispatch_note_url": "http:\/\/KAUPPA.mycashflow.fi\/orderstatus\/57\/dispatchnote\/cdd461f821623e9c469d63aad089c22a",
        "shipments": [
            {
                "order_id": 57,
                "shipping_method_id": 4,
                "weight": 10.5,
                "parcel_count": 1,
                "tracking_code": null,
                "external_id": null,
                "external_pickup_point_id": "281053201",
                "shipping_label_url": null
            }
        ]
    }
}

Registering shipments is done with a POST /api/v0/orders/{orderId}/shipments/{shipmentId}/register request. Upon success, this will result in a 200 OK response, with the shipment details in the response body:

POST /api/v0/orders/{orderId}/shipments/{shipmentId}
{
  "data": {
    "order_id": 1,
    "shipping_method_id": 1,
    "weight": 0.25,
    "parcel_count": 1,
    "tracking_code": null,
    "external_id": null,
    "external_pickup_point_id": null,
    "shipping_label_url": null
  }
}