Skip to content

API

ArgonFetch exposes a small REST API. Every endpoint is a GET, there is no authentication, and responses are JSON unless they are the media itself.

Every operation has its own page in the sidebar, generated from the schema, with its parameters, response shapes and a playground you can send real requests from.

Trying a request

The playground runs in your browser and sends real requests to app.argonfetch.dev, the hosted instance. Use the server selector to point it at your own instance instead - and make sure that instance lists docs.argonfetch.dev in CORS_ALLOWED_ORIGINS, or the browser blocks the response before it reaches the page. See Configuration.

Endpoints

EndpointWhat it does
GET /api/AppVersion and health, including why the instance is in maintenance
GET /api/App/requestsHow many resolve requests this instance has served
GET /api/Fetch/GetResourceResolves a media URL into metadata and available renditions
GET /api/Stream/Media/{key}Streams one rendition; ?format=mp3 re-encodes audio
GET /api/Stream/Combined/{key}Muxes separate video and audio into MP4

Fetch and Stream are the pair you want: resolve a URL, then stream the key you picked out of the response. Usage walks through both with curl.

Range requests

GET /api/Stream/Media/{key} honours the Range header, so a download can be resumed and a player can seek without pulling the whole file first. A ranged request answers 206 Partial Content, and a range the media cannot satisfy answers 416.

bash
curl -r 0-1048575 "https://app.argonfetch.dev/api/Stream/Media/<key>" -o part.webm

GET /api/Stream/Combined/{key} does not: it muxes video and audio as it sends them, so there is no known length to seek within. It answers 200 and streams from the start.

Errors

Failures come back as RFC 7807 ProblemDetails:

json
{
  "type": "https://tools.ietf.org/html/rfc9110#section-15.5.1",
  "title": "Unsupported Media Type",
  "status": 415,
  "detail": "This media is DRM protected and cannot be downloaded."
}

What GetResource answers, and what each one means:

StatusTitleMeans
400Bad RequestThe url parameter is missing or malformed
404Resource Not FoundThe link did not resolve to anything
415Unsupported Media TypeThe source refused, or the link shape is not handled. detail says which
502Fetch FailedExtraction failed for some other reason
503the current activityThe instance is updating yt-dlp and FFmpeg and is briefly unavailable

415 is the one worth handling separately. It is not a broken link: it means the media was found and cannot be delivered - most often DRM, which SoundCloud applies to its licensed catalogue and yt-dlp refuses. The detail field carries the reason, so a caller can tell DRM apart from a link ArgonFetch does not handle yet. Only 415 and 503 fill detail in; the rest carry title alone.

A 503 means the container is still fetching its media tooling - GET /api/App says so in its maintenance field, and it clears itself within seconds of a start.

The schema

These pages are generated from openapi.json, which is checked in at docs/public/openapi.json so clients can be generated without running the app. Swagger UI is also served at /swagger when ASPNETCORE_ENVIRONMENT=Development.

Refresh the schema from a running instance after changing any endpoint or DTO - the pages here follow automatically:

bash
curl -s http://localhost:5114/swagger/v1/swagger.json -o docs/public/openapi.json

Released under the GPL-3.0 License.