feat: Update index.html with all 44 endpoints in explorer section

- Stats counter: 35 → 44
- Explorer: 16 endpoints → 44 endpoints
- Added: trending/daily, trending/weekly, top, random, upcoming/countdown
- Added: seasonal, studio, tags, genre, year, status, format
- Added: character, staff, characters search, staff search
- Added: anime characters, relations, recommendations
- Added: batch episodes, sources, stream, download
- Added: compare, genre stats, calendar, timeline
- Added: health, stats, providers, openapi
- All endpoints with cURL, JavaScript, Python examples
This commit is contained in:
Sʜɪɴᴇɪ Nᴏᴜᴢᴇɴ
2026-06-25 12:15:22 +05:30
parent 10560e36c3
commit 6bda1d9c95
+59 -13
View File
@@ -10,7 +10,7 @@
<meta property="og:type" content="website" />
<meta property="og:url" content="https://mirurotvapi.vercel.app" />
<meta property="og:image" content="https://mirurotvapi.vercel.app/og-image.png" />
<meta property="og:description" content="Free RESTful API for anime streaming data. 35 endpoints, 12 providers, M3U8 streaming URLs. Powered by AniList GraphQL and Miruro." />
<meta property="og:description" content="Free RESTful API for anime streaming data. 44 endpoints, 12 providers, M3U8 streaming URLs. Powered by AniList GraphQL and Miruro." />
<meta property="og:site_name" content="MiruroAPI" />
<meta property="og:locale" content="en_US" />
@@ -26,13 +26,13 @@
<meta name="twitter:site" content="@Shineii86" />
<meta name="twitter:creator" content="@Shineii86" />
<meta name="twitter:title" content="MiruroAPI — Free Anime Streaming API" />
<meta name="twitter:description" content="Free RESTful API for anime streaming data. 35 endpoints, 12 providers, M3U8 streaming URLs." />
<meta name="twitter:description" content="Free RESTful API for anime streaming data. 44 endpoints, 12 providers, M3U8 streaming URLs." />
<meta name="twitter:image" content="https://mirurotvapi.vercel.app/og-image.png" />
<meta name="twitter:image:alt" content="MiruroAPI - Free Anime Streaming API" />
<meta name="twitter:domain" content="mirurotvapi.vercel.app" />
<!-- ──────────────── Generic Meta ──────────────── -->
<meta name="description" content="Free RESTful API for anime streaming data. 35 endpoints, 12 providers, M3U8 streaming URLs. Powered by AniList GraphQL and Miruro." />
<meta name="description" content="Free RESTful API for anime streaming data. 44 endpoints, 12 providers, M3U8 streaming URLs. Powered by AniList GraphQL and Miruro." />
<meta name="author" content="Shinei Nouzen" />
<meta name="keywords" content="anime api, free api, rest api, anime streaming, m3u8, anime data, anilist, miruro, episode streaming, sub, dub" />
<meta name="robots" content="index, follow" />
@@ -278,7 +278,7 @@
"@context": "https://schema.org",
"@type": "WebAPI",
"name": "MiruroAPI",
"description": "Free RESTful API for anime streaming data. 35 endpoints, 12 providers, M3U8 streaming URLs.",
"description": "Free RESTful API for anime streaming data. 44 endpoints, 12 providers, M3U8 streaming URLs.",
"url": "https://mirurotvapi.vercel.app",
"image": "https://mirurotvapi.vercel.app/og-image.png",
"documentation": "https://mirurotvapi.vercel.app/docs",
@@ -326,7 +326,7 @@
<section class="hero container">
<div class="hero-badge"><span class="dot"></span> Free &middot; No API key &middot; Open source</div>
<h1>The <span class="grad">Anime Streaming</span> API<br/>for Your Next Project</h1>
<p class="hero-sub">Search, discover, and stream anime with M3U8 URLs. Powered by AniList GraphQL + Miruro providers. 35 endpoints, 12 providers, zero config.</p>
<p class="hero-sub">Search, discover, and stream anime with M3U8 URLs. Powered by AniList GraphQL + Miruro providers. 44 endpoints, 12 providers, zero config.</p>
<div class="hero-actions">
<a href="#playground" class="btn btn-primary">
<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"/></svg>
@@ -370,7 +370,7 @@ fetch("https://mirurotvapi.vercel.app/api/search?query=naruto")
<section class="stats">
<div class="container">
<div class="stats-grid">
<div class="reveal"><div class="stat-value grad" data-count="35">0</div><div class="stat-label">API Endpoints</div></div>
<div class="reveal"><div class="stat-value grad" data-count="44">0</div><div class="stat-label">API Endpoints</div></div>
<div class="reveal reveal-delay-1"><div class="stat-value grad" data-count="12">0</div><div class="stat-label">Streaming Providers</div></div>
<div class="reveal reveal-delay-2"><div class="stat-value grad" data-count="5000">0</div><div class="stat-label">Anime Indexed</div></div>
<div class="reveal reveal-delay-3"><div class="stat-value grad">M3U8</div><div class="stat-label">Stream Format</div></div>
@@ -719,22 +719,68 @@ fetch("https://mirurotvapi.vercel.app/api/search?query=naruto")
/* ── Explorer ── */
const explorerData = [
// ---- FEATURE: Search & Discovery ----
{ id: 'search', title: 'Search', desc: 'Full-text anime search with 20+ fields per result. Paginated.', path: '/search?query={q}&page={n}&per_page={n}', params: [{ name: 'query', type: 'string', desc: 'Search query' }, { name: 'page', type: 'number', desc: 'Page (default 1)' }, { name: 'per_page', type: 'number', desc: 'Results per page (default 20)' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/search?query=naruto"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/search?query=naruto");\nconst data = await res.json();\nconsole.log(data.results);', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/search", params={"query": "naruto"})\nprint(r.json())' } },
{ id: 'suggestions', title: 'Suggestions', desc: 'Lightweight autocomplete for dropdowns. Max 8 results.', path: '/suggestions?query={q}', params: [{ name: 'query', type: 'string', desc: 'Partial query' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/suggestions?query=naru"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/suggestions?query=naru");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/suggestions", params={"query": "naru"})\nprint(r.json())' } },
{ id: 'info', title: 'Anime Info', desc: 'Everything AniList has — characters, staff, relations, recommendations, trailer, stats.', path: '/info/{anilistId}', params: [{ name: 'anilistId', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/info/20"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/info/20");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/info/20")\nprint(r.json())' } },
{ id: 'characters', title: 'Characters', desc: 'Paginated characters with Japanese voice actors.', path: '/characters/{anilistId}?page={n}', params: [{ name: 'anilistId', type: 'number', desc: 'AniList ID' }, { name: 'page', type: 'number', desc: 'Page (default 1)' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/characters/20"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/characters/20");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/characters/20")\nprint(r.json())' } },
{ id: 'relations', title: 'Relations', desc: 'Sequels, prequels, side stories, spin-offs.', path: '/relations/{anilistId}', params: [{ name: 'anilistId', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/relations/20"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/relations/20");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/relations/20")\nprint(r.json())' } },
{ id: 'recommendations', title: 'Recommendations', desc: 'Community recommendations sorted by rating.', path: '/recommendations/{anilistId}', params: [{ name: 'anilistId', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/recommendations/20"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/recommendations/20");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/recommendations/20")\nprint(r.json())' } },
{ id: 'episodes', title: 'Episodes', desc: 'Fetch all episodes from multiple providers (sub, dub, download).', path: '/episodes/{anilistId}', params: [{ name: 'anilistId', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/episodes/20"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/episodes/20");\nconst data = await res.json();\nconsole.log(data.providers);', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/episodes/20")\nprint(r.json())' } },
{ id: 'watch', title: 'Watch / Stream', desc: 'Get M3U8 streaming URL from episode ID. 12 providers.', path: '/watch/{provider}/{id}/{category}/{slug}', params: [{ name: 'provider', type: 'string', desc: 'Provider name (kiwi, pewe, etc.)' }, { name: 'id', type: 'string', desc: 'Episode ID' }, { name: 'category', type: 'string', desc: 'Category (sub, dub, raw)' }, { name: 'slug', type: 'string', desc: 'Episode slug' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/watch/kiwi/episode-id/sub/episode-slug"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/watch/kiwi/episode-id/sub/episode-slug");\nconst data = await res.json();\nconsole.log(data.streams[0].url);', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/watch/kiwi/episode-id/sub/episode-slug")\nprint(r.json())' } },
{ id: 'filter', title: 'Filter', desc: 'Filter by genre, tag, year, season, format, status, sort.', path: '/filter?genre={g}&format={f}&year={y}', params: [{ name: 'genre', type: 'string', desc: 'Genre name' }, { name: 'format', type: 'string', desc: 'TV, MOVIE, OVA, etc.' }, { name: 'year', type: 'number', desc: 'Release year' }, { name: 'season', type: 'string', desc: 'WINTER, SPRING, SUMMER, FALL' }, { name: 'status', type: 'string', desc: 'RELEASING, FINISHED, NOT_YET_RELEASED' }, { name: 'sort', type: 'string', desc: 'POPULARITY_DESC, SCORE_DESC, etc.' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/filter?genre=Action&format=TV"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/filter?genre=Action&format=TV");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/filter", params={"genre": "Action", "format": "TV"})\nprint(r.json())' } },
{ id: 'multi-search', title: 'Multi-Search', desc: 'Combined search with genre, status, year, format filters.', path: '/multi-search?q={q}&genre={g}', params: [{ name: 'q', type: 'string', desc: 'Search query' }, { name: 'genre', type: 'string', desc: 'Genre filter' }, { name: 'status', type: 'string', desc: 'Status filter' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/multi-search?q=naruto&genre=Action"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/multi-search?q=naruto&genre=Action");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/multi-search", params={"q": "naruto", "genre": "Action"})\nprint(r.json())' } },
// ---- FEATURE: Collections ----
{ id: 'trending', title: 'Trending', desc: 'Currently trending anime across the community.', path: '/trending', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/trending"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/trending");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/trending")\nprint(r.json())' } },
{ id: 'trending-daily', title: 'Trending Daily', desc: 'Daily trending anime rotation.', path: '/trending/daily', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/trending/daily"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/trending/daily");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/trending/daily")\nprint(r.json())' } },
{ id: 'trending-weekly', title: 'Trending Weekly', desc: 'Weekly trending anime rotation.', path: '/trending/weekly', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/trending/weekly"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/trending/weekly");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/trending/weekly")\nprint(r.json())' } },
{ id: 'popular', title: 'Popular', desc: 'Most popular anime of all time by user count.', path: '/popular', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/popular"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/popular");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/popular")\nprint(r.json())' } },
{ id: 'top', title: 'Top', desc: 'Top rated anime by AniList score.', path: '/top', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/top"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/top");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/top")\nprint(r.json())' } },
{ id: 'upcoming', title: 'Upcoming', desc: 'Most anticipated anime that haven\'t aired yet.', path: '/upcoming', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/upcoming"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/upcoming");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/upcoming")\nprint(r.json())' } },
{ id: 'recent', title: 'Recent Episodes', desc: 'Currently airing / this season\'s anime.', path: '/recent', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/recent"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/recent");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/recent")\nprint(r.json())' } },
{ id: 'spotlight', title: 'Spotlight', desc: 'Top 10 trending + popular. Perfect for hero banners.', path: '/spotlight', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/spotlight"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/spotlight");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/spotlight")\nprint(r.json())' } },
{ id: 'schedule', title: 'Schedule', desc: 'Upcoming episodes with UNIX timestamps.', path: '/schedule', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/schedule"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/schedule");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/schedule")\nprint(r.json())' } },
{ id: 'filter', title: 'Filter', desc: 'Filter by genre, tag, year, season, format, status, sort.', path: '/filter?genre={g}&format={f}&year={y}', params: [{ name: 'genre', type: 'number', desc: 'AniList genre ID' }, { name: 'format', type: 'string', desc: 'TV, MOVIE, OVA, etc.' }, { name: 'year', type: 'number', desc: 'Release year' }, { name: 'season', type: 'string', desc: 'WINTER, SPRING, SUMMER, FALL' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/filter?genre=1&format=TV"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/filter?genre=1&format=TV");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/filter", params={"genre": "1", "format": "TV"})\nprint(r.json())' } },
{ id: 'random', title: 'Random', desc: 'Random anime for discovery. Changes each request.', path: '/random', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/random"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/random");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/random")\nprint(r.json())' } },
{ id: 'upcoming-countdown', title: 'Upcoming Countdown', desc: 'Next 10 episodes airing soon with countdown.', path: '/upcoming/countdown', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/upcoming/countdown"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/upcoming/countdown");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/upcoming/countdown")\nprint(r.json())' } },
// ---- FEATURE: Seasonal & Studio ----
{ id: 'season', title: 'Seasonal', desc: 'Anime by year and season.', path: '/season/{year}/{season}', params: [{ name: 'year', type: 'number', desc: 'Release year' }, { name: 'season', type: 'string', desc: 'WINTER, SPRING, SUMMER, FALL' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/season/2025/spring"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/season/2025/spring");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/season/2025/spring")\nprint(r.json())' } },
{ id: 'studio', title: 'Studio', desc: 'Anime by studio name (MAPPA, Ufotable, etc.).', path: '/studio/{name}', params: [{ name: 'name', type: 'string', desc: 'Studio name' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/studio/MAPPA"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/studio/MAPPA");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/studio/MAPPA")\nprint(r.json())' } },
// ---- FEATURE: Genres & Tags ----
{ id: 'genres', title: 'Genres', desc: 'List all available genres with AniList IDs.', path: '/genres', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/genres"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/genres");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/genres")\nprint(r.json())' } },
{ id: 'tags', title: 'Tags', desc: 'List all available tags (violet, mind game, etc.).', path: '/tags', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/tags"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/tags");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/tags")\nprint(r.json())' } },
{ id: 'genre', title: 'Genre', desc: 'Anime by specific genre name.', path: '/genre/{name}', params: [{ name: 'name', type: 'string', desc: 'Genre name (Action, Romance, etc.)' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/genre/Action"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/genre/Action");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/genre/Action")\nprint(r.json())' } },
{ id: 'year', title: 'Year', desc: 'Anime by release year.', path: '/year/{year}', params: [{ name: 'year', type: 'number', desc: 'Release year' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/year/2024"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/year/2024");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/year/2024")\nprint(r.json())' } },
{ id: 'status', title: 'Status', desc: 'Anime by airing status.', path: '/status/{status}', params: [{ name: 'status', type: 'string', desc: 'RELEASING, FINISHED, NOT_YET_RELEASED' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/status/RELEASING"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/status/RELEASING");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/status/RELEASING")\nprint(r.json())' } },
{ id: 'format', title: 'Format', desc: 'Anime by format type.', path: '/format/{format}', params: [{ name: 'format', type: 'string', desc: 'TV, MOVIE, OVA, ONA, SPECIAL' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/format/MOVIE"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/format/MOVIE");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/format/MOVIE")\nprint(r.json())' } },
// ---- FEATURE: Character & Staff ----
{ id: 'character', title: 'Character', desc: 'Character detail with animeography and voice actors.', path: '/character/{id}', params: [{ name: 'id', type: 'number', desc: 'AniList character ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/character/1"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/character/1");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/character/1")\nprint(r.json())' } },
{ id: 'staff', title: 'Staff', desc: 'Staff detail with works and roles.', path: '/staff/{id}', params: [{ name: 'id', type: 'number', desc: 'AniList staff ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/staff/1"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/staff/1");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/staff/1")\nprint(r.json())' } },
{ id: 'characters-search', title: 'Characters Search', desc: 'Search characters by name.', path: '/characters?query={q}', params: [{ name: 'query', type: 'string', desc: 'Character name' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/characters?query=kaneki"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/characters?query=kaneki");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/characters", params={"query": "kaneki"})\nprint(r.json())' } },
{ id: 'staff-search', title: 'Staff Search', desc: 'Search staff by name.', path: '/staff?query={q}', params: [{ name: 'query', type: 'string', desc: 'Staff name' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/staff?query=oda"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/staff?query=oda");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/staff", params={"query": "oda"})\nprint(r.json())' } },
// ---- FEATURE: Anime Details ----
{ id: 'info', title: 'Anime Info', desc: 'Everything AniList has — characters, staff, relations, recommendations, trailer, stats.', path: '/info/{anilistId}', params: [{ name: 'anilistId', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/info/20"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/info/20");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/info/20")\nprint(r.json())' } },
{ id: 'anime-characters', title: 'Anime Characters', desc: 'Characters for an anime with voice actors.', path: '/anime/{id}/characters', params: [{ name: 'id', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/anime/20/characters"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/anime/20/characters");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/anime/20/characters")\nprint(r.json())' } },
{ id: 'relations', title: 'Relations', desc: 'Sequels, prequels, side stories, spin-offs.', path: '/anime/{id}/relations', params: [{ name: 'id', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/anime/20/relations"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/anime/20/relations");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/anime/20/relations")\nprint(r.json())' } },
{ id: 'recommendations', title: 'Recommendations', desc: 'Community recommendations sorted by rating.', path: '/anime/{id}/recommendations', params: [{ name: 'id', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/anime/20/recommendations"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/anime/20/recommendations");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/anime/20/recommendations")\nprint(r.json())' } },
// ---- FEATURE: Streaming ----
{ id: 'episodes', title: 'Episodes', desc: 'Fetch all episodes from multiple providers (sub, dub, download).', path: '/episodes/{anilistId}', params: [{ name: 'anilistId', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/episodes/20"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/episodes/20");\nconst data = await res.json();\nconsole.log(data.providers);', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/episodes/20")\nprint(r.json())' } },
{ id: 'batch-episodes', title: 'Batch Episodes', desc: 'Fetch sources for multiple episodes in one request.', path: '/episodes/{id}/batch?provider={p}&category={c}&slugs={s}', params: [{ name: 'id', type: 'number', desc: 'AniList ID' }, { name: 'provider', type: 'string', desc: 'Provider name' }, { name: 'category', type: 'string', desc: 'sub, dub, raw' }, { name: 'slugs', type: 'string', desc: 'Comma-separated slugs' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/episodes/20/batch?provider=kiwi&category=sub&slugs=animepahe-1,animepahe-2"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/episodes/20/batch?provider=kiwi&category=sub&slugs=animepahe-1,animepahe-2");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/episodes/20/batch", params={"provider": "kiwi", "category": "sub", "slugs": "animepahe-1,animepahe-2"})\nprint(r.json())' } },
{ id: 'sources', title: 'Sources', desc: 'Detailed streaming sources for an episode.', path: '/sources?episodeId={e}&provider={p}&anilistId={a}&category={c}', params: [{ name: 'episodeId', type: 'string', desc: 'Episode ID' }, { name: 'provider', type: 'string', desc: 'Provider name' }, { name: 'anilistId', type: 'number', desc: 'AniList ID' }, { name: 'category', type: 'string', desc: 'sub, dub, raw' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/sources?episodeId=ep1&provider=kiwi&anilistId=20&category=sub"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/sources?episodeId=ep1&provider=kiwi&anilistId=20&category=sub");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/sources", params={"episodeId": "ep1", "provider": "kiwi", "anilistId": "20", "category": "sub"})\nprint(r.json())' } },
{ id: 'stream', title: 'Stream', desc: 'Stream URL with quality fallback. Returns best available quality.', path: '/stream?provider={p}&anilistId={a}&category={c}&slug={s}&quality={q}', params: [{ name: 'provider', type: 'string', desc: 'Provider name' }, { name: 'anilistId', type: 'number', desc: 'AniList ID' }, { name: 'category', type: 'string', desc: 'sub, dub, raw' }, { name: 'slug', type: 'string', desc: 'Episode slug' }, { name: 'quality', type: 'string', desc: '1080p, 720p, etc.' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/stream?provider=kiwi&anilistId=20&category=sub&slug=animepahe-1&quality=1080p"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/stream?provider=kiwi&anilistId=20&category=sub&slug=animepahe-1&quality=1080p");\nconst data = await res.json();\nconsole.log(data.results.bestStream.url);', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/stream", params={"provider": "kiwi", "anilistId": "20", "category": "sub", "slug": "animepahe-1"})\nprint(r.json())' } },
{ id: 'download', title: 'Download', desc: 'Download URL for an episode.', path: '/download?provider={p}&anilistId={a}&category={c}&slug={s}', params: [{ name: 'provider', type: 'string', desc: 'Provider name' }, { name: 'anilistId', type: 'number', desc: 'AniList ID' }, { name: 'category', type: 'string', desc: 'sub, dub, raw' }, { name: 'slug', type: 'string', desc: 'Episode slug' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/download?provider=kiwi&anilistId=20&category=sub&slug=animepahe-1"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/download?provider=kiwi&anilistId=20&category=sub&slug=animepahe-1");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/download", params={"provider": "kiwi", "anilistId": "20", "category": "sub", "slug": "animepahe-1"})\nprint(r.json())' } },
{ id: 'watch', title: 'Watch / Stream', desc: 'Get M3U8 streaming URL from episode ID. 12 providers. Returns streams, subtitles, and best stream.', path: '/watch/{provider}/{id}/{category}/{slug}', params: [{ name: 'provider', type: 'string', desc: 'Provider name (kiwi, pewe, etc.)' }, { name: 'id', type: 'string', desc: 'AniList ID' }, { name: 'category', type: 'string', desc: 'Category (sub, dub, raw)' }, { name: 'slug', type: 'string', desc: 'Episode slug' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/watch/kiwi/20/sub/animepahe-1"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/watch/kiwi/20/sub/animepahe-1");\nconst data = await res.json();\nconsole.log(data.results.bestStream.url);', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/watch/kiwi/20/sub/animepahe-1")\nprint(r.json())' } },
// ---- FEATURE: Utility ----
{ id: 'compare', title: 'Compare', desc: 'Compare two anime side by side.', path: '/compare/{id1}/{id2}', params: [{ name: 'id1', type: 'number', desc: 'First AniList ID' }, { name: 'id2', type: 'number', desc: 'Second AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/compare/20/21"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/compare/20/21");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/compare/20/21")\nprint(r.json())' } },
{ id: 'stats-genre', title: 'Genre Stats', desc: 'Genre distribution statistics across the database.', path: '/stats/genre', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/stats/genre"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/stats/genre");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/stats/genre")\nprint(r.json())' } },
{ id: 'calendar', title: 'Calendar', desc: 'Monthly airing calendar with episode counts.', path: '/calendar?year={y}&month={m}', params: [{ name: 'year', type: 'number', desc: 'Year (default current)' }, { name: 'month', type: 'number', desc: 'Month 1-12 (default current)' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/calendar?year=2025&month=6"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/calendar?year=2025&month=6");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/calendar", params={"year": "2025", "month": "6"})\nprint(r.json())' } },
{ id: 'timeline', title: 'Timeline', desc: 'Anime timeline with episodes and airing dates.', path: '/timeline/{id}', params: [{ name: 'id', type: 'number', desc: 'AniList ID' }], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/timeline/20"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/timeline/20");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/timeline/20")\nprint(r.json())' } },
// ---- FEATURE: System ----
{ id: 'health', title: 'Health', desc: 'Health check — returns version, uptime, and environment.', path: '/health', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/health"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/health");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/health")\nprint(r.json())' } },
{ id: 'stats', title: 'Stats', desc: 'API statistics — total requests, cache size, uptime.', path: '/stats', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/stats"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/stats");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/stats")\nprint(r.json())' } },
{ id: 'providers', title: 'Providers', desc: 'List all available streaming providers.', path: '/providers', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/providers"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/providers");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/providers")\nprint(r.json())' } },
{ id: 'openapi', title: 'OpenAPI Spec', desc: 'Raw OpenAPI 3.0.3 specification.', path: '/openapi', params: [], code: { curl: 'curl "https://mirurotvapi.vercel.app/api/openapi"', js: 'const res = await fetch("https://mirurotvapi.vercel.app/api/openapi");\nconst data = await res.json();', python: 'import requests\nr = requests.get("https://mirurotvapi.vercel.app/api/openapi")\nprint(r.json())' } },
];
const navEl = document.getElementById('explorerNav');
const panelEl = document.getElementById('explorerPanel');