Full Scenario

This tutorial details all the steps involved in putting an album online, from creating a Label to creating a SendTask (i.e., a delivery to a DSP).

🔑 Authenticate

First of all, let’s get a token to authenticate against the API.

require "rest-client"
require "json"

login       = "Login"
password    = "Password"

response = RestClient.post(
            "https://api.idol.io/oauth/token",
            {
                grant_type: "password",
                username:   login,
                password:   password
            }
        )
token = JSON.parse(response)["access_token"] // => 'c90450...'

📣 Create Label

Each album has to be associated with a Label. Let's create a new Label and name it Demo label.

First, all labels are associated to a Company (called Contract in the Labelcamp UI ). In a standard delivery context, only a single Company is mandatory, to which you can associate all your Labels. We need to retrieve the available companies:

response = RestClient.get(
          "https://api.idol.io/api/v2/companies",
          "Authorization": "Bearer <token>",
          "Content-Type": "application/vnd.api+json"
      )

JSON.parse(response)['data']
// => [{"id"=>"666", "type"=>"companies", "links"=>{"self"=>"https://api.idol.io/api/v2/companies/<ID>"}, "attributes"=>{"created-at"=>"2013-11-18T08:07:13.000+01:00", "updated-at"=>"2018-02-21T18:06:19.311+01:00", "name"=>"Record Company", "children-count"=>6, "label-manager"=>nil, "is-tva-applicable"=>true}, "relationships"=>{"distributor"=>{"links"=>{"self"=>"https://api.idol.io/api/v2/companies/<ID>/relationships/distributor", "related"=>"https://api.idol.io/api/v2/companies/<ID>/distributor"}, "data"=>{"type"=>"distributors", "id"=>"13"}},
Company

The Company demo (id: 666) is the one available, we will use it to create our Label:

response =  RestClient.post(
              "https://api.idol.io/api/v2/labels",
              {
                "data": {
                  "attributes": {
                    "name": "My beautiful Label",
                    "cover-url": '',
                    "usage": {
                      "download": true,
                      "copy_scan": true,
                      "on_demand_stream": true,
                      "non_interactive_stream": true
                    }
                  },
                  "relationships": {
                    "rights": {
                      "data": []
                    },
                    "company": {
                      "data": {
                        "type": "companies",
                        "id": "<ID>"
                      }
                    },
                  },
                  "type": "labels"
                }
              }.to_json,
              "Content-Type": 'application/vnd.api+json',
              "Authorization": "Bearer #{token}"
            )

JSON.parse(response)['data']
// => [{"id"=>"555", "type"=>"labels"...}]
Label

📀 Create Product

Now that we have the label (id : 555), we can create the Product:

response =  RestClient.post(
              "https://api.idol.io/api/v2/products",
              {
                "data": {
                  "attributes": {
                    "artist": [
                      "Artist demo"
                    ],
                    "name": "Demo album",
                    "is-compilation": false,
                    "upc-code": "",
                    "copyright-line": "2025 Demo",
                    "production-line": "2025 Demo",
                    "production-year": 2025
                  },
                  "relationships":{
                    "label":{
                      "data":{
                        "type": "labels",
                        "id": "555"
                      }
                    }
                  },
                  "type": "products"
                }
              }.to_json,
              "Authorization": "Bearer {token}",
              "Content-Type": "application/vnd.api+json"
            )


 product = JSON.parse(response)['data']
 // => [{"id"=>"214477", "type"=>"products"...}]
Product

🎙️ Import Record

Each album contains one or more tracks. Let’s create a Track:

response = RestClient.post(
            "https://api.idol.io/api/v2/tracks",
            {
              "data": {
                "attributes": {
                  "title": "My title",
                  "artist": [
                    "My Artist"
                  ],
                  "isrc-code": "AEA020900003",
                  "track-number": "3",
                  "volume-number": "1",
                },
                "relationships": {
                  "product": {
                    "data": {
                      "id": "214477",
                      "type": "products"
                    }
                  }
                },
                "type": "tracks"
              }
            }.to_json,
            "Authorization": "Bearer <token>",
            "Content-Type": "application/vnd.api+json"
          )

track = JSON.parse(response)['data']
// => [{"id"=>"1709847", "type"=>"tracks"...}]
Track

Now, you need to associate a FLAC audio file with the Track. To do this, you must create an ImportTask and attach a download link to the record. The ImportTask will be processed asynchronously and will result in the creation of a new Record attached to the Track. Here is how to create an ImportTask:

Find more information about audio specifications in this Help Center's article.

response = RestClient.post(
            "https://api.idol.io/api/v2/import-tasks",
            {
              "data": {
                "id": <ID>,
                "type": "import-tasks",
                "attributes": {
                    "created-at": "2024-12-22T16:33:38.866+01:00",
                    "updated-at": "2024-12-22T16:33:38.866+01:00",
                    "precision": "24",
                    "master-type": "hd",
                    "status": "uploaded",
                    "url": 'https://<download_record_url>',
                },
                "relationships": {
                    "attachable": {
                        "data": {
                            "type": "products",
                            "id": "<ID>"
                        }
                    }
                }
              }
            }.to_json,
            "Authorization": "Bearer <token>",
            "Content-Type": "application/vnd.api+json"
          )

import_task = JSON.parse(response)['data']
// => [{"id"=>"4372632", "type"=>"import-tasks"...}]
ImportTask [NEW]

🌍 Add Rights

Our album must only be available on Apple Music and Spotify, with US rights.

We need to retrieve the Territory ID for US:

response = RestClient.get(
               "https://api.idol.io/api/v2/territories?filter[code_alpha_2]=US",
               Authorization: "Bearer <token>",
               "Content-Type": 'application/vnd.api+json'
           )
 
 JSON.parse(response)['data'].first['id']
 // => "223"
Territory

If you haven't read it yet, please read this article on how to manage static resources.

Then we need to retrieve our Distributor ID:

response = RestClient.get(
               "https://api.idol.io/api/v2/distributors?filter[name]=Distributeur test",
               Authorization: "Bearer <token>",
               "Content-Type": "application/vnd.api+json"
           )

 JSON.parse(response)['data'].first['id']
 // => "13"
Distributor

We also need to retrieve the Apple Music and Spotify IDs:

response = RestClient.get(
              "https://api.idol.io/api/v2/dsp-upload-identifications?include=dsp",
              "Content-Type": 'application/vnd.api+json',
              "Authorization": "Bearer <token>"
          )
 
 JSON.parse(response)['data']
 // => [{"id"=>"374", "type"=>"dsp-upload-identifications", "links"=>{"self"=>"https://api.idol.io/api/v2/dsp-upload-identifications/<ID>"}, "attributes"=>{"created-at"=>"2012-12-13T18:50:17.000+01:00", "updated-at"=>"2018-05-30T11:30:59.837+02:00", "dsp-name"=>"Apple"}, "relationships"=>{"offers"=>{"links"=>{"self"=>"https://api.idol.io/api/v2/dsp-upload-identifications/<ID>/relationships/offers", "related"=>"https://api.idol.io/api/v2/dsp-upload-identifications/<ID>/offers"}}, "dsp"=>{"links"=>{"self"=>"https://api.idol.io/api/v2/dsp-upload-identifications/<ID>/relationships/dsp", "related"=>"https://api.idol.io/api/v2/dsp-upload-identifications/<ID>/dsp"}, "data"=>{"type"=>"dsps", "id"=>"3"}}}}...
DspUploadIdentification

Now, we have to set the distribution rules for this album. Let’s add the territories and DSPs information:

response = RestClient.post(
            "https://api.idol.io/api/v2/rights",
            {
              "data": {
                "attributes": {
                  "action": "add",
                  "user-email": "[email protected]"
                },
                "relationships": {
                  "dsps": {
                    "data": [{
                      "type": "dsps",
                      "id": "3"
                    },
                    {
                      "type": "dsps",
                      "id": "30"
                    }]
                  },
                  "territories": {
                    "data": [{
                      "type": "territories",
                      "id": "223"
                    }]
                  },
                  "distributor": {
                    "data": {
                      "type": "distributors",
                      "id": "13"
                    }
                  },
                  "distributed": {
                    "data": {
                      "type": "products",
                      "id": "214477"
                    }
                  }
                },
                "type": "rights"
              }
            }.to_json,
            "Authorization": "Bearer <token>",
            "Content-Type": "application/vnd.api+json"
           )
Right

✏️ Update and validate default Offer

When you create a product, a default Offer is associated to the Product (this default offer is not associated with any DspUploadIdentification).

You can retrieve the default Offer like this:

response = RestClient.get(
            "https://api.idol.io/api/v2/offers?filter[product_id]=214477&filter[is_default]=true",
            "Content-Type": 'application/vnd.api+json',
            "Authorization": "Bearer <token>"
            )

 offer_id   = JSON.parse(response)['data'].first['id']
 // => 377099
Offer

Then, to retrieve our product and track Price Codes, we use the following request:

RestClient.get(
            "https://api.idol.io/api/v2/distributor-price-codes",
            "Content-Type": 'application/vnd.api+json',
            "Authorization": "Bearer <token>"
            )
DistributorPriceCode

In this example, we will use the product Price Code ID 10 and track Price Code ID 7.

Now, we use this request to retrieve the product's genre:

RestClient.get(
            "https://api.idol.io/api/v2/distributor-product-subgenres",
            "Content-Type": 'application/vnd.api+json',
            "Authorization": "Bearer <token>"
            )
DistributorProductSubgenres

In this example, we will use the Product Genre ID 1.

Then, we must validate the default Offer:

response = RestClient.put(
  "https://api.idol.io/api/v2/offers/<ID>",
  {
    "data": {
      "id": "377099",
      "attributes": {
        "status": "active",
        "release-date": "2025-01-01",
        "is-default": true
      },
      "relationships": {
        "price-code": {
          "data": {
            "type": "distributor-price-codes",
            "id": "10"
          }
        },
        "track-price-code": {
          "data": {
            "type": "distributor-price-codes",
            "id": "7"
          }
        },
        "subgenre": {
          "data": {
            "type": "distributor-product-subgenres",
            "id": "1"
          }
        },
        "product":{
          "data":{
            "type": "products",
            "id": "214477"
          }
        }
      },
      "type": "offers"
    }
  }.to_json,
  "Content-Type": 'application/vnd.api+json',
  "Authorization": "Bearer <token>"
 )
Offer

🎵 Create specific Apple Music / iTunes Offer

You may want to create a specific Offer for Apple Music / iTunes, for example, to set a specific pre-order date:

response = RestClient.post(
             "https://api.idol.io/api/v2/offers",
             {
               "data": {
                 "attributes": {
                   "status": "active",
                   "preorder-date": "2024-05-01T00:00:00.000+00:00",
                   "release-date": "2025-01-01",
                   "is-default": false
                 },
                 "relationships": {
                   "product": {
                     "data": {
                       "type": "products",
                       "id": "214477"
                     }
                   },
                   "dsp-upload-identifications": {
                     "data": [{
                       "type": "dsp-upload-identifications",
                       "id": "374"
                       }]
                     }
                   },
                   "type": "offers"
                 }
               }.to_json,
             "Content-Type": 'application/vnd.api+json',
             "Authorization": "Bearer <token>"
            )

itunes_offer_id = JSON.parse(response)['data']['id']
// => 377752

✅ Update and validate the Product

Before you can send deliveries to DSPs, a product must be updated and validated. To achieve this, the product status should be changed to 'active':

response = RestClient.put(
  "https://api.idol.io/api/v2/products/214477",
  {
    "data": {
      "id": "214477",
      "attributes": {
        "status": "active"
      },
      "type": "products"
    }
  }.to_json,
  "Content-Type": 'application/vnd.api+json',
  "Authorization": "Bearer <token>"
 )

status = JSON.parse(response)['data']['attributes']['status']
// => "active"
Product

The total weight of a product - masters and visual assets included - should not exceed 50gb to guarantee deliverability

🧑‍🎤 Create DSP Artist IDs

Setting the album to an 'active' status automatically creates Artists entities, which are linked to the Product through its associated Roles. More information on this process here.

You're now able to create platform-specific artist IDs, if and when required, e.g. a Spotify Artist URI or an Apple Artist ID.

First, we need to retrieve the artist linked to our Product:

response = RestClient.get(
            "https://api.idol.io/api/v2/artists?filter[product_id]=214477
            "Content-Type": 'application/vnd.api+json',
            "Authorization": "Bearer <token>"
            )

puts JSON.parse(response)['data']

// => [{ "id": "82372", "type": "artists", "links": { "self": "https://l-api.idol.io/api/v2/artists/1495354" }, "attributes": { "name": "Artist demo", "priority": 1 }}]}...

artist_id = JSON.parse(response)['data'].first['id']
// => 82372

Now that we've retrieved the artist, we'll create an artist ID for Spotify:

response = RestClient.post(
            "https://api.idol.io/api/v2/availabilities",
            {
              "data":{
                "attributes":{
                  "external":"spotify:artist:4XGbuIJBheaKE2UGZ33am9"
                },
                "relationships":{
                  "dsp":{
                    "data":{
                      "type":"dsps",
                      "id":"30"
                    }
                  },
                  "item":{
                    "data":{
                      "type":"artists",
                      "id":"3163837"
                    }
                  }
                },
                "type":"availabilities"
              }
            }.to_json,
            "Content-Type": 'application/vnd.api+json',
            "Authorization": "Bearer <token>"
            )

And, for Apple:

response = RestClient.post(
            "https://api.idol.io/api/v2/availabilities",
            {
              "data":{
                "attributes":{
                  "external":"1798210185"
                },
                "relationships":{
                  "dsp":{
                    "data":{
                      "type":"dsps",
                      "id":"3"
                    }
                  },
                  "item":{
                    "data":{
                      "type":"artists",
                      "id":"3163837"
                    }
                  }
                },
                "type":"availabilities"
              }
            }.to_json,
            "Content-Type": 'application/vnd.api+json',
            "Authorization": "Bearer <token>"
            )

Note that DSPs like Apple and Spotify provide APIs to directly create and/or retrieve existing Artist IDs from their databases.

🖥️ Deliver to Apple and Spotify

Finally, we must create a SendTask (called a 'Delivery' in our UI) to Apple Music for this album. Setting the deliverable attribute to 'true' will allow the system to enqueue its delivery to Apple:

response = RestClient.post(
              "https://api.idol.io/api/v2/send-tasks",
              {
                "data": {
                  "attributes": {
                    "deliverable": "true",
                    "delivery-type": "delivery",
                    "priority": "normal"
                  },
                  "relationships": {
                    "product": {
                      "data": {
                        "type": "products",
                        "id": "214477"
                      }
                    },
                    "dsp-upload-identification": {
                      "data": {
                        "type": "dsp-upload-identifications",
                        "id": "374"
                        }
                      }
                    },
                    "type": "send-tasks"
                  }
                }.to_json,
              "Content-Type": 'application/vnd.api+json',
              "Authorization": "Bearer <token>"
          )

 send_task_id = JSON.parse(response)['data'][id]
 // => 7434479

We'll do the same for Spotify:

response = RestClient.post(
              "https://api.idol.io/api/v2/send-tasks",
              {
                "data": {
                  "attributes": {
                    "deliverable": "true",
                    "delivery-type": "delivery",
                    "priority": "normal"
                  },
                  "relationships": {
                    "product": {
                      "data": {
                        "type": "products",
                        "id": "214477"
                      }
                    },
                    "dsp-upload-identification": {
                      "data": {
                        "type": "dsp-upload-identifications",
                        "id": "375"
                        }
                      }
                    },
                    "type": "send-tasks"
                  }
                }.to_json,
              "Content-Type": 'application/vnd.api+json',
              "Authorization": "Bearer <token>"
          )

 send_task_id = JSON.parse(response)['data'][id]
 // => 7434480
SendTask

🚀 And your album is now ready to be delivered to Apple Music & Spotify, with US territory rights and a specific pre-order date on Apple Music / iTunes.

📡 Webhooks

To follow the status of your send_tasks, you can create a Webhook:

response = RestClient.post(
              "https://api.idol.io/api/v2/webhooks",
              {
                "data": {
                  "attributes": {
                    "action": "send_task_status_update",
                    "url": "https://yourdomain.com/callbacks?id=<id>&value=<value>&updated_at=<time>"
                  },
                  "relationships": {
                    "distributor": {
                      "data": {
                        "type": "distributors",
                        "id": "13"
                      }
                    }
                  },
                  "type": "webhooks"
                }
              }.to_json,
              "Content-Type": 'application/vnd.api+json',
              "Authorization": "Bearer <token>"
          )

We will then trigger an HTTP call on the URL:

POST https://yourdomain.com/callbacks
{
    "id": "1",
    "value": "1",
    "time": "2022-09-12 00:00:00",
    "kind": "action"
}
Webhooks

Last updated