Postal Developers
REST API

Tags and auto-tagging

The tag taxonomy, editing tags, and the AI tagging pipeline.

Tracks carry tags in ten categories: genres, moods, audio types, vocal types, instruments, lyric themes, tempos, eras, characters and movements, plus free additional tags. Postal's tagging model proposes tags after every upload; you can accept them, override them, or write tags directly.

Taxonomy

GET /api/v1/taxonomy

Scope read:tracks. Every valid tag value, grouped by category and in display order. Fetch it once and cache it; tag writes must use these names.

data (trimmed)
{
  "genres": [{ "id": "…", "name": "Downtempo", "code": "downtempo", "order": 12 }],
  "moods": [  ],
  "instruments": [  ],
  "vocalTypes": [  ],
  "lyricThemes": [  ],
  "audioTypes": [  ],
  "tempos": [  ],
  "eras": [  ],
  "characters": [  ],
  "movements": [  ]
}

Update tags

PATCH /api/v1/tracks/tags?id={trackId}

Scope update:tracks. Each category you send replaces that category on the track. Categories you omit are untouched.

Request
{
  "genres": ["Downtempo", "Chillhop"],
  "moods": ["Warm", "Relaxed"],
  "types": ["Instrumental"],
  "vocals": [],
  "instruments": ["Rhodes", "Upright bass"],
  "lyricThemes": [],
  "eras": ["2020s"],
  "characters": [],
  "movements": [],
  "additionalTags": ["coffee-ad", "sync-ready"]
}

Edits train the model

Tag changes made through the API are recorded as feedback for the tagging model, the same way a person's corrections in the app are. Only write tags you are confident about.

Trigger auto-tag

POST /api/v1/tracks/auto-tag

Scope update:tracks. Body { "trackId": "…" }. Starts analysis for one track. Asynchronous: returns immediately.

Batch auto-tag

POST /api/v1/tracks/auto-tag/batch

Scope update:tracks. Body { "trackIds": ["…", "…"] }. Queues every track.

Get suggested tags

GET /api/v1/tracks/suggested-tags?id={trackId}

Scope read:tracks. Poll this until analysisStatus is completed or failed.

data
{
  "trackId": "cm1x…",
  "suggestedTags": {
    "genres": ["Downtempo"],
    "moods": ["Warm", "Relaxed"],
    "instruments": ["Rhodes"]
  },
  "needsRetagging": false,
  "analysisStatus": "completed",
  "intelligence": {
    "genreCodes": ["downtempo"],
    "moodCodes": ["warm", "relaxed"],
    "typeCodes": ["instrumental"],
    "instrumentCodes": ["rhodes"],
    "useCaseCodes": ["advertising"],
    "status": "ready",
    "ready": true
  }
}

Returns { "ok": false, "error": "TRACK_NOT_FOUND" } for an id you do not own.

Apply suggested tags

POST /api/v1/tracks/apply-suggested-tags

Scope update:tracks. Body { "trackId": "…" }. Overwrites the track's tags with the stored suggestions. Returns { "trackId", "applied", "requeued" }. requeued: true means no suggestion existed yet and analysis was started.

Typical pipeline

  1. Upload, or pick tracks with GET /tracks?createdAfter=….
  2. POST /tracks/auto-tag/batch.
  3. Wait for track.audio_profile_completed webhooks, or poll GET /tracks/suggested-tags every few seconds.
  4. Review. Apply as-is with POST /tracks/apply-suggested-tags, or send a corrected set with PATCH /tracks/tags.

The MCP server wraps steps 2–4 in a single wait_for_auto_tag tool.

On this page