Files
NtR-soudcloud-fetcher/docs/api.md
cottongin cb3ae403cf feat: add historical backfill with --init CLI and episode numbering
Adds a --init mode that seeds the database with past shows from a given
anchor episode/date forward, batch-fetching likes from SoundCloud and
partitioning them into weekly buckets. Episode numbers are tracked in
the shows table and auto-incremented by the poller for new shows.

Includes full API documentation (docs/api.md) and updated README.

Made-with: Cursor
2026-03-12 02:09:15 -04:00

6.6 KiB

NtR SoundCloud Fetcher -- API Reference

Base URL: http://127.0.0.1:8000 (configurable via NTR_HOST / NTR_PORT)


Public Endpoints

GET /health

Service health check.

Response

{
  "status": "ok",
  "poller_alive": true,
  "last_fetch": "2026-03-12T02:00:00+00:00",
  "current_week_track_count": 9
}
Field Type Description
status string Always "ok"
poller_alive boolean Whether the background poller is running
last_fetch string | null ISO 8601 timestamp of last successful poll, or null if never
current_week_track_count integer Number of tracks in the current week's playlist

GET /playlist

Returns the current week's full playlist.

Response

{
  "show_id": 10,
  "episode_number": 530,
  "week_start": "2026-03-05T02:00:00+00:00",
  "week_end": "2026-03-12T02:00:00+00:00",
  "tracks": [
    {
      "show_id": 10,
      "track_id": 12345,
      "position": 1,
      "title": "Night Drive",
      "artist": "SomeArtist",
      "permalink_url": "https://soundcloud.com/someartist/night-drive",
      "artwork_url": "https://i1.sndcdn.com/artworks-...-large.jpg",
      "duration_ms": 245000,
      "license": "cc-by",
      "liked_at": "2026-03-06T14:23:00+00:00",
      "raw_json": "{...}"
    }
  ]
}
Field Type Description
show_id integer Internal database ID for this show
episode_number integer | null Episode number (e.g. 530), or null if not assigned
week_start string ISO 8601 UTC timestamp -- start of the show's like window
week_end string ISO 8601 UTC timestamp -- end of the show's like window
tracks array Ordered list of tracks (see Track Object below)

GET /playlist/{position}

Returns a single track by its position in the current week's playlist. Positions are 1-indexed (matching IRC commands !1, !2, etc.).

Path Parameters

Parameter Type Description
position integer 1-based position in the playlist

Response -- a single Track Object (see below).

Errors

Status Detail
404 "No track at position {n}"

GET /shows

Lists all shows, ordered by week start date (newest first).

Query Parameters

Parameter Type Default Description
limit integer 20 Max number of shows to return
offset integer 0 Number of shows to skip

Response

[
  {
    "id": 10,
    "episode_number": 530,
    "week_start": "2026-03-05T02:00:00+00:00",
    "week_end": "2026-03-12T02:00:00+00:00",
    "created_at": "2026-03-05T03:00:00+00:00"
  }
]

GET /shows/{show_id}

Returns a specific show with its full track listing.

Path Parameters

Parameter Type Description
show_id integer The show's internal database ID

Response

{
  "show_id": 10,
  "episode_number": 530,
  "week_start": "2026-03-05T02:00:00+00:00",
  "week_end": "2026-03-12T02:00:00+00:00",
  "tracks": [...]
}

Errors

Status Detail
404 "Show not found"

Admin Endpoints

All admin endpoints require a bearer token via the Authorization header:

Authorization: Bearer <NTR_ADMIN_TOKEN>

Returns 401 with "Missing or invalid token" if the header is absent or the token doesn't match.


POST /admin/refresh

Triggers an immediate SoundCloud fetch for the current week's show.

Request Body (optional)

{
  "full": false
}
Field Type Default Description
full boolean false Reserved for future use (full vs incremental refresh)

Response

{
  "status": "refreshed",
  "track_count": 9
}

POST /admin/tracks

Manually add a track to the current week's show.

Request Body

{
  "track_id": 12345,
  "position": 3
}
Field Type Required Description
track_id integer yes SoundCloud track ID (must already exist in the tracks table)
position integer no Insert at this position (shifts others down). Omit to append at end.

Response

{
  "status": "added"
}

DELETE /admin/tracks/{track_id}

Remove a track from the current week's show. Remaining positions are re-compacted.

Path Parameters

Parameter Type Description
track_id integer SoundCloud track ID to remove

Response

{
  "status": "removed"
}

Errors

Status Detail
404 "Track not in current show"

PUT /admin/tracks/{track_id}/position

Move a track to a new position within the current week's show.

Path Parameters

Parameter Type Description
track_id integer SoundCloud track ID to move

Request Body

{
  "position": 1
}
Field Type Required Description
position integer yes New 1-based position for the track

Response

{
  "status": "moved"
}

Errors

Status Detail
404 "Track not in current show"

Track Object

Returned inside playlist and show detail responses.

Field Type Description
show_id integer The show this track belongs to
track_id integer SoundCloud track ID
position integer 1-based position in the playlist
title string Track title
artist string Uploader's SoundCloud username
permalink_url string Full URL to the track on SoundCloud
artwork_url string | null URL to artwork image, or null
duration_ms integer Track duration in milliseconds
license string License string (e.g. "cc-by", "cc-by-sa")
liked_at string ISO 8601 timestamp of when the host liked the track
raw_json string Full SoundCloud API response for this track (JSON string)

Week Boundaries

Shows follow a weekly cadence aligned to Wednesday 22:00 Eastern Time (EST or EDT depending on DST). The like window for a show runs from the previous Wednesday 22:00 ET to the current Wednesday 22:00 ET.

All timestamps in API responses are UTC. The boundary shifts by 1 hour across DST transitions:

Period Eastern UTC boundary
EST (Nov -- Mar) Wed 22:00 Thu 03:00
EDT (Mar -- Nov) Wed 22:00 Thu 02:00