← Back to README
RiffScore Machine-Addressable API Reference
Programmatic control of the score editor via JavaScript.
See also : Cookbook • Configuration • Architecture • Coding Patterns
Version: 1.0.0-alpha.8
Access:
React : const ref = useRef<MusicEditorAPI>(null)
Global : window.riffScore.get('my-score-id') or window.riffScore.active
Note
Methods marked ✅ are ready to use . Methods marked ⏳ are pending implementation and will return this (no-op) or throw for queries.
Principle
Description
Intent-Based
Methods describe what to do, not how .
Fluent/Chainable
All mutation/navigation methods return this.
Synchronous
State updates are immediate; React render is decoupled.
Multi-Instance
Registry supports multiple editors on one page.
Fail-Safe
Invalid inputs are no-ops or clamped to valid ranges. Returns Result object.
The API is implemented using a factory pattern with 11 domain-specific modules:
src/hooks/api/
├── index.ts # Barrel exports
├── types.ts # APIContext interface
├── navigation.ts # move, jump, select, selectById
├── selection.ts # selectAll, extend*, selectFullEvents
├── entry.ts # addNote, addRest, addTone
├── modification.ts # setPitch, transpose, structure
├── history.ts # undo, redo, transactions
├── playback.ts # play, pause, stop
├── io.ts # loadScore, reset, export
├── events.ts # on() subscription wrapper
└── chords.ts # addChord, updateChord, removeChord, selectChord
Each factory receives an APIContext containing refs and dispatch functions, then returns methods bound to this via ThisType<MusicEditorAPI> for fluent chaining.
All methods in src/api.types.ts are annotated with @status JSDoc tags:
@status implemented — Ready to use
@status stub — Returns this (no-op), tracked in Issue #119
@status partial — Partially implemented (e.g., export('json') works, others throw)
window.riffScore.get(id) ✅
Argument
Type
Required
Notes
id
string
Yes
Must match <RiffScore id="..." /> prop.
Returns: MusicEditorAPI | undefined
window.riffScore.active ✅
The most recently focused or mounted instance.
Returns: MusicEditorAPI | null
Method
Signature
Status
Description
move
move(direction)
✅
Navigate in any direction (left/right/up/down).
jump
jump(target)
✅
'start-score', 'end-score', 'start-measure', 'end-measure'.
select
select(measureNum, staffIndex?, eventIndex?, noteIndex?)
✅
Absolute targeting (1-based measure).
selectAtQuant
selectAtQuant(measureNum, quant, staffIndex?)
✅
Target by rhythmic position.
selectById
selectById(eventId, noteId?)
✅
Target by internal IDs.
3. Selection (Multi-Select)
Method
Signature
Status
Description
addToSelection
addToSelection(measureNum, staffIndex, eventIndex)
✅
Cmd+Click toggle behavior.
selectRangeTo
selectRangeTo(measureNum, staffIndex, eventIndex)
✅
Shift+Click range from anchor.
selectAll
selectAll(scope)
✅
'score', 'measure', 'staff', 'event'.
selectEvent
selectEvent(measureNum?, staffIndex?, eventIndex?)
✅
Select all notes in chord.
deselectAll
deselectAll()
✅
Clear selection.
selectFullEvents
selectFullEvents()
✅
Fill partial chord selections.
extendSelectionUp
extendSelectionUp()
✅
Vertical extend toward treble.
extendSelectionDown
extendSelectionDown()
✅
Vertical extend toward bass.
extendSelectionAllStaves
extendSelectionAllStaves()
✅
Vertical extend to all staves.
Method
Signature
Status
Description
addNote
addNote(pitch, duration?, dotted?)
✅
Append note at cursor; auto-advances.
addRest
addRest(duration?, dotted?)
✅
Append rest at cursor.
addTone
addTone(pitch)
✅
Stack pitch onto existing chord.
makeTuplet
makeTuplet(numNotes, inSpaceOf)
✅
Convert selection to tuplet.
unmakeTuplet
unmakeTuplet()
✅
Remove tuplet grouping.
toggleTie
toggleTie()
✅
Toggle tie to next note.
setTie
setTie(boolean)
✅
Explicit tie setting.
setInputMode
setInputMode('note' | 'rest')
✅
Set entry mode (UI state).
Method
Signature
Status
Description
setPitch
setPitch(pitch)
✅
Update selected note(s).
setDuration
setDuration(duration, dotted?)
✅
Update selected event(s).
setAccidental
setAccidental(type)
✅
'sharp', 'flat', 'natural', null.
toggleAccidental
toggleAccidental()
✅
Cycle accidental.
transpose
transpose(semitones)
✅
Chromatic transposition.
transposeDiatonic
transposeDiatonic(steps)
✅
Visual/diatonic transposition.
updateEvent
updateEvent(props)
✅
Generic escape hatch.
Method
Signature
Status
Description
addMeasure
addMeasure(atIndex?)
✅
Add measure at index (default: end).
deleteMeasure
deleteMeasure(measureIndex?)
✅
Delete measure (default: selected).
deleteSelected
deleteSelected()
✅
Smart delete.
setKeySignature
setKeySignature(key)
✅
Change key signature.
setTimeSignature
setTimeSignature(sig)
✅
Change time signature.
setMeasurePickup
setMeasurePickup(isPickup)
✅
Toggle pickup measure.
Method
Signature
Status
Description
setClef
setClef(clef)
✅
'treble', 'bass', 'alto', 'tenor', 'grand'.
setScoreTitle
setScoreTitle(title)
✅
Update title.
setBpm
setBpm(number)
✅
Set tempo.
setTheme
setTheme(theme)
✅
'LIGHT', 'DARK', 'WARM', 'COOL'.
setScale
setScale(number)
✅
Zoom factor.
setStaffLayout
setStaffLayout(type)
✅
'grand', 'single'.
Method
Signature
Status
Description
loadScore
loadScore(json)
✅
Load score object.
reset
reset(template?, measures?)
✅
Reset to blank score/template.
export
export(format)
✅
Returns string (empty on error). 'json' | 'abc' | 'musicxml'.
Method
Signature
Status
Description
play
play(startMeasure?, startQuant?)
✅
Start/resume playback (async).
pause
pause()
✅
Pause (retains position).
stop
stop()
✅
Stop and reset to beginning.
rewind
rewind(measureNum?)
✅
Jump playback position.
setInstrument
setInstrument(instrumentId)
✅
'bright', 'mellow', 'organ', 'piano'.
Method
Signature
Status
Description
getScore
getScore()
✅
Read-only score state.
getConfig
getConfig()
✅
Current config.
getSelection
getSelection()
✅
Current selection state.
Method
Signature
Status
Description
addChord
addChord(quant, symbol)
✅
Add chord symbol at global quant position.
updateChord
updateChord(chordId, symbol)
✅
Update an existing chord symbol.
removeChord
removeChord(chordId)
✅
Remove a chord symbol.
getChords
getChords()
✅
Get all chords sorted by quant ascending.
getChord
getChord(chordId)
✅
Get a specific chord by ID.
getChordAtQuant
getChordAtQuant(quant)
✅
Get the chord at a specific quant position.
getValidChordQuants
getValidChordQuants()
✅
Get all valid quant positions for chords.
Method
Signature
Status
Description
selectChord
selectChord(chordId)
✅
Select a chord by ID.
selectChordAtQuant
selectChordAtQuant(quant)
✅
Select the chord at a quant position.
deselectChord
deselectChord()
✅
Deselect the currently selected chord.
getSelectedChord
getSelectedChord()
✅
Get the currently selected chord.
hasChordSelection
hasChordSelection()
✅
Check if a chord is selected.
Method
Signature
Status
Description
selectNextChord
selectNextChord()
✅
Select the next chord in sequence.
selectPrevChord
selectPrevChord()
✅
Select the previous chord.
selectFirstChord
selectFirstChord()
✅
Select the first chord in the score.
selectLastChord
selectLastChord()
✅
Select the last chord in the score.
Method
Signature
Status
Description
setChordDisplay
setChordDisplay(config)
⏳
{ notation, useSymbols }.
setChordPlayback
setChordPlayback(config)
⏳
{ enabled, velocity }.
getChordDisplay
getChordDisplay()
✅
Get current chord display config.
getChordPlayback
getChordPlayback()
✅
Get current chord playback config.
Method
Signature
Status
Description
undo
undo()
✅
Undo last mutation.
redo
redo()
✅
Redo last undone.
beginTransaction
beginTransaction()
✅
Start batch (single undo step).
commitTransaction
commitTransaction(label?)
✅
End batch with optional history label.
rollbackTransaction
rollbackTransaction()
✅
Abort batch and revert changes.
copy
copy()
⏳
Copy selection.
cut
cut()
⏳
Cut selection.
paste
paste()
⏳
Paste at cursor.
Method
Signature
Status
Description
collect
collect(callback)
✅
Execute batch and aggregate results.
result
get result()
✅
Get result of last operation ({ ok, code, message }).
ok
get ok()
✅
Helper check for result.ok.
hasError
get hasError()
✅
Sticky flag if any error occurred since clear.
clearStatus
clearStatus()
✅
Reset sticky hasError flag.
debug
debug(enabled)
✅
Enable or disable verbose batch/debug output for development.
12. Events & Subscriptions
Method
Signature
Status
Description
on
on(event, callback)
✅
Subscribe to state changes.
'score' — Score mutations
'selection' — Selection changes
'playback' — Play/pause state (Pending)
'batch' — Batch transaction commit (Payload: { type: 'batch', commands: CommandSummary[], timestamp: number })
'operation' — Any API method call (Payload: Result)
'error' — Any API error (Payload: Result)
Returns: () => void — Unsubscribe function.
Important
Callbacks fire after React processes state updates (via useEffect), not synchronously.
This ensures callbacks receive guaranteed-fresh data .
In tests, use waitFor() from @testing-library/react:
await waitFor ( ( ) => {
expect ( callback ) . toHaveBeenCalled ( ) ;
} ) ;
API methods implement a Fail-Soft pattern. They never throw errors (except for critical system failures).
Every method updates the internal result state:
ok : true / false
code : string error code (e.g., 'INVALID_PITCH')
message : Human-readable description
details : Optional context object
The hasError flag is "sticky"—it remains true if any operation in a chain fails, until explicitly cleared.
api . addNote ( 'Bad' ) . addNote ( 'Good' ) ;
console . log ( api . hasError ) ; // true (from first op)
api . clearStatus ( ) ;
Scenario
Behavior
Invalid measureNum
Clamped to valid range.
Invalid pitch format
ok: false, code: 'INVALID_PITCH'.
export unknown format
Throws Error (Critical).
api . select ( 1 ) . addNote ( 'C4' ) . addNote ( 'D4' ) . addNote ( 'E4' ) ;
api . select ( 1 ) . addNote ( 'C4' ) . move ( 'left' ) . addTone ( 'E4' ) . addTone ( 'G4' ) ;
const score = api . getScore ( ) ;
const selection = api . getSelection ( ) ;
console . log ( score . title ) ;
const json = api . export ( 'json' ) ;
localStorage . setItem ( 'score' , json ) ;
api . beginTransaction ( ) ;
for ( let i = 0 ; i < 16 ; i ++ ) {
api . addNote ( `C${ ( i % 3 ) + 4 } ` , 'sixteenth' ) ;
}
api . commitTransaction ( 'Insert 16th Run' ) ;
const unsub = api . on ( 'score' , ( newScore ) => {
backend . save ( newScore ) ;
} ) ;
← Back to README