{"openapi":"3.1.0","info":{"title":"Naija Radio API","version":"1.0.0","description":"Private beta. Station metadata and direct broadcaster stream URLs. Bearer keys are server-side secrets. No audio proxying or playback guarantee."},"servers":[{"url":"https://fm.puzzofme.com/api/v1"}],"security":[{"bearerAuth":[]}],"paths":{"/stations":{"get":{"operationId":"listStations","parameters":[{"name":"city","in":"query","schema":{"type":"string","maxLength":100},"description":"Case-insensitive exact match."},{"name":"state","in":"query","schema":{"type":"string","maxLength":100},"description":"Case-insensitive exact match."},{"name":"search","in":"query","schema":{"type":"string","maxLength":100},"description":"Case-insensitive substring of name, frequency, city, state, or tags."},{"name":"countryCode","in":"query","schema":{"type":"string","pattern":"^[A-Za-z]{2}$","default":"NG"}},{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"offset","in":"query","schema":{"type":"integer","minimum":0,"maximum":10000,"default":0}}],"responses":{"200":{"description":"Stations ordered by name then ID","content":{"application/json":{"schema":{"type":"object","required":["data","pagination","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Station"}},"pagination":{"$ref":"#/components/schemas/Pagination"},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"400":{"description":"Invalid query or ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-key minute limit exceeded; Retry-After is seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Catalogue or database unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/stations/{id}":{"get":{"operationId":"getStation","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_-]{1,80}$"},"description":"Permanent Naija Radio ID or legacy alias."}],"responses":{"200":{"description":"Station","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Station"},"meta":{"$ref":"#/components/schemas/Meta"}}}}}},"400":{"description":"Invalid query or ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing, invalid or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Unknown station","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Per-key minute limit exceeded; Retry-After is seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Catalogue or database unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer"}},"schemas":{"Station":{"type":"object","required":["frequency","city","state","website","logo","lastCheckedAt","id","name","countryCode","streamUrl","updatedAt","listenUrl","tags","availability"],"properties":{"frequency":{"type":["string","null"]},"city":{"type":["string","null"]},"state":{"type":["string","null"]},"website":{"type":["string","null"]},"logo":{"type":["string","null"]},"lastCheckedAt":{"type":["string","null"]},"id":{"type":"string"},"name":{"type":"string"},"countryCode":{"type":"string"},"streamUrl":{"type":"string"},"updatedAt":{"type":"string"},"listenUrl":{"type":"string"},"tags":{"type":"array","items":{"type":"string"}},"availability":{"type":"string","enum":["unknown"]}}},"Meta":{"type":"object","required":["updatedAt","stale"],"properties":{"updatedAt":{"type":"string","format":"date-time"},"stale":{"type":"boolean","description":"No station refreshed within six hours; retained records can be older."}}},"Pagination":{"type":"object","required":["total","limit","offset","nextOffset"],"properties":{"total":{"type":"integer"},"limit":{"type":"integer"},"offset":{"type":"integer"},"nextOffset":{"type":["integer","null"]}}},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"}}}}}}}}