Galactic Radio MusicGen API
v1.0.0 — AI-powered music generation with Google Lyria 3
Contents
Authentication
The API supports three authentication methods:
- Firebase OAuth — Send a Firebase ID token as
Authorization: Bearer <token>. Used by the web frontend after Google sign-in. - API Key — Send your key as
X-API-Key: grm_xxxheader. Get a key viaPOST /api/v1/users/registeror OAuth sign-in. - Local Dev Bypass — In development mode, requests from localhost are auto-authenticated as admin. No headers needed.
Users
Register a new user. Returns an API key (shown once).
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | User email |
password | string | Yes | Min 6 characters |
display_name | string | No | Display name |
curl -X POST http://localhost:8216/api/v1/users/register \
-H "Content-Type: application/json" \
-d '{"email":"user@example.com","password":"secret123"}'
Response (201)
{
"uid": "abc123",
"email": "user@example.com",
"api_key": "grm_xxxxxxxxxxxx",
"credits_balance": 3,
"message": "Account created. Store this API key securely..."
}
OAuth sign-in callback. Provisions profile and API key for new users.
curl -X POST http://localhost:8216/api/v1/users/oauth-signin \
-H "Authorization: Bearer <firebase_id_token>"
Response (200)
{
"uid": "firebase_uid",
"email": "user@gmail.com",
"display_name": "John Doe",
"api_key": "grm_xxxxxxxxxxxx", // only for new users
"credits_balance": 3,
"is_new_user": true
}
Get current user profile.
curl http://localhost:8216/api/v1/users/me \
-H "X-API-Key: grm_xxxxxxxxxxxx"
Response (200)
{
"uid": "abc123",
"email": "user@example.com",
"display_name": "John",
"bio": "Music enthusiast",
"avatar_url": "https://...",
"role": "user",
"credits_balance": 3,
"api_key_count": 1,
"created_at": "2026-04-17T12:00:00+00:00"
}
Update profile fields (display_name, bio).
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
display_name | string | No | Display name (max 100) |
bio | string | No | Short bio (max 500) |
curl -X PATCH http://localhost:8216/api/v1/users/me \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"display_name": "DJ Nebula", "bio": "Making cosmic beats"}'
Get aggregated play statistics for the current user's songs.
curl http://localhost:8216/api/v1/users/me/stats \
-H "X-API-Key: grm_xxxxxxxxxxxx"
Response (200)
{
"total_songs": 12,
"total_plays": 150,
"plays_by_location": {"web-player": 100, "discord-bot": 50},
"top_songs": [
{"song_id": "song_abc123", "title": "Hit Track", "play_count": 42}
]
}
Generate a new API key. The raw key is returned once.
curl -X POST http://localhost:8216/api/v1/users/api-keys \
-H "X-API-Key: grm_xxxxxxxxxxxx"
Response (200)
{
"api_key": "grm_new_key_here",
"message": "Store this key securely — it will not be shown again"
}
Revoke an API key by its hash prefix.
curl -X DELETE http://localhost:8216/api/v1/users/api-keys/abc123 \
-H "X-API-Key: grm_xxxxxxxxxxxx"
Upload a custom avatar image. Max 2MB, JPEG or PNG only.
curl -X POST http://localhost:8216/api/v1/users/me/avatar \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-F "file=@avatar.jpg"
Response (200)
{
"uid": "abc123",
"email": "user@example.com",
"display_name": "John",
"avatar_url": "https://storage.googleapis.com/.../avatar.jpg",
...
}
Songs
Generate a new song via Google Lyria 3 API. Costs credits.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | Yes | Song title (1-200 chars) |
description | string | No | Description (max 500) |
lyrics | string | No | Lyrics to use (max 5000) |
genre | string | No | Genre (e.g. "ambient electronic") |
mood | string | No | Mood (e.g. "ethereal", "upbeat") |
artist_name | string | No | Artist name to display |
artist_url | string | No | Artist profile URL (max 500) |
generation_type | string | No | full_song (default) or jingle |
audio_format | string | No | mp3 (default) |
bpm | int | No | Tempo 40-300 |
key_scale | string | No | Musical key (e.g. "C minor") |
instruments | string[] | No | Instruments to feature |
duration_hint | string | No | e.g. "short", "30 seconds" |
meta | object | No | Arbitrary metadata (station_id, etc.) |
curl -X POST http://localhost:8216/api/v1/songs/generate \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Cosmic Dawn",
"genre": "ambient electronic",
"mood": "ethereal",
"artist_name": "DJ Nebula",
"generation_type": "full_song"
}'
Response (201)
Returns the full Song object.
Get a song by ID.
curl http://localhost:8216/api/v1/songs/song_abc123 \
-H "X-API-Key: grm_xxxxxxxxxxxx"
List and search songs with filtering, search, and shuffle.
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
mine | bool | false | Only show my songs |
created_by | string[] | [] | Filter by user UID(s) — repeat for multiple |
genre | string | — | Substring match, case-insensitive |
mood | string | — | Substring match, case-insensitive |
q | string | — | Free-text search (title, desc, genre, mood, artist, lyrics) |
shuffle | bool | false | Randomize results instead of newest-first |
status | string | completed | Filter by status |
limit | int | 20 | 1-100 |
offset | int | 0 | Pagination offset |
# Search for country songs about love
curl "http://localhost:8216/api/v1/songs?q=love&genre=country&limit=10" \
-H "X-API-Key: grm_xxxxxxxxxxxx"
# 5 random songs for radio shuffle
curl "http://localhost:8216/api/v1/songs?shuffle=true&limit=5" \
-H "X-API-Key: grm_xxxxxxxxxxxx"
Response (200)
{
"songs": [ ... ], // array of Song objects
"total": 42,
"limit": 20,
"offset": 0
}
Record a play event for analytics.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
location | string | Yes | Where played (e.g. "web-player", "discord-bot") |
curl -X POST http://localhost:8216/api/v1/songs/song_abc123/play \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"location": "web-player"}'
Update song metadata. Owner or admin only. At least one field required.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
title | string | No | Song title (1-200 chars) |
artist_name | string | No | Artist name (max 100) |
artist_url | string | No | Artist profile URL (max 500) |
description | string | No | Description (max 500) |
genre | string | No | Genre (max 100) |
mood | string | No | Mood (max 100) |
curl -X PATCH http://localhost:8216/api/v1/songs/song_abc123 \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"title": "Updated Title", "genre": "jazz"}'
Response (200)
Returns the updated Song object.
Upload cover art for a song. Max 2MB, JPEG or PNG only. Owner or admin only.
curl -X POST http://localhost:8216/api/v1/songs/song_abc123/art \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-F "file=@cover.jpg"
Response (200)
{
"cover_art_url": "https://storage.googleapis.com/.../cover.jpg",
"song_id": "song_abc123"
}
Delete a song. Only the owner or an admin can delete.
curl -X DELETE http://localhost:8216/api/v1/songs/song_abc123 \
-H "X-API-Key: grm_xxxxxxxxxxxx"
Credits
Get current credits balance.
curl http://localhost:8216/api/v1/credits/balance \
-H "X-API-Key: grm_xxxxxxxxxxxx"
Response (200)
{"credits_balance": 3}
Purchase credits (AP2 placeholder — returns payment_required status).
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
amount | int | Yes | Number of credits to purchase (> 0) |
curl -X POST http://localhost:8216/api/v1/credits/purchase \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"amount": 10}'
Response (200)
{
"status": "payment_required",
"ap2_metadata": {
"protocol": "ap2",
"provider": "galactic-radio-musicgen",
"amount_requested": 10,
"currency": "credits",
"message": "AP2 payment integration coming soon"
}
}
A2A Protocol (Agent-to-Agent)
The A2A protocol allows other AI agents to discover and interact with this service programmatically.
Agent discovery card. Returns service capabilities, skills, and authentication requirements.
curl http://localhost:8216/.well-known/agent.json
Skills
- generate_music — Generate a song using Lyria 3
- search_songs — Search the song catalog
- get_song — Retrieve a specific song
- purchase_credits — Purchase credits (AP2 placeholder)
JSON-RPC 2.0 endpoint for agent task execution. Supports tasks/send method.
curl -X POST http://localhost:8216/a2a \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tasks/send",
"id": 1,
"params": {
"skill_id": "search_songs",
"input": {"q": "ambient", "limit": 5}
}
}'
Response (200)
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"id": "task-uuid",
"status": {"state": "completed"},
"artifacts": [{
"parts": [{
"type": "data",
"data": {"songs": [...], "total": 5}
}]
}]
}
}
System
Health check. Returns service status.
curl http://localhost:8216/api/v1/health
Response (200)
{
"status": "ok",
"version": "1.0.0",
"environment": "development",
"services": {
"firestore": "connected",
"music_gen": "configured"
}
}
Server name, version, and environment.
curl http://localhost:8216/api/v1/info
View current runtime config (models, credits, storage).
curl http://localhost:8216/api/v1/config \
-H "X-API-Key: grm_admin_key"
Update runtime config values (in-memory, not persisted to .env).
curl -X PATCH http://localhost:8216/api/v1/config \
-H "X-API-Key: grm_admin_key" \
-H "Content-Type: application/json" \
-d '{"lyria_pro_model": "lyria-3-pro-v2", "credits_per_full_song": 2}'
Radio Station / Agent Usage
Agents and radio bots can use the search/filter/shuffle endpoints to build playlists:
# Get 5 random songs for a radio set
curl "http://localhost:8216/api/v1/songs?shuffle=true&limit=5" \
-H "X-API-Key: grm_xxxxxxxxxxxx"
# Get electronic songs matching a mood
curl "http://localhost:8216/api/v1/songs?genre=electronic&mood=chill&limit=10" \
-H "X-API-Key: grm_xxxxxxxxxxxx"
# Search by keyword
curl "http://localhost:8216/api/v1/songs?q=space+adventure&shuffle=true&limit=3" \
-H "X-API-Key: grm_xxxxxxxxxxxx"
# Generate a custom jingle for a station break
curl -X POST http://localhost:8216/api/v1/songs/generate \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Station Break Jingle",
"description": "Upbeat 30-second station identification",
"generation_type": "jingle",
"meta": {"station_id": "galactic-fm", "requested_by_agent": "dj-bot"}
}'
# Record that a song was played
curl -X POST http://localhost:8216/api/v1/songs/song_abc123/play \
-H "X-API-Key: grm_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"location": "galactic-fm-stream"}'
Song JSON Schema
Every song endpoint returns this shape:
{
"song_id": "song_abc123def456gh",
"title": "Cosmic Dawn",
"artist_name": "DJ Nebula",
"artist_url": "https://example.com/artist",
"cover_art_url": "https://storage.googleapis.com/.../cover.jpg",
"description": "Ambient track for sunrise",
"lyrics_input": null,
"lyrics_generated": "Stars fade into morning light...",
"genre": "ambient electronic",
"mood": "ethereal",
"duration_seconds": null,
"audio_url": "https://storage.googleapis.com/.../song.mp3",
"audio_path": "songs/uid/song_id/song.mp3",
"audio_format": "mp3",
"file_size_bytes": 4521984,
"model_used": "lyria-3-pro-preview",
"generation_prompt": "Create a song titled...",
"generation_type": "full_song",
"cost_credits": 1,
"play_count": 42,
"play_count_by_location": {"web-player": 30, "discord-bot": 12},
"status": "completed",
"error_message": null,
"created_by": "user_uid",
"meta": {"station_id": "galactic-fm"},
"created_at": "2026-04-17T12:00:00+00:00",
"updated_at": "2026-04-17T12:00:00+00:00"
}
Status values: pending, generating, completed, failed