soundcloud-api-ts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,249 @@
1
+ # soundcloud-api-client
2
+
3
+ A TypeScript client for the SoundCloud API. Zero dependencies, uses native `fetch` (Node 18+).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install soundcloud-api-client
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```ts
14
+ import { SoundCloudClient } from "soundcloud-api-client";
15
+
16
+ const sc = new SoundCloudClient({
17
+ clientId: "your-client-id",
18
+ clientSecret: "your-client-secret",
19
+ redirectUri: "https://yourapp.com/callback",
20
+ });
21
+
22
+ // Get a client token and store it
23
+ const token = await sc.auth.getClientToken();
24
+ sc.setToken(token.access_token);
25
+
26
+ // Now all calls use the stored token automatically
27
+ const results = await sc.search.tracks("electronic");
28
+ const me = await sc.me.getMe();
29
+ const track = await sc.tracks.getTrack(123456);
30
+ const streams = await sc.tracks.getStreams(123456);
31
+ ```
32
+
33
+ ## OAuth 2.0 Flow
34
+
35
+ ```ts
36
+ import { SoundCloudClient, generateCodeVerifier, generateCodeChallenge } from "soundcloud-api-client";
37
+
38
+ const sc = new SoundCloudClient({
39
+ clientId: "...",
40
+ clientSecret: "...",
41
+ redirectUri: "https://yourapp.com/callback",
42
+ // Optional: auto-refresh tokens on 401
43
+ onTokenRefresh: async (client) => {
44
+ const newToken = await client.auth.refreshUserToken(client.refreshToken!);
45
+ // Persist newToken to your DB here
46
+ return newToken;
47
+ },
48
+ });
49
+
50
+ // 1. Generate PKCE pair (for public clients / SPAs)
51
+ const verifier = generateCodeVerifier();
52
+ const challenge = await generateCodeChallenge(verifier);
53
+
54
+ // 2. Build authorization URL and redirect the user
55
+ const authUrl = sc.auth.getAuthorizationUrl({ state: "random", codeChallenge: challenge });
56
+ // → redirect user to authUrl
57
+
58
+ // 3. Exchange the code for tokens (in your callback handler)
59
+ const token = await sc.auth.getUserToken(code, verifier);
60
+ sc.setToken(token.access_token, token.refresh_token);
61
+
62
+ // 4. Use the API — token is used automatically
63
+ const me = await sc.me.getMe();
64
+ const tracks = await sc.search.tracks("lofi beats");
65
+
66
+ // 5. Override token per-call if needed
67
+ const otherMe = await sc.me.getMe({ token: "other-users-token" });
68
+
69
+ // 6. Refresh manually if needed
70
+ const refreshed = await sc.auth.refreshUserToken(token.refresh_token);
71
+ sc.setToken(refreshed.access_token, refreshed.refresh_token);
72
+
73
+ // 7. Sign out
74
+ await sc.auth.signOut(token.access_token);
75
+ sc.clearToken();
76
+ ```
77
+
78
+ ## Client Class
79
+
80
+ The `SoundCloudClient` class organizes all endpoints into namespaces. Token is resolved automatically when `setToken()` has been called. Override per-call via `{ token: "..." }` options object.
81
+
82
+ ```ts
83
+ const sc = new SoundCloudClient({ clientId, clientSecret, redirectUri });
84
+
85
+ // Token management
86
+ sc.setToken(accessToken, refreshToken?)
87
+ sc.clearToken()
88
+ sc.accessToken // getter
89
+ sc.refreshToken // getter
90
+
91
+ // Auth
92
+ sc.auth.getAuthorizationUrl({ state?, codeChallenge? })
93
+ sc.auth.getClientToken()
94
+ sc.auth.getUserToken(code, codeVerifier?)
95
+ sc.auth.refreshUserToken(refreshToken)
96
+ sc.auth.signOut(accessToken)
97
+
98
+ // Me (authenticated user) — primary params first, options last
99
+ sc.me.getMe(options?)
100
+ sc.me.getActivities(limit?, options?)
101
+ sc.me.getActivitiesOwn(limit?, options?)
102
+ sc.me.getActivitiesTracks(limit?, options?)
103
+ sc.me.getLikesTracks(limit?, options?)
104
+ sc.me.getLikesPlaylists(limit?, options?)
105
+ sc.me.getFollowings(limit?, options?)
106
+ sc.me.getFollowingsTracks(limit?, options?)
107
+ sc.me.follow(userUrn, options?)
108
+ sc.me.unfollow(userUrn, options?)
109
+ sc.me.getFollowers(limit?, options?)
110
+ sc.me.getPlaylists(limit?, options?)
111
+ sc.me.getTracks(limit?, options?)
112
+
113
+ // Users
114
+ sc.users.getUser(userId, options?)
115
+ sc.users.getFollowers(userId, limit?, options?)
116
+ sc.users.getFollowings(userId, limit?, options?)
117
+ sc.users.getTracks(userId, limit?, options?)
118
+ sc.users.getPlaylists(userId, limit?, options?)
119
+ sc.users.getLikesTracks(userId, limit?, cursor?, options?)
120
+ sc.users.getLikesPlaylists(userId, limit?, options?)
121
+ sc.users.getWebProfiles(userId, options?)
122
+
123
+ // Tracks
124
+ sc.tracks.getTrack(trackId, options?)
125
+ sc.tracks.getStreams(trackId, options?)
126
+ sc.tracks.getComments(trackId, limit?, options?)
127
+ sc.tracks.createComment(trackId, body, timestamp?, options?)
128
+ sc.tracks.getLikes(trackId, limit?, options?)
129
+ sc.tracks.getReposts(trackId, limit?, options?)
130
+ sc.tracks.getRelated(trackId, limit?, options?)
131
+ sc.tracks.update(trackId, params, options?)
132
+ sc.tracks.delete(trackId, options?)
133
+
134
+ // Playlists
135
+ sc.playlists.getPlaylist(playlistId, options?)
136
+ sc.playlists.getTracks(playlistId, limit?, offset?, options?)
137
+ sc.playlists.getReposts(playlistId, limit?, options?)
138
+ sc.playlists.create(params, options?)
139
+ sc.playlists.update(playlistId, params, options?)
140
+ sc.playlists.delete(playlistId, options?)
141
+
142
+ // Likes
143
+ sc.likes.likeTrack(trackId, options?)
144
+ sc.likes.unlikeTrack(trackId, options?)
145
+ sc.likes.likePlaylist(playlistId, options?)
146
+ sc.likes.unlikePlaylist(playlistId, options?)
147
+
148
+ // Reposts
149
+ sc.reposts.repostTrack(trackId, options?)
150
+ sc.reposts.unrepostTrack(trackId, options?)
151
+ sc.reposts.repostPlaylist(playlistId, options?)
152
+ sc.reposts.unrepostPlaylist(playlistId, options?)
153
+
154
+ // Search
155
+ sc.search.tracks(query, pageNumber?, options?)
156
+ sc.search.users(query, pageNumber?, options?)
157
+ sc.search.playlists(query, pageNumber?, options?)
158
+
159
+ // Resolve
160
+ sc.resolve.resolveUrl(url, options?)
161
+ ```
162
+
163
+ Where `options` is `{ token?: string }` — only needed to override the stored token.
164
+
165
+ ## Standalone Functions
166
+
167
+ Every endpoint is also available as a standalone function (token is always required):
168
+
169
+ ```ts
170
+ import {
171
+ getClientToken, getUserToken, getAuthorizationUrl,
172
+ generateCodeVerifier, generateCodeChallenge,
173
+ getMe, searchTracks,
174
+ } from "soundcloud-api-client";
175
+
176
+ const token = await getClientToken("clientId", "clientSecret");
177
+ const me = await getMe(token.access_token);
178
+ const tracks = await searchTracks(token.access_token, "lo-fi");
179
+
180
+ // Build auth URL
181
+ const authUrl = getAuthorizationUrl("clientId", "https://yourapp.com/callback", { state: "xyz" });
182
+ ```
183
+
184
+ ## Types
185
+
186
+ All response types match the SoundCloud API spec:
187
+
188
+ ```ts
189
+ import type {
190
+ SoundCloudUser,
191
+ SoundCloudMe,
192
+ SoundCloudTrack,
193
+ SoundCloudPlaylist,
194
+ SoundCloudComment,
195
+ SoundCloudToken,
196
+ SoundCloudStreams,
197
+ SoundCloudWebProfile,
198
+ SoundCloudActivity,
199
+ SoundCloudActivitiesResponse,
200
+ SoundCloudPaginatedResponse,
201
+ TokenOption,
202
+ } from "soundcloud-api-client/types";
203
+ ```
204
+
205
+ ## PKCE (Proof Key for Code Exchange)
206
+
207
+ For public clients (SPAs, mobile apps), use PKCE:
208
+
209
+ ```ts
210
+ import { generateCodeVerifier, generateCodeChallenge } from "soundcloud-api-client";
211
+
212
+ const verifier = generateCodeVerifier();
213
+ const challenge = await generateCodeChallenge(verifier);
214
+
215
+ // Pass challenge when building auth URL
216
+ const url = sc.auth.getAuthorizationUrl({ codeChallenge: challenge });
217
+
218
+ // Pass verifier when exchanging the code
219
+ const token = await sc.auth.getUserToken(code, verifier);
220
+ ```
221
+
222
+ ## Pagination
223
+
224
+ Paginated endpoints return `SoundCloudPaginatedResponse<T>`:
225
+
226
+ ```ts
227
+ interface SoundCloudPaginatedResponse<T> {
228
+ collection: T[];
229
+ next_href: string; // URL for next page
230
+ }
231
+ ```
232
+
233
+ ## Utilities
234
+
235
+ ```ts
236
+ import { getSoundCloudWidgetUrl } from "soundcloud-api-client";
237
+
238
+ // Generate a SoundCloud embed widget URL
239
+ const widgetUrl = getSoundCloudWidgetUrl(trackId);
240
+ ```
241
+
242
+ ## Requirements
243
+
244
+ - Node.js 18+ (uses native `fetch`)
245
+ - SoundCloud API credentials
246
+
247
+ ## License
248
+
249
+ MIT
@@ -0,0 +1,440 @@
1
+ import { SoundCloudTrack, SoundCloudPlaylist, SoundCloudToken, SoundCloudMe, SoundCloudActivitiesResponse, SoundCloudPaginatedResponse, SoundCloudUser, SoundCloudWebProfile, SoundCloudStreams, SoundCloudComment } from './types/index.mjs';
2
+ export { SoundCloudActivity, SoundCloudCommentUser, SoundCloudQuota, SoundCloudSubscription, SoundCloudSubscriptionProduct } from './types/index.mjs';
3
+
4
+ interface RequestOptions {
5
+ path: string;
6
+ method: "GET" | "POST" | "PUT" | "DELETE";
7
+ token?: string;
8
+ body?: Record<string, unknown> | FormData | URLSearchParams;
9
+ contentType?: string;
10
+ }
11
+ interface AutoRefreshContext {
12
+ getToken: () => string | undefined;
13
+ onTokenRefresh?: () => Promise<{
14
+ access_token: string;
15
+ refresh_token?: string;
16
+ }>;
17
+ setToken: (accessToken: string, refreshToken?: string) => void;
18
+ }
19
+ /**
20
+ * Make a request to the SoundCloud API using native fetch.
21
+ * Returns parsed JSON, or for 302 redirects returns the Location header.
22
+ */
23
+ declare function scFetch<T>(options: RequestOptions, refreshCtx?: AutoRefreshContext): Promise<T>;
24
+
25
+ interface UpdateTrackParams {
26
+ title?: string;
27
+ description?: string;
28
+ genre?: string;
29
+ tag_list?: string;
30
+ sharing?: "public" | "private";
31
+ downloadable?: boolean;
32
+ purchase_url?: string;
33
+ purchase_title?: string;
34
+ release?: string;
35
+ release_day?: number;
36
+ release_month?: number;
37
+ release_year?: number;
38
+ label_name?: string;
39
+ license?: string;
40
+ isrc?: string;
41
+ bpm?: number;
42
+ key_signature?: string;
43
+ }
44
+ /** PUT /tracks/:id — updates a track's metadata */
45
+ declare const updateTrack: (token: string, trackId: string | number, params: UpdateTrackParams) => Promise<SoundCloudTrack>;
46
+
47
+ interface CreatePlaylistParams {
48
+ title: string;
49
+ description?: string;
50
+ sharing?: "public" | "private";
51
+ tracks?: {
52
+ urn: string;
53
+ }[];
54
+ ean?: string;
55
+ genre?: string;
56
+ label_name?: string;
57
+ license?: string;
58
+ permalink?: string;
59
+ purchase_title?: string;
60
+ purchase_url?: string;
61
+ release?: string;
62
+ release_date?: string;
63
+ set_type?: "album" | "playlist";
64
+ tag_list?: string;
65
+ }
66
+ /** POST /playlists — creates a playlist */
67
+ declare const createPlaylist: (token: string, params: CreatePlaylistParams) => Promise<SoundCloudPlaylist>;
68
+
69
+ interface UpdatePlaylistParams {
70
+ title?: string;
71
+ description?: string;
72
+ sharing?: "public" | "private";
73
+ tracks?: {
74
+ urn: string;
75
+ }[];
76
+ ean?: string;
77
+ genre?: string;
78
+ label_name?: string;
79
+ license?: string;
80
+ permalink?: string;
81
+ purchase_title?: string;
82
+ purchase_url?: string;
83
+ release?: string;
84
+ release_date?: string;
85
+ set_type?: "album" | "playlist";
86
+ tag_list?: string;
87
+ }
88
+ /** PUT /playlists/:id — updates a playlist */
89
+ declare const updatePlaylist: (token: string, playlistId: string | number, params: UpdatePlaylistParams) => Promise<SoundCloudPlaylist>;
90
+
91
+ interface SoundCloudClientConfig {
92
+ clientId: string;
93
+ clientSecret: string;
94
+ redirectUri?: string;
95
+ /** Called automatically when a request returns 401. Return new tokens to retry. */
96
+ onTokenRefresh?: (client: SoundCloudClient) => Promise<SoundCloudToken>;
97
+ }
98
+ /** Optional token override, passed as the last parameter to client methods. */
99
+ interface TokenOption {
100
+ token?: string;
101
+ }
102
+ /** Resolve a token: use explicit override, fall back to stored, or throw. */
103
+ type TokenGetter = () => string | undefined;
104
+ declare class SoundCloudClient {
105
+ private config;
106
+ private _accessToken?;
107
+ private _refreshToken?;
108
+ auth: SoundCloudClient.Auth;
109
+ me: SoundCloudClient.Me;
110
+ users: SoundCloudClient.Users;
111
+ tracks: SoundCloudClient.Tracks;
112
+ playlists: SoundCloudClient.Playlists;
113
+ search: SoundCloudClient.Search;
114
+ resolve: SoundCloudClient.Resolve;
115
+ likes: SoundCloudClient.Likes;
116
+ reposts: SoundCloudClient.Reposts;
117
+ constructor(config: SoundCloudClientConfig);
118
+ /** Store an access token (and optionally refresh token) on this client instance. */
119
+ setToken(accessToken: string, refreshToken?: string): void;
120
+ /** Clear stored tokens. */
121
+ clearToken(): void;
122
+ /** Get the currently stored access token, if any. */
123
+ get accessToken(): string | undefined;
124
+ /** Get the currently stored refresh token, if any. */
125
+ get refreshToken(): string | undefined;
126
+ }
127
+ declare namespace SoundCloudClient {
128
+ class Auth {
129
+ private config;
130
+ constructor(config: SoundCloudClientConfig);
131
+ /** Build the authorization URL to redirect users to SoundCloud's login. */
132
+ getAuthorizationUrl(options?: {
133
+ state?: string;
134
+ codeChallenge?: string;
135
+ }): string;
136
+ /** POST /oauth2/token — client_credentials grant */
137
+ getClientToken(): Promise<SoundCloudToken>;
138
+ /** POST /oauth2/token — authorization_code grant */
139
+ getUserToken(code: string, codeVerifier?: string): Promise<SoundCloudToken>;
140
+ /** POST /oauth2/token — refresh_token grant */
141
+ refreshUserToken(refreshToken: string): Promise<SoundCloudToken>;
142
+ /**
143
+ * POST /sign-out — invalidates session.
144
+ *
145
+ * **Note:** This hits `https://secure.soundcloud.com`, NOT the regular
146
+ * `api.soundcloud.com` host used by all other endpoints.
147
+ */
148
+ signOut(accessToken: string): Promise<void>;
149
+ }
150
+ class Me {
151
+ private getToken;
152
+ private refreshCtx?;
153
+ constructor(getToken: TokenGetter, refreshCtx?: AutoRefreshContext | undefined);
154
+ private fetch;
155
+ /** GET /me */
156
+ getMe(options?: TokenOption): Promise<SoundCloudMe>;
157
+ /** GET /me/activities */
158
+ getActivities(limit?: number, options?: TokenOption): Promise<SoundCloudActivitiesResponse>;
159
+ /** GET /me/activities/all/own */
160
+ getActivitiesOwn(limit?: number, options?: TokenOption): Promise<SoundCloudActivitiesResponse>;
161
+ /** GET /me/activities/tracks */
162
+ getActivitiesTracks(limit?: number, options?: TokenOption): Promise<SoundCloudActivitiesResponse>;
163
+ /** GET /me/likes/tracks */
164
+ getLikesTracks(limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
165
+ /** GET /me/likes/playlists */
166
+ getLikesPlaylists(limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
167
+ /** GET /me/followings */
168
+ getFollowings(limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
169
+ /** GET /me/followings/tracks */
170
+ getFollowingsTracks(limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
171
+ /** PUT /me/followings/:user_urn — follow a user */
172
+ follow(userUrn: string | number, options?: TokenOption): Promise<void>;
173
+ /** DELETE /me/followings/:user_urn — unfollow a user */
174
+ unfollow(userUrn: string | number, options?: TokenOption): Promise<void>;
175
+ /** GET /me/followers */
176
+ getFollowers(limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
177
+ /** GET /me/playlists */
178
+ getPlaylists(limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
179
+ /** GET /me/tracks */
180
+ getTracks(limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
181
+ }
182
+ class Users {
183
+ private getToken;
184
+ private refreshCtx?;
185
+ constructor(getToken: TokenGetter, refreshCtx?: AutoRefreshContext | undefined);
186
+ private fetch;
187
+ /** GET /users/:id */
188
+ getUser(userId: string | number, options?: TokenOption): Promise<SoundCloudUser>;
189
+ /** GET /users/:id/followers */
190
+ getFollowers(userId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
191
+ /** GET /users/:id/followings */
192
+ getFollowings(userId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
193
+ /** GET /users/:id/tracks */
194
+ getTracks(userId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
195
+ /** GET /users/:id/playlists */
196
+ getPlaylists(userId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
197
+ /** GET /users/:id/likes/tracks */
198
+ getLikesTracks(userId: string | number, limit?: number, cursor?: string, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
199
+ /** GET /users/:id/likes/playlists */
200
+ getLikesPlaylists(userId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
201
+ /** GET /users/:id/web-profiles */
202
+ getWebProfiles(userId: string | number, options?: TokenOption): Promise<SoundCloudWebProfile[]>;
203
+ }
204
+ class Tracks {
205
+ private getToken;
206
+ private refreshCtx?;
207
+ constructor(getToken: TokenGetter, refreshCtx?: AutoRefreshContext | undefined);
208
+ private fetch;
209
+ /** GET /tracks/:id */
210
+ getTrack(trackId: string | number, options?: TokenOption): Promise<SoundCloudTrack>;
211
+ /** GET /tracks/:id/streams */
212
+ getStreams(trackId: string | number, options?: TokenOption): Promise<SoundCloudStreams>;
213
+ /** GET /tracks/:id/comments */
214
+ getComments(trackId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudComment>>;
215
+ /** POST /tracks/:id/comments */
216
+ createComment(trackId: string | number, body: string, timestamp?: number, options?: TokenOption): Promise<SoundCloudComment>;
217
+ /** GET /tracks/:id/favoriters */
218
+ getLikes(trackId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
219
+ /** GET /tracks/:id/reposters */
220
+ getReposts(trackId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
221
+ /** GET /tracks/:id/related */
222
+ getRelated(trackId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudTrack[]>;
223
+ /** PUT /tracks/:id — update track metadata */
224
+ update(trackId: string | number, params: UpdateTrackParams, options?: TokenOption): Promise<SoundCloudTrack>;
225
+ /** DELETE /tracks/:id */
226
+ delete(trackId: string | number, options?: TokenOption): Promise<void>;
227
+ }
228
+ class Playlists {
229
+ private getToken;
230
+ private refreshCtx?;
231
+ constructor(getToken: TokenGetter, refreshCtx?: AutoRefreshContext | undefined);
232
+ private fetch;
233
+ /** GET /playlists/:id */
234
+ getPlaylist(playlistId: string | number, options?: TokenOption): Promise<SoundCloudPlaylist>;
235
+ /** GET /playlists/:id/tracks */
236
+ getTracks(playlistId: string | number, limit?: number, offset?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
237
+ /** GET /playlists/:id/reposters */
238
+ getReposts(playlistId: string | number, limit?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
239
+ /** POST /playlists — create a playlist */
240
+ create(params: CreatePlaylistParams, options?: TokenOption): Promise<SoundCloudPlaylist>;
241
+ /** PUT /playlists/:id — update a playlist */
242
+ update(playlistId: string | number, params: UpdatePlaylistParams, options?: TokenOption): Promise<SoundCloudPlaylist>;
243
+ /** DELETE /playlists/:id */
244
+ delete(playlistId: string | number, options?: TokenOption): Promise<void>;
245
+ }
246
+ class Search {
247
+ private getToken;
248
+ private refreshCtx?;
249
+ constructor(getToken: TokenGetter, refreshCtx?: AutoRefreshContext | undefined);
250
+ private fetch;
251
+ /** GET /tracks?q= */
252
+ tracks(query: string, pageNumber?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
253
+ /** GET /users?q= */
254
+ users(query: string, pageNumber?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
255
+ /** GET /playlists?q= */
256
+ playlists(query: string, pageNumber?: number, options?: TokenOption): Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
257
+ }
258
+ class Resolve {
259
+ private getToken;
260
+ private refreshCtx?;
261
+ constructor(getToken: TokenGetter, refreshCtx?: AutoRefreshContext | undefined);
262
+ private fetch;
263
+ /** GET /resolve?url= */
264
+ resolveUrl(url: string, options?: TokenOption): Promise<string>;
265
+ }
266
+ class Likes {
267
+ private getToken;
268
+ private refreshCtx?;
269
+ constructor(getToken: TokenGetter, refreshCtx?: AutoRefreshContext | undefined);
270
+ private fetch;
271
+ /** POST /likes/tracks/:id */
272
+ likeTrack(trackId: string | number, options?: TokenOption): Promise<boolean>;
273
+ /** DELETE /likes/tracks/:id */
274
+ unlikeTrack(trackId: string | number, options?: TokenOption): Promise<boolean>;
275
+ /** POST /likes/playlists/:id */
276
+ likePlaylist(playlistId: string | number, options?: TokenOption): Promise<boolean>;
277
+ /** DELETE /likes/playlists/:id */
278
+ unlikePlaylist(playlistId: string | number, options?: TokenOption): Promise<boolean>;
279
+ }
280
+ class Reposts {
281
+ private getToken;
282
+ private refreshCtx?;
283
+ constructor(getToken: TokenGetter, refreshCtx?: AutoRefreshContext | undefined);
284
+ private fetch;
285
+ /** POST /reposts/tracks/:id */
286
+ repostTrack(trackId: string | number, options?: TokenOption): Promise<boolean>;
287
+ /** DELETE /reposts/tracks/:id */
288
+ unrepostTrack(trackId: string | number, options?: TokenOption): Promise<boolean>;
289
+ /** POST /reposts/playlists/:id */
290
+ repostPlaylist(playlistId: string | number, options?: TokenOption): Promise<boolean>;
291
+ /** DELETE /reposts/playlists/:id */
292
+ unrepostPlaylist(playlistId: string | number, options?: TokenOption): Promise<boolean>;
293
+ }
294
+ }
295
+
296
+ declare const getClientToken: (clientId: string, clientSecret: string) => Promise<SoundCloudToken>;
297
+
298
+ declare const getUserToken: (clientId: string, clientSecret: string, redirectUri: string, code: string, codeVerifier?: string) => Promise<SoundCloudToken>;
299
+
300
+ declare const refreshUserToken: (clientId: string, clientSecret: string, redirectUri: string, refreshToken: string) => Promise<SoundCloudToken>;
301
+
302
+ /**
303
+ * POST /sign-out — invalidates session associated with current token.
304
+ *
305
+ * **Note:** This hits `https://secure.soundcloud.com`, NOT the regular
306
+ * `api.soundcloud.com` host used by all other endpoints.
307
+ */
308
+ declare const signOut: (accessToken: string) => Promise<void>;
309
+
310
+ /**
311
+ * Build the SoundCloud authorization URL for the OAuth 2.0 code flow.
312
+ *
313
+ * Redirect the user to this URL so they can grant access to your application.
314
+ */
315
+ declare function getAuthorizationUrl(clientId: string, redirectUri: string, options?: {
316
+ state?: string;
317
+ codeChallenge?: string;
318
+ }): string;
319
+
320
+ /**
321
+ * Generate a random PKCE code verifier (43 chars, base64url).
322
+ * Works in Node 18+ and modern browsers via globalThis.crypto.
323
+ */
324
+ declare function generateCodeVerifier(): string;
325
+ /**
326
+ * Derive the S256 code challenge from a code verifier.
327
+ * Uses the Web Crypto API (SubtleCrypto) available in Node 18+ and browsers.
328
+ */
329
+ declare function generateCodeChallenge(verifier: string): Promise<string>;
330
+
331
+ declare const getMe: (token: string) => Promise<SoundCloudMe>;
332
+
333
+ declare const getUser: (token: string, userId: string | number) => Promise<SoundCloudUser>;
334
+
335
+ declare const getFollowers: (token: string, userId: string | number, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
336
+
337
+ declare const getFollowings: (token: string, userId: string | number, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
338
+
339
+ declare const getUserTracks: (token: string, userId: string | number, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
340
+
341
+ declare const getUserPlaylists: (token: string, userId: string | number, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
342
+
343
+ declare const getUserLikesTracks: (token: string, userId: string | number, limit?: number, cursor?: string) => Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
344
+
345
+ declare const getUserLikesPlaylists: (token: string, userId: string | number, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
346
+
347
+ /** GET /users/:id/web-profiles — returns user's external links */
348
+ declare const getUserWebProfiles: (token: string, userId: string | number) => Promise<SoundCloudWebProfile[]>;
349
+
350
+ declare const getTrack: (token: string, trackId: string | number) => Promise<SoundCloudTrack>;
351
+
352
+ declare const getTrackComments: (token: string, trackId: string | number, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudComment>>;
353
+
354
+ /** POST /tracks/:id/comments — creates a comment on a track */
355
+ declare const createTrackComment: (token: string, trackId: string | number, body: string, timestamp?: number) => Promise<SoundCloudComment>;
356
+
357
+ declare const getTrackLikes: (token: string, trackId: string | number, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
358
+
359
+ declare const getTrackReposts: (token: string, trackId: string | number, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
360
+
361
+ declare const getRelatedTracks: (token: string, trackId: string | number, limit?: number) => Promise<SoundCloudTrack[]>;
362
+
363
+ /** GET /tracks/:id/streams — returns streamable URLs */
364
+ declare const getTrackStreams: (token: string, trackId: string | number) => Promise<SoundCloudStreams>;
365
+
366
+ declare const likeTrack: (token: string, trackId: string | number) => Promise<boolean>;
367
+
368
+ /** DELETE /likes/tracks/:id — unlikes a track */
369
+ declare const unlikeTrack: (token: string, trackId: string | number) => Promise<boolean>;
370
+
371
+ /** DELETE /tracks/:id — deletes a track */
372
+ declare const deleteTrack: (token: string, trackId: string | number) => Promise<void>;
373
+
374
+ declare const getPlaylist: (token: string, playlistId: string | number) => Promise<SoundCloudPlaylist>;
375
+
376
+ declare const getPlaylistTracks: (token: string, playlistId: string | number, limit?: number, offset?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
377
+
378
+ declare const getPlaylistReposts: (token: string, playlistId: string | number, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
379
+
380
+ /** DELETE /playlists/:id — deletes a playlist */
381
+ declare const deletePlaylist: (token: string, playlistId: string | number) => Promise<void>;
382
+
383
+ declare const searchTracks: (token: string, query: string, pageNumber?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
384
+
385
+ declare const searchUsers: (token: string, query: string, pageNumber?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
386
+
387
+ declare const searchPlaylists: (token: string, query: string, pageNumber?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
388
+
389
+ declare const resolveUrl: (token: string, url: string) => Promise<string>;
390
+
391
+ /** GET /me/activities */
392
+ declare const getMeActivities: (token: string, limit?: number) => Promise<SoundCloudActivitiesResponse>;
393
+ /** GET /me/activities/all/own */
394
+ declare const getMeActivitiesOwn: (token: string, limit?: number) => Promise<SoundCloudActivitiesResponse>;
395
+ /** GET /me/activities/tracks */
396
+ declare const getMeActivitiesTracks: (token: string, limit?: number) => Promise<SoundCloudActivitiesResponse>;
397
+
398
+ /** GET /me/likes/tracks */
399
+ declare const getMeLikesTracks: (token: string, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
400
+ /** GET /me/likes/playlists */
401
+ declare const getMeLikesPlaylists: (token: string, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
402
+
403
+ /** GET /me/followings */
404
+ declare const getMeFollowings: (token: string, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
405
+ /** GET /me/followings/tracks */
406
+ declare const getMeFollowingsTracks: (token: string, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
407
+ /** PUT /me/followings/:user_urn — follow a user */
408
+ declare const followUser: (token: string, userUrn: string | number) => Promise<void>;
409
+ /** DELETE /me/followings/:user_urn — unfollow a user */
410
+ declare const unfollowUser: (token: string, userUrn: string | number) => Promise<void>;
411
+
412
+ /** GET /me/followers */
413
+ declare const getMeFollowers: (token: string, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudUser>>;
414
+
415
+ /** GET /me/playlists */
416
+ declare const getMePlaylists: (token: string, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudPlaylist>>;
417
+
418
+ /** GET /me/tracks */
419
+ declare const getMeTracks: (token: string, limit?: number) => Promise<SoundCloudPaginatedResponse<SoundCloudTrack>>;
420
+
421
+ /** POST /likes/playlists/:id */
422
+ declare const likePlaylist: (token: string, playlistId: string | number) => Promise<boolean>;
423
+ /** DELETE /likes/playlists/:id */
424
+ declare const unlikePlaylist: (token: string, playlistId: string | number) => Promise<boolean>;
425
+
426
+ /** POST /reposts/tracks/:id */
427
+ declare const repostTrack: (token: string, trackId: string | number) => Promise<boolean>;
428
+ /** DELETE /reposts/tracks/:id */
429
+ declare const unrepostTrack: (token: string, trackId: string | number) => Promise<boolean>;
430
+ /** POST /reposts/playlists/:id */
431
+ declare const repostPlaylist: (token: string, playlistId: string | number) => Promise<boolean>;
432
+ /** DELETE /reposts/playlists/:id */
433
+ declare const unrepostPlaylist: (token: string, playlistId: string | number) => Promise<boolean>;
434
+
435
+ /**
436
+ * Returns an encoded SoundCloud widget embed URL for a given track ID.
437
+ */
438
+ declare const getSoundCloudWidgetUrl: (trackId: string | number) => string;
439
+
440
+ export { type CreatePlaylistParams, type RequestOptions, SoundCloudActivitiesResponse, SoundCloudClient, type SoundCloudClientConfig, SoundCloudComment, SoundCloudMe, SoundCloudPaginatedResponse, SoundCloudPlaylist, SoundCloudStreams, SoundCloudToken, SoundCloudTrack, SoundCloudUser, SoundCloudWebProfile, type TokenOption, type UpdatePlaylistParams, type UpdateTrackParams, createPlaylist, createTrackComment, deletePlaylist, deleteTrack, followUser, generateCodeChallenge, generateCodeVerifier, getAuthorizationUrl, getClientToken, getFollowers, getFollowings, getMe, getMeActivities, getMeActivitiesOwn, getMeActivitiesTracks, getMeFollowers, getMeFollowings, getMeFollowingsTracks, getMeLikesPlaylists, getMeLikesTracks, getMePlaylists, getMeTracks, getPlaylist, getPlaylistReposts, getPlaylistTracks, getRelatedTracks, getSoundCloudWidgetUrl, getTrack, getTrackComments, getTrackLikes, getTrackReposts, getTrackStreams, getUser, getUserLikesPlaylists, getUserLikesTracks, getUserPlaylists, getUserToken, getUserTracks, getUserWebProfiles, likePlaylist, likeTrack, refreshUserToken, repostPlaylist, repostTrack, resolveUrl, scFetch, searchPlaylists, searchTracks, searchUsers, signOut, unfollowUser, unlikePlaylist, unlikeTrack, unrepostPlaylist, unrepostTrack, updatePlaylist, updateTrack };