{
  "openapi": "3.1.0",
  "info": {
    "title": "Las Tetras Public AI Radio API",
    "version": "2026-06-02",
    "description": "Public bot-readable endpoints for Las Tetras, an AI-native cumbia project. Use these endpoints for playlist UIs, AI radio demos, agent sandboxes and vibe-coded music prototypes. Attribute data and assets to Las Tetras, https://lastetras.com."
  },
  "servers": [
    {
      "url": "https://lastetras.com"
    }
  ],
  "tags": [
    {
      "name": "radio",
      "description": "Radio Tetra AI feeds and live-ish now-playing rotation."
    },
    {
      "name": "vibecoders",
      "description": "Bot-readable context, manifests and embeddable widget docs."
    }
  ],
  "paths": {
    "/radio/now.json": {
      "get": {
        "tags": ["radio"],
        "summary": "Get current Radio Tetra AI track and queue",
        "operationId": "getRadioNowPlaying",
        "responses": {
          "200": {
            "description": "Current track, queue, public audio URL and feed links.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NowPlaying"
                }
              }
            }
          }
        }
      }
    },
    "/radio/live.json": {
      "get": {
        "tags": ["radio"],
        "summary": "Get live JSON alias for current Radio Tetra AI rotation",
        "operationId": "getRadioLiveJson",
        "responses": {
          "200": {
            "description": "Live-ish current and next track data.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NowPlaying"
                }
              }
            }
          }
        }
      }
    },
    "/radio/live.m3u": {
      "get": {
        "tags": ["radio"],
        "summary": "Get current Radio Tetra AI M3U playlist",
        "operationId": "getRadioLiveM3u",
        "responses": {
          "200": {
            "description": "M3U playlist for current public audio URL.",
            "content": {
              "audio/x-mpegurl": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/radio/live.pls": {
      "get": {
        "tags": ["radio"],
        "summary": "Get current Radio Tetra AI PLS playlist",
        "operationId": "getRadioLivePls",
        "responses": {
          "200": {
            "description": "PLS playlist for current public audio URL.",
            "content": {
              "audio/x-scpls": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/radio/listen": {
      "get": {
        "tags": ["radio"],
        "summary": "Redirect to current playable MP3",
        "operationId": "redirectToCurrentTrack",
        "responses": {
          "302": {
            "description": "Redirects to the current GCS-hosted MP3."
          }
        }
      }
    },
    "/radio.json": {
      "get": {
        "tags": ["radio"],
        "summary": "Get full AI-radio-ready catalog",
        "operationId": "getRadioCatalog",
        "responses": {
          "200": {
            "description": "Full Radio Tetra AI catalog metadata and public MP3 URLs.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/vibecoder-pack.json": {
      "get": {
        "tags": ["vibecoders"],
        "summary": "Get Las Tetras vibecoder manifest",
        "operationId": "getVibecoderPack",
        "responses": {
          "200": {
            "description": "Public links, snippets, assets, prompts and attribution rules.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/radio-widget.js": {
      "get": {
        "tags": ["vibecoders"],
        "summary": "Get embeddable Radio Tetra custom element JavaScript",
        "operationId": "getRadioWidgetJs",
        "responses": {
          "200": {
            "description": "Dependency-free custom element defining <radio-tetra-player>.",
            "content": {
              "application/javascript": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/radio-widget.md": {
      "get": {
        "tags": ["vibecoders"],
        "summary": "Get Markdown install docs for the embeddable widget",
        "operationId": "getRadioWidgetMarkdown",
        "responses": {
          "200": {
            "description": "Markdown install guide for humans, agents and LLM retrieval.",
            "content": {
              "text/markdown": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/llms.txt": {
      "get": {
        "tags": ["vibecoders"],
        "summary": "Get bot-readable Las Tetras context",
        "operationId": "getLlmsTxt",
        "responses": {
          "200": {
            "description": "Bot/agent context, stable links and attribution rules.",
            "content": {
              "text/plain": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Track": {
        "type": "object",
        "properties": {
          "id": { "type": "string" },
          "artist": { "type": "string" },
          "title": { "type": "string" },
          "duration_seconds": { "type": "integer" },
          "audio_url": { "type": "string", "format": "uri" },
          "listen_url": { "type": "string", "format": "uri" },
          "source": { "type": "string", "format": "uri" },
          "license_note": { "type": "string" }
        },
        "required": ["id", "artist", "title", "duration_seconds", "audio_url"]
      },
      "NowPlaying": {
        "type": "object",
        "properties": {
          "schema_version": { "type": "string" },
          "type": { "type": "string" },
          "generated_at": { "type": "string", "format": "date-time" },
          "station": {
            "type": "object",
            "properties": {
              "name": { "type": "string" },
              "artist": { "type": "string" },
              "description": { "type": "string" },
              "homepage": { "type": "string", "format": "uri" },
              "image": { "type": "string", "format": "uri" },
              "language": { "type": "string" },
              "explicit": { "type": "boolean" }
            }
          },
          "status": { "type": "string" },
          "note": { "type": "string" },
          "current": {
            "allOf": [
              { "$ref": "#/components/schemas/Track" },
              {
                "type": "object",
                "properties": {
                  "started_at": { "type": "string", "format": "date-time" },
                  "ends_at": { "type": "string", "format": "date-time" },
                  "progress_seconds": { "type": "integer" },
                  "remaining_seconds": { "type": "integer" }
                }
              }
            ]
          },
          "queue": {
            "type": "array",
            "items": {
              "allOf": [
                { "$ref": "#/components/schemas/Track" },
                {
                  "type": "object",
                  "properties": {
                    "scheduled_at": { "type": "string", "format": "date-time" }
                  }
                }
              ]
            }
          },
          "feeds": {
            "type": "object",
            "additionalProperties": {
              "type": "string",
              "format": "uri"
            }
          }
        },
        "required": ["schema_version", "station", "current", "queue", "feeds"]
      }
    }
  }
}
