Skip to content

๐ŸŽฏ Complete Album Creation Tutorial

Step-by-step guide to create a complete album with all its relationships using the limbo/API

What You'll Learn

This tutorial will guide you through creating a complete music album from scratch, including all necessary relationships and validations. By the end, you'll have created:

  • โ€ข 1 Record Label - Music distributor
  • โ€ข 4 Artists - Band members with unique roles
  • โ€ข 1 Album - With complete metadata
  • โ€ข 4 Album-Artist relationships - Different roles
  • โ€ข 3 Tracks - Album songs with lyrics
  • โ€ข Country associations - Distribution territories
  • โ€ข 4 DSP associations - Streaming platforms
  • โ€ข 1 Distribution Request - Submission workflow
  • โ€ข Complete validation - Error handling examples
  • โ€ข Final verification - Query complete data

๐Ÿ“‹ Prerequisites

Before starting:

  • Valid API credentials (email and password)
  • HTTP client (Postman, Insomnia, VS Code REST Client, etc.)
  • Basic understanding of REST APIs and JSON
  • Familiarity with JSON API specification (optional but helpful)

๐Ÿ” Step 0: Authentication

Every API request requires authentication. Start by obtaining your Bearer token:

POST /oauth/token
{
  "email": "user@example.com",
  "password": "password123",
  "grant_type": "password"
}

Success Response

{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9...",
  "token_type": "Bearer",
  "expires_in": 3000
}

๐Ÿ’ก Important

Save the access_token - you'll need it for every subsequent request as: Authorization: Bearer {your_token}

๐Ÿ“‹ Step 1: Create Label

Every album needs a Label. Let's create one for our fictional band:

POST /labels
{
  "data": {
    "type": "labels",
    "attributes": {
      "name": "Label Records",
      "description": "Independent record label specializing in alternative rock"
    }
  }
}

Success Response

{
  "data": {
    "type": "labels",
    "id": "1",
    "attributes": {
      "name": "Label Records",
      "description": "Independent record label specializing in alternative rock",
      "created-at": "2024-08-19T10:00:00Z",
      "updated-at": "2024-08-19T10:00:00Z"
    }
  }
}

๐Ÿ“ Note: Save the label ID (1) - you'll need it when creating the album.

๐Ÿ‘ฅ Step 2: Create Artists

Our fictional band has 4 members. Let's create each artist:

๐ŸŽค Artist 1: Main Artist

POST /artists
{
  "data": {
    "type": "artists",
    "attributes": {
      "name": "James Carter",
      "bio": "Lead vocalist with over 10 years of experience in alternative rock"
    }
  }
}

๐ŸŽธ Artist 2: Featured Artist

{
  "data": {
    "type": "artists",
    "attributes": {
      "name": "Lisa Thompson",
      "bio": "Featured guitarist and composer, band founder. Influenced by 90s national rock"
    }
  }
}

๐ŸŽธ Artist 3: Producer

{
  "data": {
    "type": "artists",
    "attributes": {
      "name": "David Miller",
      "bio": "Producer and bassist with classical training. Responsible for the album's sound production and arrangement"
    }
  }
}

๐Ÿฅ Artist 4: Composer

{
  "data": {
    "type": "artists",
    "attributes": {
      "name": "Anna Roberts",
      "bio": "Composer and drummer with experience in rock, jazz and Latin music. Main songwriter and rhythmic foundation of the band"
    }
  }
}

๐Ÿ’ก Smart Artist Creation

The API implements intelligent find-or-create logic. If an artist with the same name already exists for your user, the system will return the existing artist instead of creating a duplicate.

๐Ÿ” Step 3: Explore Required Resources

Before creating an album, you need to identify valid IDs for required relationships. Let's explore the available options:

Required Relationships

  • โ€ข Primary Genre: GET /genres
  • โ€ข Language: GET /languages
  • โ€ข Album Format: GET /album-formats

Optional Relationships

  • โ€ข Countries: GET /countries
  • โ€ข Versions: GET /versions
  • โ€ข Artist Roles: GET /artist-roles

Example: Get Available Genres

GET /genres
{
  "data": [
    {
      "type": "genres",
      "id": "1",
      "attributes": {
        "name": "Rock"
      }
    },
    {
      "type": "genres",
      "id": "2",
      "attributes": {
        "name": "Pop"
      }
    }
  ]
}

๐Ÿ“ For This Tutorial

We'll use these common IDs that typically exist in the system:

  • Genre ID: 1 (Rock)
  • Language ID: 2 (Spanish)
  • Format ID: 1 (Album)
  • Artist Role IDs: 1 (Main), 2 (Featured), 3 (Producer), 4 (Composer and Lyricist)

๐Ÿ’ฟ Step 4: Create the Album

Now let's create our album "Whispers in the Dark" with all required attributes and relationships:

POST /albums
{
  "data": {
    "type": "albums",
    "attributes": {
      "title": "Whispers in the Dark",
      "artwork": "https://picsum.photos/3000/3000?random=1",
      "is-explicit": false,
      "original-release-date": "2024-12-15",
      "digital-release-date": "2024-12-15",
      "rights-owner-year": 2024,
      "rights-owner-name": "Label Records"
    },
    "relationships": {
      "label": {
        "data": {
          "type": "labels",
          "id": "1"
        }
      },
      "primary-genre": {
        "data": {
          "type": "genres",
          "id": "1"
        }
      },
      "language": {
        "data": {
          "type": "languages",
          "id": "2"
        }
      },
      "format": {
        "data": {
          "type": "album-formats",
          "id": "1"
        }
      }
    }
  }
}

Success Response

{
  "data": {
    "type": "albums",
    "id": "5",
    "attributes": {
      "title": "Whispers in the Dark",
      "artwork": "https://storage.s3.amazonaws.com/albums/artwork/artwork-3000x3000.jpg",
      "is-explicit": false,
      "original-release-date": "2024-12-15",
      "digital-release-date": "2024-12-15",
      "rights-owner-year": 2024,
      "rights-owner-name": "Label Records",
      "description": "First studio album by the band...",
      "created-at": "2024-08-19T10:00:00Z",
      "updated-at": "2024-08-19T10:00:00Z"
    }
  }
}

๐Ÿ“ Note: Save the album ID (5) - you'll need it for creating relationships and tracks.

๐ŸŽญ Step 5: Create Album-Artist Relationships

Now we'll associate each artist with the album, assigning different roles to each band member:

James Carter - Main Artist

{
  "data": {
    "type": "album-artists",
    "relationships": {
      "album": {
        "data": { "type": "albums", "id": "5" }
      },
      "artist": {
        "data": { "type": "artists", "id": "1" }
      },
      "artist-role": {
        "data": { "type": "artist-roles", "id": "1" }
      }
    }
  }
}

Lisa Thompson - Featured Artist

{
  "data": {
    "type": "album-artists",
    "relationships": {
      "album": {
        "data": { "type": "albums", "id": "5" }
      },
      "artist": {
        "data": { "type": "artists", "id": "2" }
      },
      "artist-role": {
        "data": { "type": "artist-roles", "id": "2" }
      }
    }
  }
}

David Miller - Producer

{
  "data": {
    "type": "album-artists",
    "relationships": {
      "album": {
        "data": { "type": "albums", "id": "5" }
      },
      "artist": {
        "data": { "type": "artists", "id": "3" }
      },
      "artist-role": {
        "data": { "type": "artist-roles", "id": "4" }
      }
    }
  }
}

Anna Roberts - Composer

{
  "data": {
    "type": "album-artists",
    "relationships": {
      "album": {
        "data": { "type": "albums", "id": "5" }
      },
      "artist": {
        "data": { "type": "artists", "id": "4" }
      },
      "artist-role": {
        "data": { "type": "artist-roles", "id": "5" }
      }
    }
  }
}

Anna Roberts - Lyricist

{
  "data": {
    "type": "album-artists",
    "relationships": {
      "album": {
        "data": { "type": "albums", "id": "5" }
      },
      "artist": {
        "data": { "type": "artists", "id": "4" }
      },
      "artist-role": {
        "data": { "type": "artist-roles", "id": "6" }
      }
    }
  }
}

All Album-Artist requests use the same endpoint:

POST /album-artists

๐ŸŒ Step 6: Add Distribution Countries

Let's add countries where this album will be distributed. We'll use the special relationships endpoint:

POST /albums/5/relationships/countries
{
  "data": [
    {
      "type": "countries",
      "id": "1"
    },
    {
      "type": "countries",
      "id": "9"
    },
    {
      "type": "countries",
      "id": "39"
    }
  ]
}

๐Ÿ’ก Important

Use the /relationships/countries endpoint (not /countries) for adding, updating, or removing country associations.

๐ŸŽฏ Step 7: Associate DSPs to Album

Before creating a distribution request, we need to associate the album with Digital Service Providers (DSPs). This tells the system which platforms should receive this album:

Spotify

{
  "data": {
    "type": "album-dsps",
    "relationships": {
      "album": {
        "data": { "type": "albums", "id": "5" }
      },
      "dsp": {
        "data": { "type": "dsps", "id": "1" }
      }
    }
  }
}

Apple Music

{
  "data": {
    "type": "album-dsps",
    "relationships": {
      "album": {
        "data": { "type": "albums", "id": "5" }
      },
      "dsp": {
        "data": { "type": "dsps", "id": "2" }
      }
    }
  }
}

Amazon Music

{
  "data": {
    "type": "album-dsps",
    "relationships": {
      "album": {
        "data": { "type": "albums", "id": "5" }
      },
      "dsp": {
        "data": { "type": "dsps", "id": "3" }
      }
    }
  }
}

YouTube Music

{
  "data": {
    "type": "album-dsps",
    "relationships": {
      "album": {
        "data": { "type": "albums", "id": "5" }
      },
      "dsp": {
        "data": { "type": "dsps", "id": "4" }
      }
    }
  }
}

All Album-DSP requests use the same endpoint:

POST /album-dsps

๐Ÿ“ For This Tutorial

Common DSP IDs used in this tutorial:

  • DSP ID 1: Spotify
  • DSP ID 2: Apple Music
  • DSP ID 3: Amazon Music
  • DSP ID 4: YouTube Music

๐ŸŽต Step 8: Create Album Tracks

Now let's add 3 tracks to our album. Each track will have unique characteristics:

๐ŸŽต Track 1: "City Lights" (First Single)

POST /tracks
{
  "data": {
    "type": "tracks",
    "attributes": {
      "title": "City Lights",
      "is-explicit": false,
      "rights-owner-year": 2024,
      "rights-owner-name": "Label Records",
      "order": 1,
      "full-audiofile-url": "https://storage.example.com/tracks/audio1.wav"
    },
    "relationships": {
      "albums": {
        "data": [
          {
            "type": "albums",
            "id": "5"
          }
        ]
      },
      "primary-genre": {
        "data": {
          "type": "genres",
          "id": "1"
        }
      },
      "language": {
        "data": {
          "type": "languages",
          "id": "2"
        }
      }
    }
  }
}

๐ŸŽต Track 2: "Asphalt Memories" (Melancholic)

{
  "data": {
    "type": "tracks",
    "attributes": {
      "title": "Asphalt Memories",
      "is-explicit": false,
      "rights-owner-year": 2024,
      "rights-owner-name": "Label Records",
      "order": 2,
      "full-audiofile-url": "https://storage.example.com/tracks/audio2.wav"
    },
    "relationships": {
      "albums": {
        "data": [{ "type": "albums", "id": "5" }]
      },
      "primary-genre": {
        "data": { "type": "genres", "id": "1" }
      },
      "language": {
        "data": { "type": "languages", "id": "2" }
      }
    }
  }
}

๐ŸŽต Track 3: "Silent Revolution" (Explicit Content)

{
  "data": {
    "type": "tracks",
    "attributes": {
      "title": "Silent Revolution",
      "is-explicit": true,
      "rights-owner-year": 2024,
      "rights-owner-name": "Label Records",
      "order": 3,
      "full-audiofile-url": "https://storage.example.com/tracks/audio3.wav"
    },
    "relationships": {
      "albums": {
        "data": [{ "type": "albums", "id": "5" }]
      },
      "primary-genre": {
        "data": { "type": "genres", "id": "1" }
      },
      "language": {
        "data": { "type": "languages", "id": "2" }
      }
    }
  }
}

โš ๏ธ Explicit Content

Track 3 demonstrates explicit content handling. Set is-explicit: true for tracks containing explicit language or mature themes.

๐Ÿ” Step 8.5: Validate Album for Distribution

Why Validate Before Distribution?

Before creating a distribution request, it's crucial to validate that your album meets all the requirements for distribution. This prevents failed submissions and ensures your album will be accepted by digital service providers (DSPs).

โœ… Benefits of Validation

  • โ€ข Early detection of missing data
  • โ€ข Prevents failed distribution requests
  • โ€ข Saves time and API calls
  • โ€ข Ensures compliance with DSP requirements

โŒ Risks of Skipping Validation

  • โ€ข Distribution requests may be rejected
  • โ€ข Album status changes may fail
  • โ€ข Wasted processing resources
  • โ€ข Delays in getting music online

๐Ÿ“‹ Validation Request

Use the album validation endpoint to check if your album is ready for distribution:

GET /albums/{album_id}/validate

Replace {album_id} with your actual album ID

๐Ÿ“ค Validation Responses

โœ… Album Ready for Distribution

When your album passes all validation checks:

HTTP 200 OK

{
  "jsonapi": {
    "version": "1.0"
  },
  "data": {
    "type": "album-distribution-check",
    "id": "1234",
    "attributes": {
      "valid_for_distribution": true,
      "message": "Album is ready for distribution"
    }
  }
}

Meaning: Your album is complete and ready to create distribution requests. You can proceed to Step 9.

โŒ Album Needs Corrections

When validation fails, you'll receive detailed error information:

HTTP 200 OK (with errors)

{
  "jsonapi": {
    "version": "1.0"
  },
  "data": {
    "type": "album-distribution-check",
    "id": "1234",
    "attributes": {
      "valid_for_distribution": false,
      "message": "Album is not ready for distribution",
      "errors": [
        {
          "status": "422",
          "title": "Validation error",
          "detail": [
            "Track 'Song Title': Track requires at least one composer",
            "Track 'Another Song': Track requires at least one lyricist",
            "Album artist 'Artist Name' with role 'composer' must also be assigned to at least one track with the same role"
          ]
        }
      ]
    }
  }
}

Meaning: Your album has issues that must be fixed before distribution. The errors array contains specific problems to address.

๐Ÿ’ก Pro Tip

Always validate your album before creating distribution requests. This saves time and prevents failed submissions that could affect your album's distribution status.

๐Ÿ“ค Step 9: Create Distribution Request

Finally, let's create a distribution request to submit our completed album for distribution to all the configured DSPs and countries:

POST /distribution-requests
{
  "data": {
    "type": "distribution-requests",
    "attributes": {
      "request-type": "delivery"
    },
    "relationships": {
      "album": {
        "data": {
          "type": "albums",
          "id": "5"
        }
      }
    }
  }
}

Success Response

{
  "data": {
    "type": "distribution-requests",
    "id": "1",
    "attributes": {
      "date": "2024-08-21",
      "request-type": "delivery",
      "status": "pending",
      "created-at": "2024-08-21T12:00:00Z",
      "updated-at": "2024-08-21T12:00:00Z"
    },
    "relationships": {
      "album": {
        "data": {
          "type": "albums",
          "id": "5"
        }
      }
    }
  }
}

๐Ÿ”„ What Happens Automatically

When you create a distribution request, the system automatically:

  • Assigns the request to the authenticated user
  • Sets the date to current date
  • Sets status to "pending"
  • Copies all Album-DSP relationships to the distribution request
  • Updates the album status to indicate it's in distribution
  • Creates a distribution batch for processing

๐Ÿ” Step 10: Final Verification

Let's verify everything was created correctly by querying the complete album with all its relationships:

GET /albums/5?include=label,primary-genre,language,format,countries,artists,tracks,dsps

Expected Result

You should see your album with:

  • โœ… Label relationship (Label Records)
  • โœ… 4 Artist relationships with different roles
  • โœ… 3 Tracks in order (1, 2, 3)
  • โœ… Multiple country associations
  • โœ… 4 DSP associations (Spotify, Apple Music, Amazon, YouTube)
  • โœ… Genre, language, and format relationships
  • โœ… Active distribution request

๐Ÿ“Š Additional Verification Queries

  • โ€ข GET /album-artists?include=album,artist,artist-role
  • โ€ข GET /tracks?include=albums&sort=order
  • โ€ข GET /labels/1?include=albums
  • โ€ข GET /albums/5/countries
  • โ€ข GET /album-dsps?include=album,dsp
  • โ€ข GET /distribution-requests?include=album

๐Ÿงช Test Validations

Try these to see error handling:

  • โ€ข Create album without title (should fail)
  • โ€ข Create track without title (should fail)
  • โ€ข Create duplicate album-artist (should fail)
  • โ€ข Create duplicate distribution request (should fail)
  • โ€ข Use invalid relationship IDs (should fail)

๐ŸŽ‰ Congratulations!

What You've Accomplished

You've successfully created a complete music album using the limbo/API! Here's what you built:

๐ŸŽต "Whispers in the Dark" Album

  • โ€ข Complete metadata and artwork
  • โ€ข Associated with Label Records label
  • โ€ข Rock genre, Spanish language
  • โ€ข Multi-country distribution
  • โ€ข 4 major DSP associations
  • โ€ข Full rights management information
  • โ€ข Active distribution request

๐ŸŽญ Complete Band Setup

  • โ€ข 4 artists with unique biographies
  • โ€ข Different roles per artist
  • โ€ข 3 diverse tracks with lyrics
  • โ€ข Proper track ordering
  • โ€ข Explicit content handling
  • โ€ข Ready for distribution workflow

๐Ÿš€ Next Steps

  • โ€ข Monitor your distribution request status and approvals
  • โ€ข Explore delivery tracking and DSP-specific metadata
  • โ€ข Add more tracks or create additional albums
  • โ€ข Experiment with different DSP configurations
  • โ€ข Try the advanced filtering and search features
  • โ€ข Implement error handling in your applications
  • โ€ข Explore the analytics and reporting endpoints