{"components":{"schemas":{"ApiError":{"properties":{"error":{"properties":{"code":{"description":"Machine-readable error code.","type":"string"},"hint":{"description":"Optional resolution hint for agents.","type":"string"},"message":{"description":"Human-readable error message.","type":"string"}},"required":["code","message"],"type":"object"}},"required":["error"],"type":"object"}}},"externalDocs":{"description":"the purple life API","url":"https://the.purple.life/developers"},"info":{"contact":{"email":"support@the.purple.life","name":"the purple life support","url":"https://the.purple.life/contact"},"description":"Public REST API for the purple life — free streaming of original music by the purple life (single-artist catalog), plus search and radio. Authentication: none required (no API key or Authorization header). Verify with GET /api/v1/health. Versioning uses the /api/v1 path prefix; breaking changes ship under a new path version; deprecated operations are marked deprecated in this document and may send Deprecation response headers. Rate limiting: public /api/v1 routes are limited per client IP and endpoint scope (typically tens of requests per minute for many public reads); over limit returns HTTP 429 with JSON error code rate_limited and a Retry-After header in seconds — clients and agents must honor Retry-After and must not retry sooner. Prefer Markdown page exports (Accept: text/markdown or .md) for lyrics and backstories. Human docs: /developers (overview, including rate limiting) and /developers/{handle} per operation. Also see /agent.txt.","title":"the purple life public API","version":"1.0.0"},"openapi":"3.1.0","paths":{"/api/openapi.json":{"get":{"description":"OpenAPI 3.1 document for public agent-facing REST endpoints (alias of /openapi.json).","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-api-openapi-json"},"operationId":"get_api_openapi_json","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"info":{"title":"the purple life public API","version":"1.0.0"},"openapi":"3.1.0","paths":{}},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"OpenAPI 3.1 document for public agent-facing REST endpoints (alias of /openapi.json).","tags":["catalog"]}},"/api/v1/albums/{handle}/download":{"get":{"description":"Redirects to the public album zip on the CDN.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-albums-handle-download"},"operationId":"get_albums_handle_download","parameters":[{"description":"Path parameter `handle`.","in":"path","name":"handle","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":"Redirect to the CDN download URL. No JSON body.","schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Redirects to the public album zip on the CDN.","tags":["catalog"]}},"/api/v1/double-singles/{handle}/download":{"get":{"description":"Redirects to the public double-single zip on the CDN.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-double-singles-handle-download"},"operationId":"get_double_singles_handle_download","parameters":[{"description":"Path parameter `handle`.","in":"path","name":"handle","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":"Redirect to the CDN download URL. No JSON body.","schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Redirects to the public double-single zip on the CDN.","tags":["catalog"]}},"/api/v1/eps/{handle}/download":{"get":{"description":"Redirects to the public EP zip on the CDN.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-eps-handle-download"},"operationId":"get_eps_handle_download","parameters":[{"description":"Path parameter `handle`.","in":"path","name":"handle","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":"Redirect to the CDN download URL. No JSON body.","schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Redirects to the public EP zip on the CDN.","tags":["catalog"]}},"/api/v1/health":{"get":{"description":"Public process health. version is the build SHA, or unknown when it is not set.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-health"},"operationId":"get_health","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"environment":"production","ok":true,"timestamp":"2026-10-08T17:00:00.000Z","version":"unknown"},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Public process health. version is the build SHA, or unknown when it is not set.","tags":["health"]}},"/api/v1/leaderboard":{"get":{"description":"Public leaderboard page. section is required.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-leaderboard"},"operationId":"get_leaderboard","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"items":[],"page":1,"pageSize":20,"range":"30d","section":"song","sort":"streams","totalRanked":0},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Public leaderboard page. section is required.","tags":["catalog"]}},"/api/v1/push/subscribe":{"post":{"description":"Stores a web push subscription. Rate limited.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/post-push-subscribe"},"operationId":"post_push_subscribe","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Stores a web push subscription. Rate limited.","tags":["catalog"]}},"/api/v1/push/unsubscribe":{"post":{"description":"Removes a web push subscription.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/post-push-unsubscribe"},"operationId":"post_push_unsubscribe","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"ok":true},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Removes a web push subscription.","tags":["catalog"]}},"/api/v1/radio/clock":{"get":{"description":"Returns the server clock used to sync the radio player.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-radio-clock"},"operationId":"get_radio_clock","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"serverUnixMs":1759942800000},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Returns the server clock used to sync the radio player.","tags":["radio"]}},"/api/v1/radio/listeners":{"get":{"description":"Active radio listener count only (`{ \"number\": <count> }`). Use this when you need the count without the fuller radio sync payload from GET /api/v1/radio/status.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-radio-listeners"},"operationId":"get_radio_listeners","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"number":0},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Active radio listener count only (`{ \"number\": <count> }`). Use this when you need the count without the fuller radio sy","tags":["radio"]}},"/api/v1/radio/now-playing":{"get":{"description":"Returns the track currently on the radio clock.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-radio-now-playing"},"operationId":"get_radio_now_playing","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"nextTrackStartsAt":"2026-10-08T17:03:00.000Z","positionSeconds":12,"serverTime":"2026-10-08T17:00:00.000Z","track":null,"trackStartedAt":"2026-10-08T17:00:00.000Z"},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Returns the track currently on the radio clock.","tags":["radio"]}},"/api/v1/radio/presence":{"post":{"description":"Updates radio listener presence for a client session id.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/post-radio-presence"},"operationId":"post_radio_presence","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"count":1,"ok":true},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Updates radio listener presence for a client session id.","tags":["radio"]}},"/api/v1/radio/status":{"get":{"description":"Radio sync payload (track timing, seed, and listenerCount). Prefer GET /api/v1/radio/listeners when you only need the active listener count.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-radio-status"},"operationId":"get_radio_status","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"listenerCount":1,"positionSeconds":12,"serverUnixMs":1759942800000,"status":"ok","trackIndex":0},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Radio sync payload (track timing, seed, and listenerCount). Prefer GET /api/v1/radio/listeners when you only need the ac","tags":["radio"]}},"/api/v1/radio/tune-in":{"get":{"description":"Full radio sync payload for a new listener.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-radio-tune-in"},"operationId":"get_radio_tune_in","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"listenerCount":1,"nextTrackStartsAt":"2026-10-08T17:03:00.000Z","positionSeconds":0,"radioPlaylist":[],"seed":"example-seed","serverTime":"2026-10-08T17:00:00.000Z","serverUnixMs":1759942800000,"track":null,"trackIndex":0,"trackStartedAt":"2026-10-08T17:00:00.000Z"},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Full radio sync payload for a new listener.","tags":["radio"]}},"/api/v1/recently-played":{"get":{"description":"Recently qualified public streams.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-recently-played"},"operationId":"get_recently_played","parameters":[],"responses":{"200":{"content":{"application/json":{"example":{"cachedUntilSec":180,"items":[{"artist":"Example Artist","artworkUrl":null,"canDownload":true,"durationSeconds":180,"handle":"example-handle","hasLyrics":false,"resourceType":"song","title":"Example"}]},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Recently qualified public streams.","tags":["catalog"]}},"/api/v1/search":{"get":{"description":"Public catalog search.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-search"},"operationId":"get_search","parameters":[{"description":"Search query string.","in":"query","name":"q","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"query":"purple","results":[{"artistName":"Example Artist","artworkUrl":null,"genres":[],"href":"/catalog/songs/example-handle","id":"00000000-0000-4000-8000-000000000000","recordLabelName":"Example Label","releaseAt":"2026-10-08T00:00:00.000Z","resourceType":"song","slug":"example-handle","title":"Example","versionLabel":null}],"total":1},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Public catalog search.","tags":["search"]}},"/api/v1/search/suggest":{"get":{"description":"Short public search suggestions. limit max is 20.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-search-suggest"},"operationId":"get_search_suggest","parameters":[{"description":"Search query string.","in":"query","name":"q","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":{"query":"purple","results":[],"total":0},"schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Short public search suggestions. limit max is 20.","tags":["search"]}},"/api/v1/songs/{handle}/audio":{"get":{"description":"Redirects to the public streaming audio URL.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-songs-handle-audio"},"operationId":"get_songs_handle_audio","parameters":[{"description":"Path parameter `handle`.","in":"path","name":"handle","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":"308 redirect to the CDN stream URL. No JSON body.","schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Redirects to the public streaming audio URL.","tags":["catalog"]}},"/api/v1/songs/{handle}/download":{"get":{"description":"Redirects to the public song download on the CDN.","externalDocs":{"description":"Human docs for this operation","url":"https://the.purple.life/developers/get-songs-handle-download"},"operationId":"get_songs_handle_download","parameters":[{"description":"Path parameter `handle`.","in":"path","name":"handle","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"example":"Redirect to the CDN download URL. No JSON body.","schema":{"additionalProperties":true,"type":"object"}}},"description":"Successful response."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Bad request."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Not found."},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"description":"Rate limited (error.code typically rate_limited). Honor the Retry-After header (seconds) and do not retry sooner.","headers":{"Retry-After":{"description":"Whole seconds to wait before retrying this request.","required":true,"schema":{"minimum":1,"type":"integer"}}}}},"summary":"Redirects to the public song download on the CDN.","tags":["catalog"]}}},"servers":[{"description":"Production","url":"https://the.purple.life/"}]}