google_youtube_api_v3

Package Version Hex Docs

Gleam bindings for the YouTube Data API v3, code-generated from Google’s official discovery document.

Each of the 209 API resource types gets its own module under youtube/ with:

Each of the 32 API resources also gets a fluent request builder under youtube/api/ (one per resource, all 83 methods), plus a Sans-IO runtime in google_youtube_api_v3/request (maintained source, not generated):

This is a Sans-IO library: it never performs I/O. You execute the rendered Request with your own HTTP client — convert it with request.to_http_request into a standard gleam/http record and hand it to any ecosystem client such as gleam_httpc.

gleam add google_youtube_api_v3@1
import gleam/httpc
import gleam/json
import gleam/option
import gleam/result
import google_youtube_api_v3/request
import google_youtube_api_v3/youtube/api/videos
import google_youtube_api_v3/youtube/playlist_item_status
import google_youtube_api_v3/youtube/video
import google_youtube_api_v3/youtube/video_list_response

pub fn video_title(body: String) -> option.Option(String) {
  // Decode a video resource. Missing fields become `None`,
  // unknown enum strings are a decode error, not silent garbage.
  let assert Ok(v) = json.parse(body, video.decoder())
  case v.snippet {
    option.Some(snippet) -> snippet.title
    option.None -> option.None
  }
}

pub fn privacy_label(status: playlist_item_status.PlaylistItemStatus) -> String {
  case status.privacy_status {
    option.Some(s) -> playlist_item_status.privacy_status_to_string(s)
    option.None -> "unknown"
  }
}

pub fn most_popular(api_key: String) {
  // Build the request as pure data, convert it to a standard
  // `gleam/http` request, send it with Stock Erlang httpc, then parse
  // the response with a generated decoder.
  let req =
    videos.list(["snippet"])
    |> videos.list_with_chart(videos.ListChartMostPopular)
    |> videos.list_with_max_results(10)
    |> videos.list_request
  use response <- result.try(
    req
    |> request.authorize(request.ApiKey(api_key))
    |> request.to_http_request
    |> httpc.send
    |> result.map_error(fn(_) { Nil }),
  )
  request.parse_response(
    response.status,
    response.body,
    video_list_response.decoder(),
  )
  |> result.map_error(fn(_) { Nil })
}

Further documentation can be found at https://hexdocs.pm/google_youtube_api_v3/.

Development

gleam test                  # Run the tests
gleam run -m google_youtube_api_v3/generate  # Regenerate from discovery/
gleam format src test       # Generated code needs a format pass

Regenerating wipes and rewrites src/youtube, and gleam run also type-checks the tests — which import the generated modules. If the two drift apart mid-change, move test/generate_test.gleam aside, regenerate, format, and restore it.

The generator (src/generate.gleam) parses discovery/ with maintained gleam/dynamic/decode decoders — covered by regression tests that pin schema counts, method counts, and tallies per type — and emits each module with gleamgen.

Vocabulary used here: generated files (everything under src/youtube/, marked DO NOT CHANGE) are reproducible artifacts of the generator — edit the generator, not the output. Everything else (src/generate.gleam, src/google_youtube_api_v3/, tests) is maintained source: written with AI assistance, reviewed by a human before commit.

Disclosure: this project is AI-assisted, not vibe-coded. An AI coding agent (via OpenCode) wrote the generator and the generated code under human direction, and a human reviews what gets committed. Every generated decoder is exercised by round-trip tests, and gleam build plus gleam test pass clean — trust the test suite, not the author list.

✨ Search Document