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:8888

Overview

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

FieldTypeRequiredDescription
imageFilerequiredImage file. Accepted: JPG, PNG, WebP, GIF. Max 16MB. Automatically compressed to 1200px.
moodstringoptionalMood ID. One of: sad, angry, street, energetic, romantic, nostalgic, dark, calm, powerful, melancholic, happy, mysterious. Default: melancholic
languagestringoptionalLanguage code. One of: any, tr, en, fr, de, es, ru, it, ja, ko, pt, ar, nl. Default: any
lyrics_hintstringoptionalA word, phrase, or concept to match in lyrics. Can be in any language — the AI will adapt it semantically.
song_countintegeroptionalNumber 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

StatusMeaning
400Missing or invalid image file
429Rate limit exceeded (12 req/min per IP)
500Internal 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}`);
});