← API Reference

Track Structure

POST
https://api.audioscape.ai/developer/v1/track/structure

On this pageEndpoint

Endpoint

Fetch the beat grid and section metadata for a track. Use this to sync animations, lighting, or VFX to the music — drop a particle burst on every downbeat, trigger a camera shake on the Drop, swap shaders between Verse and Chorus.

Roughly 96% of the catalog has beat grid analysis and 91% has section labels. Tracks without analysis return null for beat_grid and empty arrays for sections/phrases.

Headers

NameTypeDescription
x-api-keyrequiredYour API key
Content-TyperequiredMust be application/json

Request Body

ParameterTypeDescription
asset_id
string
required
The Roblox asset ID of the track. Numeric string.

Response

Returns the flattened beat grid and section structure for the track.label values come from the classifier vocabulary: Intro, Verse, Chorus, Drop, Bridge, Climax, Outro, Main, Break, Build, Breakdown, Transition, Peak.energy is an integer 1–4.

response.json
{
  "asset_id": "string",
  "duration": number,
  "bpm": number,
  "track_energy": number,
  "beat_grid": {
    "times": [number],
    "downbeats": [number]
  },
  "sections": [
    {
      "start": number,
      "end": number,
      "label": "Intro" | "Verse" | "Drop" | ...,
      "energy": 1 | 2 | 3 | 4 | null,
      "bar_start": number,
      "bar_end": number,
      "bars": null,
      "color": "rgba(...)"
    }
  ],
  "phrases": [ ... ]
}

Example: Sync VFX to downbeats

Using the SDK helpers — fetch the structure once, then drive a particle burst on every downbeat:

Luau (Roblox)
local AudioScape = require(ServerStorage.AudioScape)
local client = AudioScape.new("your-api-key")

local structure, err = client:getStructure({ asset_id = "1843209165" })
if not structure then return end

-- Schedule a burst at every downbeat
for _, t in ipairs(structure.beat_grid.downbeats) do
  task.delay(t, function() emitter:Emit(20) end)
end

-- Or query at runtime — punch the camera FOV on Drops
local camera = workspace.CurrentCamera
local section = client:sectionAtTime("1843209165", currentTime)
if section and section.label == "Drop" then
  camera.FieldOfView = camera.FieldOfView + section.energy * 5
end

Error Responses

400Bad Request

Missing or non-numeric asset_id.

400.json
{
  "error": "asset_id is required and must be a numeric string"
}
401Unauthorized

Missing or invalid API key. Confirm your x-api-key header is set.

401.json
{
  "error": "Invalid or missing API key"
}
404Not Found

The asset_id doesn't exist in our catalog.

404.json
{
  "error": "asset_id not found"
}
429Too Many Requests

You've exceeded your rate limit. See your current tier on the API Keys page.

500Internal Server Error

Something went wrong on our end. Retry with backoff; if it persists, ping us on Discord.

Ready to sync your game to the music?

Grab the SDK and start triggering effects on every beat.

Get Your API Key