Public Tagging API Documentation

The V4V Music Public Tagging API provides external access to the music tagging system, allowing third-party applications to discover, retrieve, and contribute tags to music items across the RSS ecosystem. This API follows the v4vTags pattern for simplicity and interoperability.

🔑 API Keys

Table of Contents

Overview

Design Philosophy

  • ✓ Simple: Easy to understand and implement
  • ✓ Interoperable: Works with any RSS music application
  • ✓ Secure: API key protection for write operations
  • ✓ RSS-Compatible: Uses standard RSS identifiers

Authentication Model

  • Read No authentication required (anonymous access)
  • Write Valid API key required
  • Rate Limiting Different limits for authenticated vs anonymous users

Base URL

https://v4vmusic.com

Authentication

API Keys

To submit tags to the system, you need a valid API key. API keys can be obtained by:

  1. Creating an account on the V4V Music platform
  2. Visiting the API Keys management page
  3. Generating a new API key with appropriate permissions

API Key Format

API keys follow this format:

v4v_<32 random base64url characters>

Example: v4v_b4cr2eI2fBtTGJ-A9s9oR-MEGlSOhMLBLe1IncQZWWw

Using API Keys

API keys can be provided in two ways:

Header Method (Recommended)

curl -H "x-api-key: v4v_your_api_key_here" \
     https://v4vmusic.com/api/public/items/byGuid/05b75483-9f5b-5236-bd66-69e9d3e1b995/c56c5b2b-fa79-4cd7-ae23-55cb207b103b/tags

Body Method (for POST requests)

{
  "tags": ["rock", "metal"],
  "apiKey": "v4v_your_api_key_here"
}

Rate Limiting

Limits

  • Anonymous users: 100 requests per hour
  • Authenticated users: 1000 requests per hour
  • Admin users: 5000 requests per hour

Rate Limit Headers

All responses include rate limit information:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1640995200

API Endpoints

GET /api/public/tags

Returns a simple array of all available tag names, sorted alphabetically.

curl https://v4vmusic.com/api/public/tags

Response

[
  "ambient",
  "blues", 
  "classical",
  "country",
  "electronic",
  "folk",
  "hip-hop",
  "jazz",
  "metal",
  "pop",
  "rap",
  "reggae",
  "rock",
  "soul"
]

GET /api/public/tags/popular

Returns popular tags with usage counts, sorted by count descending. Useful for tag suggestions, trending tags, and discovery features.

Query Parameters

Parameter Type Default Description
limit integer 100 Number of tags to return (max: 500)
curl https://v4vmusic.com/api/public/tags/popular
curl https://v4vmusic.com/api/public/tags/popular?limit=50

Response

{
  "tags": [
    { "name": "rock", "count": 150 },
    { "name": "indie", "count": 120 },
    { "name": "electronic", "count": 95 },
    { "name": "jazz", "count": 80 },
    { "name": "folk", "count": 65 }
  ],
  "total": 5,
  "hasMore": true
}

Response Fields

Field Type Description
tags array Array of tag objects with name and count
total integer Number of tags returned in this response
hasMore boolean Whether more tags exist beyond the limit

GET /api/public/items/bytag/{tagName}

Returns all items (songs, albums, playlists) that have been tagged with the specified tag.

curl https://v4vmusic.com/api/public/items/bytag/rock

Response

[
  {
    "feedGuid": "acddbb03-064b-5098-87ca-9b146beb12e8",
    "itemGuid": "baa182e9-d088-4cc1-a3f7-e4af48ff112a",
    "feedUrl": "https://ableandthewolf.com/static/media/feed.xml",
    "title": "Stay Awhile",
    "artistName": "Able and The Wolf",
    "mp3Url": "https://ableandthewolf.com/static/media/music/04_StayAwhile.mp3",
    "image": "https://ableandthewolf.com/static/media/04_StayAwhile.dfbfd4a349471a817e3a.jpg"
  },
  {
    "feedGuid": "fc815bcf-3639-5395-ba7d-fa217ec93d32",
    "itemGuid": "b2a61b9f-4dc8-40e3-a849-e7fe96d4e843",
    "feedUrl": "https://music.behindthesch3m3s.com/wp-content/uploads/Delta_OG/Aged_Friends_and_Old_Whiskey/aged_friends_old_whiskey.xml",
    "title": "The Devil Never Change",
    "artistName": "Delta OG",
    "mp3Url": "https://music.behindthesch3m3s.com/wp-content/uploads/Delta_OG/Aged_Friends_and_Old_Whiskey/The%20Devil%20Never%20Change.wav",
    "image": "https://music.behindthesch3m3s.com/wp-content/uploads/Delta_OG/Aged_Friends_and_Old_Whiskey/deltaog-bg.png"
  }
]

GET /api/public/items/byGuid/{feedGuid}/{itemGuid}

Retrieve a specific item by its RSS identifiers. Returns item details including tags.

curl https://v4vmusic.com/api/public/items/byGuid/05b75483-9f5b-5236-bd66-69e9d3e1b995/c56c5b2b-fa79-4cd7-ae23-55cb207b103b

Response

{
  "id": "song-123",
  "feedGuid": "05b75483-9f5b-5236-bd66-69e9d3e1b995",
  "itemGuid": "c56c5b2b-fa79-4cd7-ae23-55cb207b103b",
  "feedUrl": "https://example.com/feed.xml",
  "title": "Example Song",
  "artistName": "Example Artist",
  "mp3Url": "https://example.com/song.mp3",
  "image": "https://example.com/cover.jpg",
  "itemType": "song",
  "tags": ["rock", "indie"]
}

POST /api/public/items/byGuid/{feedGuid}/{itemGuid}/tags

Add tags to a specific item (requires API key).

curl -X POST \
  -H "Content-Type: application/json" \
  -H "x-api-key: v4v_your_api_key_here" \
  -d '{"tags": ["rock", "metal"]}' \
  https://v4vmusic.com/api/public/items/byGuid/05b75483-9f5b-5236-bd66-69e9d3e1b995/c56c5b2b-fa79-4cd7-ae23-55cb207b103b/tags

Response

{
  "success": true,
  "message": "Tags added successfully",
  "itemId": "song-123",
  "itemType": "song",
  "tagsAdded": ["rock", "metal"],
  "totalTags": 2
}

GET /api/public/items/byFeedGuid/{feedGuid}

Get all items from a specific feed.

curl https://v4vmusic.com/api/public/items/byFeedGuid/05b75483-9f5b-5236-bd66-69e9d3e1b995

Response

[
  {
    "feedGuid": "05b75483-9f5b-5236-bd66-69e9d3e1b995",
    "itemGuid": "c56c5b2b-fa79-4cd7-ae23-55cb207b103b",
    "feedUrl": "https://example.com/feed.xml",
    "title": "Song One",
    "artistName": "Example Artist",
    "mp3Url": "https://example.com/song1.mp3",
    "image": "https://example.com/cover.jpg"
  },
  {
    "feedGuid": "05b75483-9f5b-5236-bd66-69e9d3e1b995",
    "itemGuid": "d67d6c3c-gb80-5de8-bf34-66dc208c214c",
    "feedUrl": "https://example.com/feed.xml",
    "title": "Song Two",
    "artistName": "Example Artist",
    "mp3Url": "https://example.com/song2.mp3",
    "image": "https://example.com/cover.jpg"
  }
]

POST /api/public/items/byFeedGuid/{feedGuid}/tags

Add tags to ALL items in a feed/album (requires API key). Useful for bulk tagging entire albums.

curl -X POST \
  -H "Content-Type: application/json" \
  -H "x-api-key: v4v_your_api_key_here" \
  -d '{"tags": ["indie", "alternative"]}' \
  https://v4vmusic.com/api/public/items/byFeedGuid/05b75483-9f5b-5236-bd66-69e9d3e1b995/tags

Response

{
  "success": true,
  "message": "Tags added to 12 items",
  "feedGuid": "05b75483-9f5b-5236-bd66-69e9d3e1b995",
  "tagsAdded": ["indie", "alternative"],
  "itemsUpdated": 12
}

GET /api/public/items/{id}/tags

Get all tags for a specific item by internal ID. The item type can be optionally specified via query parameter.

curl https://v4vmusic.com/api/public/items/song-123/tags
curl https://v4vmusic.com/api/public/items/song-123/tags?itemType=song

Response

{
  "itemId": "song-123",
  "itemType": "song",
  "tags": [
    {
      "id": 1,
      "tagId": 42,
      "tag": {
        "id": 42,
        "name": "rock"
      }
    },
    {
      "id": 2,
      "tagId": 15,
      "tag": {
        "id": 15,
        "name": "indie"
      }
    }
  ],
  "total": 2
}

POST /api/public/items/{id}/tags

Add tags to a specific item by internal ID (requires API key in body).

curl -X POST \
  -H "Content-Type: application/json" \
  -d '{"tags": ["rock", "metal"], "apiKey": "v4v_your_api_key_here"}' \
  https://v4vmusic.com/api/public/items/song-123/tags

Response

{
  "itemId": "song-123",
  "itemType": "song",
  "addedTags": ["rock", "metal"],
  "success": true,
  "message": "Tags submitted successfully",
  "result": {
    "itemTags": 2,
    "createdTags": 0,
    "updatedTags": 2
  }
}

Data Models

Tags List Response

The GET /api/public/tags endpoint returns a simple array of tag name strings:

["ambient", "blues", "classical", "rock", "soul"]

Item Object

Field Type Description
id string Internal item identifier
feedGuid string RSS feed identifier (globally unique)
itemGuid string RSS item identifier (unique within feed)
feedUrl string Original RSS feed URL
title string Item title
artistName string Artist/author name
mp3Url string (optional) Audio file URL (songs only)
image string (optional) Song/album cover art URL
itemType string Type of item: "song", "album", or "playlist"
tags array (optional) Array of tag names (included when fetching by GUID)

id

Type: string

Description: Internal item identifier

feedGuid

Type: string

Description: RSS feed identifier (globally unique)

itemGuid

Type: string

Description: RSS item identifier (unique within feed)

feedUrl

Type: string

Description: Original RSS feed URL

title

Type: string

Description: Item title

artistName

Type: string

Description: Artist/author name

mp3Url

Type: string (optional)

Description: Audio file URL (songs only)

image

Type: string (optional)

Description: Song/album cover art URL

itemType

Type: string

Description: Type of item: "song", "album", or "playlist"

tags

Type: array (optional)

Description: Array of tag names (included when fetching by GUID)

Error Handling

HTTP Status Codes

Code Description
200 Success
400 Bad Request - Invalid parameters
401 Unauthorized - Invalid or missing API key
403 Forbidden - Insufficient permissions
404 Not Found - Resource doesn't exist
429 Too Many Requests - Rate limit exceeded
500 Internal Server Error

200

Description: Success

400

Description: Bad Request - Invalid parameters

401

Description: Unauthorized - Invalid or missing API key

403

Description: Forbidden - Insufficient permissions

404

Description: Not Found - Resource doesn't exist

429

Description: Too Many Requests - Rate limit exceeded

500

Description: Internal Server Error

Error Response Format

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid tag format",
    "details": {
      "field": "tags",
      "issue": "Tag 'rock music' contains spaces"
    }
  }
}

Integration Examples

JavaScript (Fetch API)

// Get all tags
const response = await fetch('https://v4vmusic.com/api/public/tags');
const data = await response.json();

// Add tags to an item
const addTags = async (feedGuid, itemGuid, tags, apiKey) => {
  const response = await fetch(
    `https://v4vmusic.com/api/public/items/byGuid/${feedGuid}/${itemGuid}/tags`,
    {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'x-api-key': apiKey
      },
      body: JSON.stringify({ tags })
    }
  );
  return response.json();
};

Python (requests)

import requests

# Get all tags
response = requests.get('https://v4vmusic.com/api/public/tags')
tags = response.json()

# Add tags to an item
def add_tags(feed_guid, item_guid, tags, api_key):
    url = f'https://v4vmusic.com/api/public/items/byGuid/{feed_guid}/{item_guid}/tags'
    headers = {'x-api-key': api_key}
    data = {'tags': tags}
    response = requests.post(url, json=data, headers=headers)
    return response.json()

cURL Examples

# Get all tags
curl https://v4vmusic.com/api/public/tags

# Get popular tags with counts
curl https://v4vmusic.com/api/public/tags/popular
curl https://v4vmusic.com/api/public/tags/popular?limit=50

# Find items with a specific tag
curl https://v4vmusic.com/api/public/items/bytag/rock

# Add tags to an item
curl -X POST \
  -H "Content-Type: application/json" \
  -H "x-api-key: v4v_your_api_key_here" \
  -d '{"tags": ["rock", "metal"]}' \
  https://v4vmusic.com/api/public/items/byGuid/05b75483-9f5b-5236-bd66-69e9d3e1b995/c56c5b2b-fa79-4cd7-ae23-55cb207b103b/tags

Best Practices

Tag Naming

  • Use lowercase letters only
  • Separate words with hyphens (e.g., "indie-rock")
  • Keep tags concise and descriptive
  • Avoid special characters except hyphens

API Usage

  • Always include the x-api-key header for write operations
  • Handle rate limiting by checking response headers
  • Use appropriate HTTP methods (GET for read, POST for write)
  • Validate tag names before submission

Error Handling

  • Always check HTTP status codes
  • Parse error messages for debugging
  • Implement exponential backoff for rate limit errors
  • Log API responses for monitoring

Performance

  • Cache tag lists to reduce API calls
  • Batch tag operations when possible
  • Use appropriate timeouts for requests
  • Monitor your API usage to stay within limits

Common Workflows

Discovering Music by Tags

  1. Get all available tags: GET /api/public/tags
  2. Find items with specific tags: GET /api/public/items/bytag/{tagName}
  3. Get detailed item information with tags: GET /api/public/items/byGuid/{feedGuid}/{itemGuid}

Contributing Tags to Music

  1. Obtain an API key from the API Keys page
  2. Identify the item's RSS identifiers (feedGuid, itemGuid)
  3. Submit tags: POST /api/public/items/byGuid/{feedGuid}/{itemGuid}/tags
  4. Verify the tags were added: GET /api/public/items/byGuid/{feedGuid}/{itemGuid} (tags included in response)

Bulk Tagging an Album/Feed

  1. Obtain an API key from the API Keys page
  2. Identify the feed's GUID (feedGuid)
  3. Submit tags to all items: POST /api/public/items/byFeedGuid/{feedGuid}/tags
  4. Verify by listing items: GET /api/public/items/byFeedGuid/{feedGuid}

Building a Tag-Based Recommendation System

  1. Analyze user's favorite music to identify common tags
  2. Find similar items using those tags
  3. Suggest new music based on tag overlap
  4. Allow users to contribute tags to improve recommendations