API Docs
TheVibe exposes a simple REST API for image-to-music matching. The same endpoint powers the web app.
v1.1 BASE URL: http://localhost:8888Overview
The API accepts an image file along with mood, language, and optional lyric hint parameters. It runs a three-stage pipeline:
# Pipeline stages 1. Image Analysis → Gemini 2.5 Flash reads mood, energy, atmosphere 2. Query Generation → Gemini generates targeted Genius search queries 3. Song Search → Genius API + Spotify API enrich results
Authentication
No API key is required to call the endpoint. The server uses its own credentials (Gemini, Genius, Spotify) configured via .env. Rate limiting applies per IP address.
Rate Limiting
12 requests per minute per IP address. Exceeding this returns HTTP 429 with an error message.
POST /api/recommend
POST
/api/recommend
Analyzes an image and returns song recommendations matching the visual's mood and user preferences.
Accepts
multipart/form-data.
Request Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| image | File | required | Image file. Accepted: JPG, PNG, WebP, GIF. Max 16MB. Automatically compressed to 1200px. |
| mood | string | optional | Mood ID. One of: sad, angry, street, energetic, romantic, nostalgic, dark, calm, powerful, melancholic, happy, mysterious. Default: melancholic |
| language | string | optional | Language code. One of: any, tr, en, fr, de, es, ru, it, ja, ko, pt, ar, nl. Default: any |
| lyrics_hint | string | optional | A word, phrase, or concept to match in lyrics. Can be in any language — the AI will adapt it semantically. |
| song_count | integer | optional | Number of songs to return. Range: 1–12. Default: 6 |
Response Format
Success (200)
{
"success": true,
"songs": [
{
"title": "Song Title",
"artist": "Artist Name",
"full_title": "Artist Name - Song Title",
"url": "https://genius.com/...",
"image": "https://images.genius.com/...",
"spotify_url": "https://open.spotify.com/track/..." // null if not found
}
],
"analysis": {
"mood": "bittersweet nostalgia",
"energy": "low",
"dominant_colors": ["deep blue", "grey", "amber"],
"atmosphere": "...",
"genre_suggestions":["indie folk", "ambient"],
"bpm_range": "60-80",
"instruments": ["piano", "guitar"],
"era": "modern",
"keywords": ["longing", "rain", "memory"],
"specific_artists":["Bon Iver", "Sufjan Stevens"],
"scene_description":"A rainy city street at dusk..."
},
"queries_used": ["Bon Iver skinny love", "sad indie rainy", "..."],
"song_count": 6
}
Error
{
"success": false,
"error": "Error message"
}
Error Codes
| Status | Meaning |
|---|---|
| 400 | Missing or invalid image file |
| 429 | Rate limit exceeded (12 req/min per IP) |
| 500 | Internal error — Gemini, Genius, or Spotify API failure |
Examples
cURL
curl -X POST http://localhost:8888/api/recommend \ -F "image=@/path/to/photo.jpg" \ -F "mood=melancholic" \ -F "language=en" \ -F "lyrics_hint=rainy night" \ -F "song_count=6"
Python
import requests with open("photo.jpg", "rb") as f: resp = requests.post( "http://localhost:8888/api/recommend", files={"image": f}, data={ "mood": "melancholic", "language": "en", "lyrics_hint": "rainy night", "song_count": 6, } ) data = resp.json() for song in data["songs"]: print(f"{song['artist']} — {song['title']}") print(f" Spotify: {song['spotify_url']}")
JavaScript (fetch)
const fd = new FormData(); fd.append("image", fileInput.files[0]); fd.append("mood", "melancholic"); fd.append("language", "en"); fd.append("lyrics_hint", "rainy night"); fd.append("song_count", "6"); const res = await fetch("/api/recommend", { method: "POST", body: fd }); const data = await res.json(); data.songs.forEach(song => { console.log(`${song.artist} — ${song.title}`); });