Best Practices
Last updated
Short recommendations for integrating with the Rad TV API.
Use DIDs as the canonical ID for channels and content (e.g. did:rad.live:channel/<uuid>, did:rad.live:content/feature/<id>). Do not mix raw content-metadata or 12core IDs with DIDs in client flows.
Channels do not have a legacy content field. Use:
channel.features(limit, start)
channel.series(limit, start)
channel.episodes(limit, start)
channel.streams(limit, start)
channel.seasons(limit, start)
channel.miniseries(limit, start)
Catalog types (Feature, Episode, Stream, Serie, Season, Miniseries) implement Likeable and Commentable (id, likes, commentCount, comments).
The schema uses ! for non-null fields. Use this when writing clients:
Content: metadata, assets, likes, and commentCount are never null. assets may have empty videos/images before upload. transcodeJob and outputAssets are null when not processing or not available.
Single-entity queries: channel(id), feature(id), stream(id), etc. return null when the entity is not found or not accessible. Check for null before using the result.
Generated TypeScript types (from npm run codegen) reflect the schema.
GraphQL: Responses are { data?, errors? }. Always check response.errors; the HTTP status may still be 200 when there are field errors. Use response.data for the result.
REST/Internal: Success uses { data: <payload> }; errors use { errors: [ { message, code? } ] }.
For MCP, scripts, or long-lived access, use an API key (from POST /internal/v0/generate-api-key) instead of a user JWT. JWTs are for user sessions; API keys are for programmatic and IDE integration.
Use introspection against POST /graphql or the Altair playground at /altair (in development) to explore the full schema. This helps avoid trial-and-error when building queries.
List queries use limit and start (offset). There is no cursor-based pagination or total count in the schema. Implement "next page" by incrementing start by limit until you get fewer results than limit or an empty list.
Last updated

