Skip to content

GraphQL API reference

BitAgent exposes a GraphQL endpoint at :3333/graphql. The schema is generated from internal/gql/gqlgen.yml via gqlgen and supports full introspection.

Overview

Property Value
Endpoint POST http://<host>:3333/graphql
Playground GET http://<host>:3333/graphql (renders the gqlgen playground)
Auth none by default — front with a reverse proxy for public exposure
Schema introspection enabled

Tools that work out of the box: the gqlgen playground (built-in), Insomnia, Bruno, IntelliJ HTTP client.

Top-level Query fields

Field Type Purpose
torrent TorrentQuery Torrent-centric reads — files, sources, metrics, tag suggestions
torrentContent TorrentContentQuery Search across enriched content (movies / TV / music / books)
queue QueueQuery Queue / job state
workers WorkersQuery Worker registry
health HealthQuery DB / queue / torrent health

TorrentQuery fields

Field Returns Purpose
files(input) TorrentFilesQueryResult List files for given infohashes
listSources() TorrentListSourcesResult Distinct torrent sources known to the indexer
metrics(input) TorrentMetricsQueryResult Bucketed counts over time
suggestTags(input) TorrentSuggestTagsResult Tag suggestions for filtering

TorrentContentQuery fields

Field Returns Purpose
search(input: TorrentContentSearchQueryInput) TorrentContentSearchResult Primary search

TorrentContentSearchResult shape:

Field Purpose
items The matched torrent-content rows
totalCount Estimated or exact count, see next field
totalCountIsEstimate If true, totalCount came from a planner estimate
hasNextPage True when offset+limit < totalCount
aggregations Facet counts: contentType, language, releaseYear, torrentFileType, torrentSource, torrentTag, videoResolution, videoSource

Common queries

Search torrents by free text

query Search {
  torrentContent {
    search(input: { queryString: "the matrix", limit: 25 }) {
      items {
        infoHash
        title
        contentType
        publishedAt
        torrentSource
      }
      totalCount
      hasNextPage
    }
  }
}

Category facet counts (no item rows)

Useful for the dashboard sidebar and for cardinality probes.

query Facets {
  torrentContent {
    search(input: { queryString: "matrix", limit: 0 }) {
      totalCount
      aggregations {
        contentType {
          value
          label
          count
          isEstimate
        }
      }
    }
  }
}

List the 10 most-recent torrents

query MostRecent {
  torrentContent {
    search(input: { limit: 10, orderBy: { field: published_at, descending: true } }) {
      items {
        infoHash
        title
        publishedAt
      }
    }
  }
}

Files for a specific infohash

query Files {
  torrent {
    files(input: { infoHashes: ["a1b2c3d4e5f67890123456789012345678901234"] }) {
      items {
        infoHash
        path
        size
        index
        extension
        fileType
      }
    }
  }
}

Health check

query Health {
  health {
    db
    queue
    torrent
  }
}

Worker list

query Workers {
  workers {
    listAll {
      workers {
        key
        started
      }
    }
  }
}

Top-level Mutation fields

Field Type Purpose
torrent TorrentMutation Torrent management — delete / tag / reprocess
queue QueueMutation Queue management — purge / enqueue reprocess batches

TorrentMutation fields

Field Args Returns
delete infoHashes: [Hash20!]! Boolean!
setTags infoHashes, tagNames Boolean!
putTags infoHashes, tagNames Boolean! (additive)
deleteTags infoHashes, tagNames Boolean!
reprocess input: TorrentReprocessInput Boolean!

QueueMutation fields

Field Args Returns
purgeJobs input: QueuePurgeJobsInput Boolean!
enqueueReprocessTorrentsBatch input: QueueEnqueueReprocessTorrentsBatchInput Boolean!

Common mutations

Apply tags to a torrent

mutation Tag {
  torrent {
    setTags(
      infoHashes: ["a1b2c3d4e5f67890123456789012345678901234"]
      tagNames: ["operator-curated", "trusted"]
    )
  }
}

Delete a torrent by infohash

mutation Delete {
  torrent {
    delete(infoHashes: ["a1b2c3d4e5f67890123456789012345678901234"])
  }
}

Reprocess after editing the classifier

mutation Reprocess {
  torrent {
    reprocess(input: { classifierFlags: { reclassifyAll: true } })
  }
}

(For bulk reprocess across the whole corpus, use the bitagent reprocess CLI command instead — it's transactional.)

Custom scalars

Scalar Description
Hash20 40-character hex info_hash
DateTime RFC3339
Date YYYY-MM-DD
Year Integer year
Duration ISO 8601 duration
ContentType Enum: movie, tv_show, music, audiobook, ebook, comic, software, game, xxx, other
FileType Enum: video / audio / archive / document / image / executable / subtitle / other
VideoResolution Enum: v480p, v720p, v1080p, v2160p, ...
VideoSource Enum: webdl, bluray, dvd, cam, ts, ...
VideoCodec Enum: h264, h265, av1, ...
Video3D, VideoModifier Enum
LanguageInfo Object: code, name, nativeName

Pagination

Set input.offset and input.limit. The result's hasNextPage is true when more rows exist; loop until it goes false.

query Page {
  torrentContent {
    search(input: { queryString: "ubuntu", limit: 50, offset: 100 }) {
      items { infoHash title }
      hasNextPage
      totalCount
    }
  }
}

limit should not exceed 200 for interactive queries — the resolver does not impose a cap, but Postgres planner cost grows fast on large pages.

Error handling

GraphQL errors come back in the standard errors[] array:

{
  "data": null,
  "errors": [
    {
      "message": "input: torrent.delete: at least one infoHash required",
      "path": ["torrent", "delete"],
      "locations": [{ "line": 3, "column": 5 }]
    }
  ]
}

Field-level errors return data with the partial result and a non-empty errors[].

See also