BOP 4 MUSIC API ยท AGENT GUIDE Plain HTTP and JSON. No account, no audio rendering on the server: the API stores immutable song revisions and the browser studio plays them. LOOP 1. compose: POST https://bop-api.sahildev.com/bop/api/v4/compose with a song (below). Reply: revision, songUrl. 2. Open songUrl in a browser (https://sahildev.com/bop/studio/?revision=ID) to hear and edit it. 3. inspect: POST https://bop-api.sahildev.com/bop/api/v4/inspect {"revision":ID,"inspect":{"view":...}} 4. edit: POST https://bop-api.sahildev.com/bop/api/v4/edit {"revision":ID,"batch":{"edits":[...]}} Every edit makes a new revision; the old one never changes, so branch freely. No POST? GET https://bop-api.sahildev.com/bop/api/v4// works too (max 15,000 characters; or gzip/). Revisions are immutable and public to anyone who has their ID. Errors return {"ok":false,"error":{code,path,message,hint}}: fix what path points at and retry. EXAMPLE SONG (composes as-is; 4 tracks, 2 sections, shared chords) {"title":"Harbor lights","tempo":96,"key":"G major","sections":{"verse":4,"chorus":4},"form":"verse chorus verse chorus","voicings":{"G":"G3 B3 D4","C":"C4 E4 G4","D":"D4 F#4 A4","Em":"E4 G4 B4"},"rhythms":{"pulse":[[0,1.5],[1.5,0.5],[2,2]]},"tracks":{"lead":{"role":"melody","sound":"sung-ah-high","expression":"swell","mix":{"reverb":25,"gainDb":4},"patterns":{"a":"G4 A4 B4:2 | D5:1.5 B4:0.5 A4:2","b":{"use":"a","transform":{"transpose":5}},"sigh":{"notes":[{"at":0,"duration":3,"pitch":"D5","velocity":0.8,"pins":[[0,0,1],[3,-2,0.4]]}],"bars":1}},"parts":{"verse":"a a","chorus":"sigh sigh b"}},"keys":{"role":"harmony","sound":"grand-piano","mix":{"gainDb":-6,"pan":-20},"patterns":{"verse":{"harmony":"G C G D","rhythm":"pulse"},"chorus":{"harmony":"C G Em D","rhythm":"pulse"}},"parts":{"verse":"verse","chorus":"chorus"}},"bass":{"role":"bass","sound":"cello","patterns":{"verse":{"harmony":"G C G D","tones":[1],"transform":{"transpose":-24}},"chorus":{"harmony":"C G Em D","tones":[1],"transform":{"transpose":-24}}},"parts":{"verse":"verse","chorus":"chorus"},"mix":{"gainDb":-6}},"drums":{"role":"percussion","sound":"standard-drumset","mix":{"gainDb":-8},"patterns":{"beat":"kick hat snare hat"},"parts":{"verse":"beat","chorus":"beat"}}}} NOTATION Song: title, tempo (BPM), key (a label), meter (beats per bar, default 4), sections {name: bars}, form "verse chorus ...", tracks {id: track}. Track: role (melody, harmony, bass, percussion, texture...: edits can select by role), sound (see https://bop-api.sahildev.com/bop/api/v4/sounds), mix, patterns {id: pattern}, parts {section: "a b*2 -"} played in order and repeated to fill the section; - is a silent bar (-*4 is four). Patterns in the song's top-level patterns are shared. A part can vary its patterns: {"play":"a b","transform":{"velocity":0.8}}. Phrase text: C4 D#4 Bb3 (scientific pitch), :2 lasts two beats (default 1), :0.5 or :1/3 for fractions, r rest, [C4,E4,G4] chord (up to 4), | next bar. Drums: kick snare hat ride shaker soft-shaker or D0..D11; on standard-drumset D1-D3 are low drums rising in pitch (toms), D4 a higher, shorter drum, D7 a bright cymbal and D11 a short bright noise hit (clap-like). Expressive notes: {"notes":[{"at":0,"duration":3,"pitch":"D5", "velocity":0.8,"pins":[[beat,bendSemitones,intensity],...]}],"bars":1}. Pins start at [0,0,x] and end at the duration; they shape bends and swells. To slide up into a note, write the lower pitch and bend up to the target (or use the scoop shape below). Variation: {"use":"a","transform":{"transpose":5,"velocity":0.7, "stretch":2,"reverse":true}} follows its source when the source changes. Chords: song "voicings" {"G":"G3 B3 D4"} are exact pitches (chord symbols are never guessed); "rhythms" {"pulse":[[beat,beats],[beat,beats,[tones]]]} are one bar of hits. A pattern {"harmony":"G C*2 D","rhythm":"pulse","tones":[1]} plays one chord per bar through the rhythm; [["G",2],["C",2]] changes chords mid-bar; tones pick 1-based voicing positions ([1] makes a bass line). A hit's own tones override the pattern's; hits may not overlap within the bar. Shapes: "expression" on a track (default) or pattern shapes every note without pins: swell, taper, fade, soft, scoop (rises into the written pitch), or your own "expressions" {"lift":[[0,0,0.2],[1,0,1]]} of [fraction,bend,intensity]. Performance: song "performance" [{"track":"drums","scope":{"section":"verse", "occurrence":1,"bars":[1,4]},"mix":{"muted":true}}] changes mix or adds "transpose" for one stretch of the song without touching patterns (the mix and transpose edits below write these for you). Add "to" for a ramp: those controls move smoothly across the scope from their starting value to "to", arriving at its end. BUILDING A SONG (grow gradually; don't just switch layers on at section lines) - Ramp levels and brightness: a mix edit with "to" (examples below) fades a track in, opens its brightnessHz, or crescendos into the next section. End the ramp at the level the next section uses so nothing jumps. - Bring tracks in mid-section: parts {"verse":"-*4 a*4"} enter halfway. A pattern always starts from its own beginning, so a harmony pattern entering halfway needs its own second-half progression (or ramp its gain in instead). - Thicken rhythm as you go: a sparser pattern first, the busier one later, and a fill bar before a new section ("beat*7 fill"). - Swell long notes with pins, and lift the last chorus with a variation an octave up or a part transform (velocity) that leaves room to grow. - Drop out before the biggest moment: fewer tracks for two bars makes the final chorus land harder. EDITS (batch.select applies to every edit; an edit's own select overrides it. select: tracks "id" or roles [...], section, occurrence (1-based), bars [from,to]) - Louder, roomier melody in every chorus (relative): {"select":{"roles":["melody"],"section":"chorus"},"edits":[{"op":"adjust","by":{"gainDb":3,"reverb":10}}]} - Mute the drums in the first verse only: {"select":{"tracks":"drums","section":"verse","occurrence":1},"edits":[{"op":"mix","set":{"muted":true}}]} - Change the lead's instrument (vowel oo): {"edits":[{"op":"sound","select":{"tracks":"lead"},"sound":"sung-oo-high"}]} - Rewrite a phrase everywhere it repeats, including its variation b: {"edits":[{"op":"pattern","track":"lead","id":"a","value":"G4 B4 D5:2 | E5:1.5 D5:0.5 B4:2"}]} - Lift the last chorus a whole step (drums are never transposed): {"select":{"section":"chorus","occurrence":2},"edits":[{"op":"transpose","select":{"roles":["melody","harmony","bass"]},"semitones":2}]} - Add a bridge, give tracks parts in it, and reorder the form: {"edits":[{"op":"section","id":"bridge","value":2},{"op":"pattern","track":"keys","id":"bridge","value":{"harmony":"Em D","rhythm":"pulse"}},{"op":"part","track":"keys","section":"bridge","play":"bridge"},{"op":"form","value":"verse chorus bridge chorus"}]} - Revoice a chord everywhere it is used (keys and bass follow): {"edits":[{"op":"voicing","id":"C","value":"C4 E4 G4 B4"}]} - Change the accompaniment rhythm everywhere: {"edits":[{"op":"rhythm","id":"pulse","value":[[0,1],[1,1],[2,1],[3,0.5],[3.5,0.5]]}]} - Add a pad that only plays in the chorus: {"edits":[{"op":"addTrack","id":"pad","value":{"role":"texture","sound":"warm-pad","mix":{"gainDb":-14},"patterns":{"p":"[G3,D4]:4"},"parts":{"chorus":"p"}}}]} - Build: bring the keys in softly and open them up across the first verse (a ramp): {"select":{"tracks":"keys","section":"verse","occurrence":1},"edits":[{"op":"mix","set":{"gainDb":-20,"brightnessHz":900},"to":{"gainDb":-6,"brightnessHz":16000}}]} - Crescendo the drums through the second verse into the chorus: {"select":{"tracks":"drums","section":"verse","occurrence":2},"edits":[{"op":"mix","set":{"gainDb":-18},"to":{"gainDb":-8}}]} - Tempo and title: {"edits":[{"op":"song","tempo":104,"title":"Harbor lights (brighter)"}]} Also: removeTrack {track}, role {track,value}, rename {track,name}, mixPreset {id,value} then mix {use:id}, part {track,section,play:null} to silence. mix sets absolute values; adjust adds to them. Replies list each change with the effective before/after values, so you rarely need to re-inspect. INSPECT - Tracks, roles, sections and length: {"view":"summary"} - Sections in form order with bar ranges: {"view":"structure"} - Every note of the lead in the second chorus: {"view":"notes","select":{"tracks":"lead","section":"chorus","occurrence":2}} - Effective mix values of the melody: {"view":"mix","select":{"roles":["melody"]}} - Harmony, register and repetition facts: {"view":"analysis"} MIX CONTROLS (continuous; set exact values). Every sound plays at the same loudness at gainDb 0 (compose marks new songs "levels":"matched"; "raw" keeps each sound's own level, as older songs were balanced). A track without gainDb starts from its role (medians of 30 balanced songs): melody 0, harmony -6, bass -4, drums/percussion -6, counter-lines -6, texture/pads -11. A soft or sparse lead (voices, long swells) may want +3 to +5. A track starts from its sound's own room (violin: reverb 33); anything you set overrides it. - gainDb -60..24 dB (default 0): Continuous configured gain; use muted to silence without losing the level. - pan -100..100 % (default 0): Equal-power stereo position: -100 left, 0 center, 100 right. - reverb 0..100 % (default 0): Room effect amount; zero is dry. - chorus 0..100 % (default 0): Chorus amount; zero disables chorus. - echoFeedback 0..95 % (default 0): Echo feedback; zero disables echo. - echoDelayBeats 0.0417..8 beats (default 0.5): Echo delay measured in quarter-note beats. - brightnessHz 20..24000 Hz (default 20000): Low-pass cutoff, independent of the instrument's body resonances. - muted true|false SOUNDS https://bop-api.sahildev.com/bop/api/v4/sounds lists 197 IDs by category. Good starting points: grand-piano, nylon-guitar, violin, cello, flute, clarinet, tenor-sax, warm-pad, standard-drumset (drum tracks), and the measured human voices sung-ah-high, sung-oo-high (soprano), sung-ah-low, sung-oo-low (baritone). Voices sing vowels, not words. SCHEMAS https://bop-api.sahildev.com/bop/api/v4/schema lists JSON Schemas: https://bop-api.sahildev.com/bop/api/v4/schema/project (a song), https://bop-api.sahildev.com/bop/api/v4/schema/inspect and https://bop-api.sahildev.com/bop/api/v4/schema/edit. SOURCE https://bop-api.sahildev.com/bop/api/v4/revisions/ returns a revision's full song JSON; https://bop-api.sahildev.com/bop/api/v4/revisions//midi returns it as a Standard MIDI File.