# SoundCloud API

- Tool: Bubble
- Difficulty: Beginner
- Time required: 45 minutes
- Last updated: July 2026

## TL;DR

Connect Bubble to SoundCloud's API using a client_id URL parameter — no token exchange, no expiry timer. Mark the client_id parameter Private in Bubble's API Connector and it stays server-side automatically. Use GET /resolve to convert a SoundCloud username slug to a numeric user ID, then GET /users/{id}/tracks to build an artist catalog repeating group with track artwork and an in-page audio player wired to the stream URL.

## SoundCloud API + Bubble: independent artist apps without OAuth complexity

SoundCloud is the API of choice for Bubble apps built around independent music — artist portfolio sites, fan community platforms, music discovery tools for unsigned acts. Its v1 API has the simplest authentication model of any major audio platform: a client_id URL parameter appended to every request. No token endpoint to call, no expiry to manage, no OAuth redirect URI to configure. In Bubble's API Connector, marking the client_id as a shared Private parameter means it appends automatically to every call and never reaches the browser. The main SoundCloud-specific gotcha to understand before building: SoundCloud's internal user IDs are numeric (like `12345678`), not the friendly slugs you see in profile URLs (like `@artist-name`). The /resolve endpoint bridges this gap — give it a public SoundCloud profile URL and it returns the numeric user ID. You need that ID before you can query a user's tracks. SoundCloud v1 API also returns track metadata in a flat JSON array for user track queries, which Bubble handles well. For audio playback, the `stream_url` field on each track can be piped directly into a Bubble Audio element — letting users listen to full tracks from within your Bubble app without leaving the page.

## Before you start

- A SoundCloud account and a registered app at soundcloud.com/you/apps — the API is free to access; registration provides your client_id and client_secret
- A Bubble account (any plan, including free) — the core read integration works without Backend Workflows
- The API Connector plugin installed in your Bubble app (Plugins tab → Add plugins → API Connector by Bubble)
- The SoundCloud profile URL or username of the artist or content you want to display — you will use the /resolve endpoint to get their numeric ID

## Step-by-step guide

### 1. Register a SoundCloud app and get your client_id

Go to soundcloud.com/you/apps and log in with your SoundCloud account. Click 'Register a new application.' Fill in your app name (e.g., 'My Bubble Music App'), your website URL, and a short description of what the app does. Click 'Register.' Your new app's detail page shows your client_id and client_secret. For public data access (tracks, user profiles, play counts) — which covers most Bubble use-cases — you only need the client_id. Copy it and keep it handy. Important: SoundCloud's API terms require apps to be reviewed before commercial use. If you are building a public-facing Bubble app that uses SoundCloud data commercially, review the SoundCloud Developer API Terms at soundcloud.com/pages/developer-api-terms before launching. For internal tools and prototypes, the development key works without review.

**Expected result:** You have a SoundCloud developer app with your client_id copied and ready to use in Bubble.

### 2. Add the SoundCloud API Connector with a shared Private client_id parameter

In your Bubble editor, go to Plugins tab → Add plugins, search 'API Connector,' find the one by Bubble, and install it. Click 'API Connector' in your plugins list. Click 'Add another API.' Name it 'SoundCloud.' Set the base URL to `https://api.soundcloud.com`. Leave Authentication as 'None or self-handled.' Scroll down to 'Shared parameters' (URL parameters shared across all calls). Click 'Add a parameter.' Set the key to `client_id` and the value to your SoundCloud client_id string. Check the 'Private' checkbox — this is the key security step. With Private checked, Bubble appends the client_id to every API call from its servers, and the parameter never appears in browser-side network requests. Because client_id auto-appends to all calls, you do not need to add it again in individual call configurations. Save the API configuration before adding calls.

```
{
  "api_name": "SoundCloud",
  "base_url": "https://api.soundcloud.com",
  "shared_parameters": [
    {
      "key": "client_id",
      "value": "<your_soundcloud_client_id>",
      "private": true
    }
  ]
}
```

**Expected result:** The SoundCloud API entry appears in Bubble's API Connector with the Private client_id parameter configured as a shared parameter. The parameter auto-appends to all calls you add.

### 3. Create a /resolve call to convert a username to a numeric user ID

SoundCloud's internal user IDs are numeric integers, not the friendly slugs visible in profile URLs. For example, the profile at `soundcloud.com/thom-yorke-official` has a numeric ID like `12345678` — and all track and follow queries use the numeric ID, not the slug. If you try to query `/users/thom-yorke-official/tracks`, you will get a 404. The /resolve endpoint handles the conversion. Inside the SoundCloud API Connector entry, click 'Add a call.' Name it 'Resolve User.' Method: GET. Path: `/resolve`. Add a URL parameter: key `url`, value `<dynamic>`. Under 'Use as,' choose 'Data.' Click 'Initialize call.' In the test value for `url`, enter a real SoundCloud profile URL (e.g., `https://soundcloud.com/your-test-artist`). Bubble sends the request and receives a JSON object containing the user's full profile. The key fields to note: `id` (numeric), `username`, `full_name`, `track_count`, `followers_count`, `avatar_url`. Mark this call as Use as Data — you will use the returned `id` as input to the next call.

```
{
  "call_name": "Resolve User",
  "method": "GET",
  "path": "/resolve",
  "parameters": [
    {
      "key": "url",
      "value": "<dynamic: full SoundCloud profile URL>"
    }
  ],
  "use_as": "Data",
  "note": "client_id appended automatically from shared parameters"
}
```

**Expected result:** The Resolve User call is initialized. Bubble shows detected response fields including 'id' (the numeric user ID), 'username', 'track_count', 'avatar_url', and 'followers_count'.

### 4. Create a GET /users/{id}/tracks call and initialize it

With the numeric user ID in hand, you can fetch an artist's full track catalog. Click 'Add a call' inside the SoundCloud API Connector entry. Name it 'Get User Tracks.' Method: GET. Path: `/users/<dynamic:userId>/tracks` — in Bubble's API Connector, dynamic path segments use brackets around the parameter name; set `userId` as a dynamic parameter. Add URL parameters: `limit` (value `200` — the SoundCloud v1 API allows up to 200 tracks per request for this endpoint), `linked_partitioning` (value `true` — enables cursor-based pagination for large catalogs). Under 'Use as,' choose 'Data.' Click 'Initialize call.' Enter a real numeric user ID in the `userId` field (get it from the Resolve User call result or look up an artist ID using SoundCloud's public URL). Bubble will receive a flat JSON array of track objects. Key fields per track: `id`, `title`, `playback_count`, `likes_count` (verify field name — may be `favoritings_count` in v1), `comment_count`, `duration` (milliseconds), `created_at`, `permalink_url`, `artwork_url`, `stream_url`. Define the response as a list and mark `items` as the array root.

```
{
  "call_name": "Get User Tracks",
  "method": "GET",
  "path": "/users/<dynamic:userId>/tracks",
  "parameters": [
    { "key": "limit",               "value": "200" },
    { "key": "linked_partitioning", "value": "true" }
  ],
  "use_as": "Data",
  "key_response_fields": [
    "id",
    "title",
    "playback_count",
    "likes_count",
    "comment_count",
    "duration",
    "created_at",
    "permalink_url",
    "artwork_url",
    "stream_url"
  ]
}
```

**Expected result:** The Get User Tracks call is initialized with detected response fields. Bubble shows fields like 'title', 'playback_count', 'artwork_url', 'stream_url', and 'duration' ready to bind in a repeating group.

### 5. Build the track catalog repeating group with artwork and play stats

Add a Repeating Group element to your Bubble page. Set its type to 'SoundCloud Get User Tracks' and its data source to 'Get User Tracks from SoundCloud' — pass the numeric user ID you resolved earlier (store it in a Custom State or page URL parameter). Add a workflow on page load: 1) Call Resolve User with the target artist's URL to get their numeric ID, 2) Store the ID in a Custom State, 3) Refresh the repeating group using that ID. Inside the repeating group cell, add an Image element bound to `artwork_url` (with an empty fallback image). Add Text elements for: `title` (track name), `playback_count` (formatted as a number with commas using ':formatted as'), and `duration` (convert milliseconds using Bubble's math expression: duration / 1000 gives seconds, then format as minutes:seconds). Add a link button using `permalink_url` to open the full track on SoundCloud in a new tab. For the in-page audio player, see the next step. RapidDev's team regularly builds Bubble music apps with SoundCloud integrations — for help wiring advanced features like user follow checks or comment feeds, reach out at rapidevelopers.com/contact for a free scoping call.

**Expected result:** The track catalog repeating group loads the artist's SoundCloud tracks with artwork thumbnails, titles, play counts, and permalink links to SoundCloud.

### 6. Wire a Bubble Audio element to the SoundCloud stream URL

SoundCloud's `stream_url` field on each track object provides a direct URL to the track's audio stream — you can pipe this into a Bubble Audio element for in-page playback. Add a Bubble Audio element to your page (not inside the repeating group — use a fixed-position player at the bottom of the page, or a popup). Add a Custom State of type 'text' named `current_stream_url`. Inside the repeating group, add a Play button with a workflow: set the `current_stream_url` Custom State to 'Current cell's SoundCloud Get User Tracks stream_url'. The Audio element's source should be bound to this Custom State value. When a user clicks Play on any track, the Custom State updates and the Audio element starts playing the selected track. Important: some tracks restrict streaming even with a valid client_id. If the stream_url request returns 403, the track owner has disabled streaming for third-party apps — this is normal and not an error in your integration. Add a conditional to the Play button: 'This element is visible when Current cell's tracks stream_url is not empty.' Note: SoundCloud API v2 (`api-v2.soundcloud.com`) offers richer data but is not publicly documented as stable — use v1 for production Bubble integrations.

**Expected result:** Clicking a Play button in the track repeating group updates the Custom State, and the Audio element begins playing the selected SoundCloud track audio within the Bubble app.

## Best practices

- Mark the client_id as a shared Private parameter in Bubble's API Connector — this auto-appends it to all calls server-side and is the most important security step. Without Private, the client_id appears in browser network requests.
- Use the /resolve endpoint once and cache the numeric user ID in a Bubble Custom State or database field — calling /resolve on every page load wastes WU and adds latency when you already know the artist you are displaying.
- Handle null artwork_url with a fallback image in every Image element — approximately 20–30% of SoundCloud tracks have no cover art, and unhandled nulls create broken icon placeholders that look unprofessional.
- Add a Data Privacy rule if you store any SoundCloud-fetched data in Bubble's database — prevent other users from searching or reading track records that should be visible only to the current user.
- Avoid sub-minute API polling — SoundCloud does not publish rate limits, but frequent automated calls (e.g., polling for new tracks every 30 seconds) can trigger throttling. For 'latest tracks' displays, poll at most once per page load.
- Use SoundCloud v1 API (`api.soundcloud.com`) for production integrations — v2 (`api-v2.soundcloud.com`) offers richer data but is undocumented and subject to breaking changes without notice.
- Before launching a public-facing app, review SoundCloud's Developer API Terms at soundcloud.com/pages/developer-api-terms — commercial use of SoundCloud data may require API terms compliance beyond the basic developer registration.

## Use cases

### Artist Portfolio and Track Catalog

Build a music portfolio site in Bubble for an independent artist. Fetch their full track catalog using GET /users/{id}/tracks with limit=200, display tracks in a repeating group with artwork, play counts, and likes, and embed an audio player for listening without leaving the site.

Prompt example:

```
Create a Bubble page that loads an artist's SoundCloud track catalog into a repeating group sorted by play count descending, showing track title, artwork thumbnail, play count, and like count. Add an audio player that plays the track when clicked.
```

### Fan Community Platform with Music Embeds

Build a Bubble community where fans can browse their favorite artist's tracks, see real-time play counts and comment counts pulled from SoundCloud, and add internal comments or reactions stored in Bubble's database — combining live SoundCloud data with community features.

Prompt example:

```
Build a Bubble fan community page where each post shows a SoundCloud track embedded with its current play and like counts from the API, plus a Bubble-native comment thread stored in the database.
```

### Music Discovery and Comparison Tool

Let users search for artists or tracks by genre using SoundCloud's /search endpoint, compare track stats (plays, likes, comments), and save favorites to a Bubble database. Useful for music blogs, A&R tools, or playlist curation apps targeting independent music.

Prompt example:

```
Build a Bubble page where users search SoundCloud by genre tag, see a repeating group of matching tracks with play count and likes sorted by popularity, and can click a heart icon to save favorites to their Bubble user profile.
```

## Troubleshooting

### GET /users/{userId}/tracks returns 404

Cause: The userId is the URL slug (e.g., 'artist-name') instead of the numeric ID. SoundCloud's v1 API user-track endpoints require numeric IDs — slugs return 404.

Solution: Use the /resolve endpoint first: pass the full SoundCloud profile URL (e.g., 'https://soundcloud.com/artist-name') and extract the numeric 'id' field from the response. Store that ID in a Custom State and use it in the Get User Tracks call.

### Initialize call returns 'There was an issue setting up your call' or a 401 error

Cause: The client_id is invalid, has not been approved, or the shared Private parameter was not saved correctly. Also possible: SoundCloud API registration is pending review for your account.

Solution: Double-check the client_id value in Bubble's API Connector shared parameters — copy it directly from soundcloud.com/you/apps. Re-save the API Connector configuration and re-initialize. If your SoundCloud app registration is new, allow a few minutes for activation. Test the endpoint manually in a browser tab (the Private checkbox does not prevent testing) to confirm the client_id is accepted.

### artwork_url is null for some tracks and the Image element shows a broken icon

Cause: Tracks without a cover art image return null in the artwork_url field — this is normal for tracks where the artist did not upload cover art.

Solution: In the Bubble Image element settings, scroll to the 'Fallback image' option and set a default placeholder image (upload a generic music note graphic to Bubble's File Manager). The Image element will use the fallback automatically when artwork_url is empty.

### Audio playback returns 403 Forbidden for some tracks

Cause: The track owner has restricted streaming access for third-party apps. SoundCloud allows individual artists to disable external streaming for their tracks — this is a track-level permission set by the artist, not an error in your integration.

Solution: This is expected behavior for some tracks. Add a conditional to the Play button hiding it when stream_url returns a restricted URL. If you are building a tool specifically for one artist, check with them directly about their streaming settings in SoundCloud's settings panel.

## Frequently asked questions

### Is the SoundCloud API free to use?

Yes, the SoundCloud API is free for development and non-commercial use. You need to register at soundcloud.com/you/apps to get a client_id. For commercial or public-facing apps, review the SoundCloud Developer API Terms at soundcloud.com/pages/developer-api-terms — SoundCloud may require approval or a commercial agreement for certain use cases.

### Why do I need the numeric user ID instead of the username?

SoundCloud's v1 API identifies users internally by numeric integer IDs (e.g., 12345678), not by the slug you see in the profile URL (e.g., @artist-name). The /resolve endpoint converts a public SoundCloud URL to its numeric ID in one API call. Store the result so you do not need to resolve it on every page load.

### Can I access private SoundCloud tracks?

Not with client_id alone. Private tracks require user-level OAuth 2.0 authentication — the track owner must authorize your app and you must use a Bearer access token with the appropriate scope. This tutorial covers public track access only. For private track access, you would need to build an OAuth flow similar to the Canva or Spotify user OAuth pattern.

### What is the difference between SoundCloud v1 and v2 APIs?

SoundCloud v1 (`api.soundcloud.com`) is the publicly documented, stable API — use this for production Bubble apps. SoundCloud v2 (`api-v2.soundcloud.com`) is an undocumented internal API used by SoundCloud's own web client. v2 offers richer data and endpoints, but it can change or break without notice and is not officially supported for third-party use.

### Can I upload tracks to SoundCloud from Bubble?

Track upload requires OAuth 2.0 user authentication (the user must authorize your app) and a POST /tracks request with multipart/form-data containing the audio file. This is technically possible with Bubble's API Connector if you can handle file uploads, but it requires user OAuth setup and is significantly more complex than the read-only flow in this tutorial.

### How do I display the track duration correctly in Bubble?

SoundCloud returns duration in milliseconds. To display as minutes and seconds, use Bubble's math expressions: divide duration by 60000 for total minutes (floored), and use modulo 60000 then divide by 1000 for remaining seconds. You can also create a custom display text like '3:45' using Bubble's text concatenation with formatted number expressions.

---

Source: https://www.rapidevelopers.com/bubble-integrations/soundcloud-api
© RapidDev — https://www.rapidevelopers.com/bubble-integrations/soundcloud-api
