{"id":44148727,"url":"https://github.com/twin-paws/soundcloud-api-ts","last_synced_at":"2026-02-12T21:01:27.060Z","repository":{"id":337304828,"uuid":"1153052440","full_name":"twin-paws/soundcloud-api-ts","owner":"twin-paws","description":"A TypeScript client for the SoundCloud API. Zero dependencies, native fetch, full OAuth 2.0 + PKCE support.","archived":false,"fork":false,"pushed_at":"2026-02-09T07:20:52.000Z","size":214,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-09T07:24:27.029Z","etag":null,"topics":["api","audio","music","node","oauth2","pkce","rest-api","sdk","soundcloud","soundcloud-api","streaming","typescript"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/twin-paws.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-08T20:35:02.000Z","updated_at":"2026-02-09T07:20:55.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/twin-paws/soundcloud-api-ts","commit_stats":null,"previous_names":["twin-paws/soundcloud-api-client"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/twin-paws/soundcloud-api-ts","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twin-paws%2Fsoundcloud-api-ts","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twin-paws%2Fsoundcloud-api-ts/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twin-paws%2Fsoundcloud-api-ts/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twin-paws%2Fsoundcloud-api-ts/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/twin-paws","download_url":"https://codeload.github.com/twin-paws/soundcloud-api-ts/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/twin-paws%2Fsoundcloud-api-ts/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29381028,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T20:34:40.886Z","status":"ssl_error","status_checked_at":"2026-02-12T20:23:00.490Z","response_time":55,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","audio","music","node","oauth2","pkce","rest-api","sdk","soundcloud","soundcloud-api","streaming","typescript"],"created_at":"2026-02-09T03:04:40.535Z","updated_at":"2026-02-12T21:01:26.966Z","avatar_url":"https://github.com/twin-paws.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# soundcloud-api-ts\n\n[![npm version](https://img.shields.io/npm/v/soundcloud-api-ts)](https://www.npmjs.com/package/soundcloud-api-ts)\n[![npm downloads](https://img.shields.io/npm/dw/soundcloud-api-ts)](https://www.npmjs.com/package/soundcloud-api-ts)\n[![CI](https://github.com/twin-paws/soundcloud-api-ts/actions/workflows/ci.yml/badge.svg)](https://github.com/twin-paws/soundcloud-api-ts/actions/workflows/ci.yml)\n[![license](https://img.shields.io/npm/l/soundcloud-api-ts)](https://github.com/twin-paws/soundcloud-api-ts/blob/main/LICENSE)\n[![bundle size](https://img.shields.io/bundlephobia/minzip/soundcloud-api-ts)](https://bundlephobia.com/package/soundcloud-api-ts)\n[![install size](https://packagephobia.com/badge?p=soundcloud-api-ts)](https://packagephobia.com/result?p=soundcloud-api-ts)\n[![TypeScript](https://img.shields.io/badge/TypeScript-5.9+-blue.svg)](https://www.typescriptlang.org/)\n[![Node](https://img.shields.io/badge/Node.js-≥22-339933.svg)](https://nodejs.org/)\n[![coverage](https://img.shields.io/badge/coverage-100%25-brightgreen.svg)]()\n[![docs](https://img.shields.io/badge/docs-TypeDoc-blue.svg)](https://twin-paws.github.io/soundcloud-api-ts/)\n[![GitHub stars](https://img.shields.io/github/stars/twin-paws/soundcloud-api-ts)](https://github.com/twin-paws/soundcloud-api-ts)\n\nsoundcloud-api-ts is a TypeScript-first SoundCloud API client for accessing tracks, users, playlists, and search endpoints using modern async/await APIs.\n\nZero dependencies, native `fetch`, built-in OAuth 2.1 + PKCE, automatic retry, and an interactive CLI.\n\nThis package is intended to be the recommended option for developers looking for a TypeScript SoundCloud API client.\n\n## Why This Package?\n\nUnlike legacy JavaScript SoundCloud SDKs and community wrappers that require separate `@types` packages or scrape undocumented internal APIs, soundcloud-api-ts is:\n\n- **TypeScript-first** — full types ship with the package, no community typings required\n- **An API client, not a scraper** — uses SoundCloud's official documented API with registered app credentials\n- **Modern async/await interface** — designed for modern TypeScript projects\n- **Zero dependencies** — uses native `fetch`, nothing to install\n- **Token management built-in** — `setToken()`, auto-refresh on 401\n- **PKCE support** for public clients and SPAs\n- **Interactive CLI** — explore the API from your terminal with `sc-cli`\n- **Clean API** — `sc.tracks.getTrack(id)` not `getTrack(token, id)`\n- **Automatic retry** — exponential backoff on 429 and 5xx\n- **Dual ESM/CJS output** — works everywhere\n- **LLM-friendly** — includes `llms.txt` and `AGENTS.md` for AI coding agents\n\n## Comparison\n\n| Feature | soundcloud-api-ts | soundcloud.ts | soundcloud-fetch |\n| --- | --- | --- | --- |\n| TypeScript | ✅ Native | ✅ | ✅ |\n| Dependencies | **0** | 1 | 3 (lodash, cookie, undici) |\n| Bundle size (min+gz) | **4.5 KB** | ❌ unbundlable (native binary) | 191 KB |\n| Auth method | **Official OAuth 2.1** | ⚠️ Scrape client ID from browser | ⚠️ Scrape client ID from browser |\n| PKCE support | ✅ | ❌ | ❌ |\n| Auto token refresh | ✅ on 401 | ❌ | ❌ |\n| Auto retry (429/5xx) | ✅ exponential backoff | ❌ | ❌ |\n| CLI tool | ✅ `sc-cli` | ❌ | ❌ |\n| Pagination helpers | ✅ async iterators | ❌ | ✅ |\n| Typed errors | ✅ `SoundCloudError` | ❌ | ❌ |\n| Test coverage | **100%** | — | — |\n| API docs site | ✅ [TypeDoc](https://twin-paws.github.io/soundcloud-api-ts/) | ✅ | ❌ |\n| LLM/AI-friendly | ✅ llms.txt + AGENTS.md | ❌ | ❌ |\n| Maintained | ✅ 2026 | ✅ 2025 | ✅ 2026 |\n\n\u003e **Why does auth method matter?** `soundcloud.ts` and `soundcloud-fetch` use SoundCloud's undocumented internal `api-v2` and require you to scrape your client ID from browser dev tools. This can break anytime SoundCloud changes their frontend, and may violate the [API Terms of Use](https://developers.soundcloud.com/docs/api/terms-of-use) which state *\"you must register your app\"* and *\"any attempt to circumvent this and obtain a new client ID and Security Code is strictly prohibited.\"*\n\u003e\n\u003e `soundcloud-api-ts` uses the **official documented API** (`api.soundcloud.com`) with registered app credentials, OAuth 2.1 via `secure.soundcloud.com` as specified by SoundCloud, PKCE for public clients, and automatic token refresh.\n\n**Coming from `soundcloud.ts`?** See the [Migration Guide](docs/MIGRATING.md) — most changes are find-and-replace.\n\n## Install\n\n```bash\nnpm install soundcloud-api-ts\n```\n\n## CLI\n\nExplore the SoundCloud API right from your terminal — no code required:\n\n```bash\n# Install globally\nnpm install -g soundcloud-api-ts\n\n# Set up credentials (interactive)\nsc-cli auth\n\n# Search tracks — colorful formatted table\nsc-cli search \"lofi beats\"\n\n# Get track details\nsc-cli track 293\n\n# View user profile\nsc-cli user 12345\n\n# Play a track in your terminal (mpv recommended)\nsc-cli play 293\n\n# Get stream URLs\nsc-cli stream 293\n\n# Show playlist with track listing\nsc-cli playlist 456\n\n# Resolve a SoundCloud URL\nsc-cli resolve https://soundcloud.com/artist/track\n\n# OAuth login for authenticated endpoints\nsc-cli login\nsc-cli me\nsc-cli likes\n```\n\nEvery command supports `--json` for machine-readable output (great for piping to `jq` or using in scripts). Run `sc-cli --help` for the full command list.\n\n```\n⚡ sc-cli — Explore the SoundCloud API from your terminal\n\nCommands: auth, login, search, track, user, playlist, play, stream, resolve, me, likes\nOptions:  --json (raw JSON output), --url (play: print URL only), --help (per-command help)\n\nPlay controls: [space] pause/resume (mpv/ffplay), [q] quit\nSupported players: mpv (recommended — IPC pause/resume), ffplay, afplay (macOS)\n```\n\n## Quick Start\n\n```ts\nimport { SoundCloudClient } from \"soundcloud-api-ts\";\n\nconst sc = new SoundCloudClient({\n  clientId: \"your-client-id\",\n  clientSecret: \"your-client-secret\",\n  redirectUri: \"https://yourapp.com/callback\",\n});\n\n// Get a client token and store it\nconst token = await sc.auth.getClientToken();\nsc.setToken(token.access_token);\n\n// Now all calls use the stored token automatically\nconst results = await sc.search.tracks(\"electronic\");\nconst me = await sc.me.getMe();\nconst track = await sc.tracks.getTrack(123456);\nconst streams = await sc.tracks.getStreams(123456);\n```\n\n## OAuth 2.1 Flow\n\n```ts\nimport { SoundCloudClient, generateCodeVerifier, generateCodeChallenge } from \"soundcloud-api-ts\";\n\nconst sc = new SoundCloudClient({\n  clientId: \"...\",\n  clientSecret: \"...\",\n  redirectUri: \"https://yourapp.com/callback\",\n  // Optional: auto-refresh tokens on 401\n  onTokenRefresh: async (client) =\u003e {\n    const newToken = await client.auth.refreshUserToken(client.refreshToken!);\n    // Persist newToken to your DB here\n    return newToken;\n  },\n});\n\n// 1. Generate PKCE pair (for public clients / SPAs)\nconst verifier = generateCodeVerifier();\nconst challenge = await generateCodeChallenge(verifier);\n\n// 2. Build authorization URL and redirect the user\nconst authUrl = sc.auth.getAuthorizationUrl({ state: \"random\", codeChallenge: challenge });\n// → redirect user to authUrl\n\n// 3. Exchange the code for tokens (in your callback handler)\nconst token = await sc.auth.getUserToken(code, verifier);\nsc.setToken(token.access_token, token.refresh_token);\n\n// 4. Use the API — token is used automatically\nconst me = await sc.me.getMe();\nconst tracks = await sc.search.tracks(\"lofi beats\");\n\n// 5. Override token per-call if needed\nconst otherMe = await sc.me.getMe({ token: \"other-users-token\" });\n\n// 6. Refresh manually if needed\nconst refreshed = await sc.auth.refreshUserToken(token.refresh_token);\nsc.setToken(refreshed.access_token, refreshed.refresh_token);\n\n// 7. Sign out\nawait sc.auth.signOut(token.access_token);\nsc.clearToken();\n```\n\n## Client Class\n\nThe `SoundCloudClient` class organizes all endpoints into namespaces. Token is resolved automatically when `setToken()` has been called. Override per-call via `{ token: \"...\" }` options object.\n\n```ts\nconst sc = new SoundCloudClient({ clientId, clientSecret, redirectUri });\n\n// Token management\nsc.setToken(accessToken, refreshToken?)\nsc.clearToken()\nsc.accessToken   // getter\nsc.refreshToken  // getter\n\n// Auth\nsc.auth.getAuthorizationUrl({ state?, codeChallenge? })\nsc.auth.getClientToken()\nsc.auth.getUserToken(code, codeVerifier?)\nsc.auth.refreshUserToken(refreshToken)\nsc.auth.signOut(accessToken)\n\n// Me (authenticated user) — primary params first, options last\nsc.me.getMe(options?)\nsc.me.getActivities(limit?, options?)\nsc.me.getActivitiesOwn(limit?, options?)\nsc.me.getActivitiesTracks(limit?, options?)\nsc.me.getLikesTracks(limit?, options?)\nsc.me.getLikesPlaylists(limit?, options?)\nsc.me.getFollowings(limit?, options?)\nsc.me.getFollowingsTracks(limit?, options?)\nsc.me.follow(userUrn, options?)\nsc.me.unfollow(userUrn, options?)\nsc.me.getFollowers(limit?, options?)\nsc.me.getPlaylists(limit?, options?)\nsc.me.getTracks(limit?, options?)\n\n// Users\nsc.users.getUser(userId, options?)\nsc.users.getFollowers(userId, limit?, options?)\nsc.users.getFollowings(userId, limit?, options?)\nsc.users.getTracks(userId, limit?, options?)\nsc.users.getPlaylists(userId, limit?, options?)\nsc.users.getLikesTracks(userId, limit?, cursor?, options?)\nsc.users.getLikesPlaylists(userId, limit?, options?)\nsc.users.getWebProfiles(userId, options?)\n\n// Tracks\nsc.tracks.getTrack(trackId, options?)\nsc.tracks.getStreams(trackId, options?)\nsc.tracks.getComments(trackId, limit?, options?)\nsc.tracks.createComment(trackId, body, timestamp?, options?)\nsc.tracks.getLikes(trackId, limit?, options?)\nsc.tracks.getReposts(trackId, limit?, options?)\nsc.tracks.getRelated(trackId, limit?, options?)\nsc.tracks.update(trackId, params, options?)\nsc.tracks.delete(trackId, options?)\n\n// Playlists\nsc.playlists.getPlaylist(playlistId, options?)\nsc.playlists.getTracks(playlistId, limit?, offset?, options?)\nsc.playlists.getReposts(playlistId, limit?, options?)\nsc.playlists.create(params, options?)\nsc.playlists.update(playlistId, params, options?)\nsc.playlists.delete(playlistId, options?)\n\n// Likes\nsc.likes.likeTrack(trackId, options?)\nsc.likes.unlikeTrack(trackId, options?)\nsc.likes.likePlaylist(playlistId, options?)\nsc.likes.unlikePlaylist(playlistId, options?)\n\n// Reposts\nsc.reposts.repostTrack(trackId, options?)\nsc.reposts.unrepostTrack(trackId, options?)\nsc.reposts.repostPlaylist(playlistId, options?)\nsc.reposts.unrepostPlaylist(playlistId, options?)\n\n// Search\nsc.search.tracks(query, pageNumber?, options?)\nsc.search.users(query, pageNumber?, options?)\nsc.search.playlists(query, pageNumber?, options?)\n\n// Resolve\nsc.resolve.resolveUrl(url, options?)\n```\n\nWhere `options` is `{ token?: string }` — only needed to override the stored token.\n\n## Standalone Functions\n\nEvery endpoint is also available as a standalone function (token is always required):\n\n```ts\nimport {\n  getClientToken, getUserToken, getAuthorizationUrl,\n  generateCodeVerifier, generateCodeChallenge,\n  getMe, searchTracks,\n} from \"soundcloud-api-ts\";\n\nconst token = await getClientToken(\"clientId\", \"clientSecret\");\nconst me = await getMe(token.access_token);\nconst tracks = await searchTracks(token.access_token, \"lo-fi\");\n\n// Build auth URL\nconst authUrl = getAuthorizationUrl(\"clientId\", \"https://yourapp.com/callback\", { state: \"xyz\" });\n```\n\n## Types\n\nAll response types match the SoundCloud API spec:\n\n```ts\nimport type {\n  SoundCloudUser,\n  SoundCloudMe,\n  SoundCloudTrack,\n  SoundCloudPlaylist,\n  SoundCloudComment,\n  SoundCloudToken,\n  SoundCloudStreams,\n  SoundCloudWebProfile,\n  SoundCloudActivity,\n  SoundCloudActivitiesResponse,\n  SoundCloudPaginatedResponse,\n  TokenOption,\n} from \"soundcloud-api-ts/types\";\n```\n\n## PKCE (Proof Key for Code Exchange)\n\nFor public clients (SPAs, mobile apps), use PKCE:\n\n```ts\nimport { generateCodeVerifier, generateCodeChallenge } from \"soundcloud-api-ts\";\n\nconst verifier = generateCodeVerifier();\nconst challenge = await generateCodeChallenge(verifier);\n\n// Pass challenge when building auth URL\nconst url = sc.auth.getAuthorizationUrl({ codeChallenge: challenge });\n\n// Pass verifier when exchanging the code\nconst token = await sc.auth.getUserToken(code, verifier);\n```\n\n## Pagination\n\nPaginated endpoints return `SoundCloudPaginatedResponse\u003cT\u003e`:\n\n```ts\ninterface SoundCloudPaginatedResponse\u003cT\u003e {\n  collection: T[];\n  next_href: string; // URL for next page\n}\n```\n\n### Automatic Pagination\n\nThe client provides three helpers that automatically follow `next_href` across pages:\n\n```ts\n// Stream pages — yields T[] for each page\nfor await (const page of sc.paginate(() =\u003e sc.users.getTracks(userId))) {\n  console.log(`Got ${page.length} tracks`);\n}\n\n// Stream individual items — yields one T at a time\nfor await (const track of sc.paginateItems(() =\u003e sc.search.tracks(\"lofi\"))) {\n  console.log(track.title);\n}\n\n// Collect all into a flat array (with optional limit)\nconst allTracks = await sc.fetchAll(() =\u003e sc.users.getTracks(userId));\nconst first100 = await sc.fetchAll(() =\u003e sc.search.tracks(\"lofi\"), { maxItems: 100 });\n```\n\nThe standalone functions are also exported for advanced use:\n\n```ts\nimport { paginate, paginateItems, fetchAll, scFetchUrl } from \"soundcloud-api-ts\";\n```\n\n## Utilities\n\n```ts\nimport { getSoundCloudWidgetUrl } from \"soundcloud-api-ts\";\n\n// Generate a SoundCloud embed widget URL\nconst widgetUrl = getSoundCloudWidgetUrl(trackId);\n```\n\n## Error Handling\n\nAll API errors throw a `SoundCloudError` with structured properties:\n\n```ts\nimport { SoundCloudError } from \"soundcloud-api-ts\";\n\ntry {\n  await sc.tracks.getTrack(999);\n} catch (err) {\n  if (err instanceof SoundCloudError) {\n    console.log(err.status);     // 404\n    console.log(err.statusText); // \"Not Found\"\n    console.log(err.message);    // \"404 - Not Found\" (from SC's response)\n    console.log(err.errorCode);  // \"invalid_client\" (on auth errors)\n    console.log(err.errors);     // [\"404 - Not Found\"] (individual error messages)\n    console.log(err.docsLink);   // \"https://developers.soundcloud.com/docs/api/explorer/open-api\"\n    console.log(err.body);       // full parsed response body\n\n    // Convenience getters\n    if (err.isNotFound) { /* handle 404 */ }\n    if (err.isRateLimited) { /* handle 429 */ }\n    if (err.isUnauthorized) { /* handle 401 */ }\n    if (err.isForbidden) { /* handle 403 */ }\n    if (err.isServerError) { /* handle 5xx */ }\n  }\n}\n```\n\nError messages are parsed directly from SoundCloud's API response format, giving you the most useful message available.\n\n## Rate Limiting \u0026 Retries\n\nThe client automatically retries on **429 Too Many Requests** and **5xx Server Errors** with exponential backoff:\n\n```ts\nconst sc = new SoundCloudClient({\n  clientId: \"...\",\n  clientSecret: \"...\",\n  maxRetries: 3,         // default: 3\n  retryBaseDelay: 1000,  // default: 1000ms\n  onDebug: (msg) =\u003e console.log(msg), // optional retry logging\n});\n```\n\n- **429 responses** respect the `Retry-After` header when present\n- **5xx responses** (500, 502, 503, 504) are retried with exponential backoff\n- **4xx errors** (except 429) are NOT retried — they throw immediately\n- **401 errors** trigger `onTokenRefresh` (if configured) instead of retry\n- Backoff formula: `baseDelay × 2^attempt` with jitter\n\n## API Terms Compliance\n\nThis package is built on SoundCloud's **official documented API** (`api.soundcloud.com`) and follows the [API Terms of Use](https://developers.soundcloud.com/docs/api/terms-of-use):\n\n- ✅ Uses registered app credentials (client ID + client secret) via OAuth 2.1 on `secure.soundcloud.com`\n- ✅ No undocumented or internal API endpoints (`api-v2`)\n- ✅ No client ID scraping or credential circumvention\n- ✅ No content downloading, ripping, or stream capture\n- ✅ No content aggregation into alternative streaming services\n\n\u003e **Important:** SoundCloud's API Terms prohibit using User Content (audio, tracks, metadata) to train or develop AI/ML models. The \"LLM-friendly\" features of this package (`llms.txt`, `AGENTS.md`) are for helping AI coding agents **use the package itself** — not for feeding SoundCloud content to AI systems. Please review the [full terms](https://developers.soundcloud.com/docs/api/terms-of-use) before building your application.\n\n## AI / LLM Integration\n\nThis package is designed to be easily used by AI coding agents:\n\n- **[`llms.txt`](llms.txt)** — Complete method reference in plain text, optimized for LLM consumption\n- **[`AGENTS.md`](AGENTS.md)** — Setup guide, common patterns, and gotchas for AI agents\n- **Full JSDoc** with `@example` on every export — works great with GitHub Copilot, Cursor, etc.\n\n## Documentation\n\nFull API documentation is available at **[twin-paws.github.io/soundcloud-api-ts](https://twin-paws.github.io/soundcloud-api-ts/)** — auto-generated from source with TypeDoc.\n\n## Requirements\n\n- Node.js 20+ (uses native `fetch`)\n- SoundCloud API credentials\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for release history.\n\n## Related Packages\n\n- **[soundcloud-api-ts-next](https://github.com/twin-paws/soundcloud-api-ts-next)** — React hooks + Next.js API route handlers built on this package. Use it when building Next.js apps that need SoundCloud data with secrets kept server-side.\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.\n\n## License\n\n[MIT](LICENSE) © Twin Paws\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwin-paws%2Fsoundcloud-api-ts","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftwin-paws%2Fsoundcloud-api-ts","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftwin-paws%2Fsoundcloud-api-ts/lists"}