Track Structure
POSThttps://api.audioscape.ai/developer/v1/track/structureEndpoint
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
| Name | Type | Description |
|---|---|---|
| x-api-key | required | Your API key |
| Content-Type | required | Must be application/json |
Request Body
| Parameter | Type | Description |
|---|---|---|
| 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.
{
"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:
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
endError Responses
400Bad RequestMissing or non-numeric asset_id.
{
"error": "asset_id is required and must be a numeric string"
}401UnauthorizedMissing or invalid API key. Confirm your x-api-key header is set.
{
"error": "Invalid or missing API key"
}404Not FoundThe asset_id doesn't exist in our catalog.
{
"error": "asset_id not found"
}429Too Many RequestsYou've exceeded your rate limit. See your current tier on the API Keys page.
500Internal Server ErrorSomething 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