#Jamcorder device API

This document describes the network API exposed by Jamcorder firmware. It is written for application and tooling authors who need to discover a Jamcorder, read its state, change settings, transfer files, or stream MIDI.

Purpose: help people access their MIDI data across devices and develop extensions that interact directly with Jamcorder.

The Jamcorder API exposes 167 /api/... paths. Always use the runtime discovery endpoints instead of assuming that every firmware build has every endpoint.

Security: the API is available to anyone on your network. Only connect your Jamcorder device to a trusted network. Endpoints can change persistent settings, delete extensions, reboot the device, and more. For your protection, no API endpoint exists that can delete recordings.

#Contents

#Quick start

#Set up Jamcorder Wi-Fi

Before using the API, connect your Jamcorder device to Wi-Fi. You can set up Wi-Fi with the Jamcorder app or with Web-based setup.

#App-based setup PREFERRED

In the Jamcorder app, open Settings → [Jamcorder name] → Wi-Fi and follow the setup instructions.

#Web-based setup

Web-based setup lets you configure Wi-Fi from a browser without the app. Hold the device button for about 1.5 seconds, join the jamcorder-xxxxxxxx Wi-Fi network, and open http://192.168.0.1. Select your home network and enter its password.

#Connect to the API

Set JAMCORDER to the device address. A Jamcorder normally advertises jamcorder.local and a secondary mDNS name based on its full UUID; /api/wifi/info reports its current IP address. An IP address is least ambiguous when multiple Jamcorders share a network.

JAMCORDER=http://jamcorder.local

# Learn which API families this firmware supports.
curl --compressed "$JAMCORDER/api/meta/capabilities"

# Get the exact endpoint list for this running build.
curl --compressed "$JAMCORDER/api/meta/endpoints"

# Read device identity.
curl --compressed "$JAMCORDER/api/identities/get"

# Rename the device.
curl --compressed \
  -H 'Content-Type: application/json' \
  -d '{"jamcorderName":"Studio Jamcorder"}' \
  "$JAMCORDER/api/identities/rename/jamcorder"

curl --compressed is recommended because JSON responses larger than 1,000 bytes are returned with Content-Encoding: deflate.

#Concepts and API domains

#Identities and names

The identities object separates stable identifiers from user-facing labels:

FieldMeaning
jamcorderUuidOpaque identifier for this physical Jamcorder. It is also used to associate recordings and derive device-facing names.
jamcorderNameEditable display name for the device, such as Studio Jamcorder.
performerUuidOpaque identifier for the performer identity stored on the device.
performerNameEditable display name for the performer.

Use UUIDs as database and synchronization keys; use names for UI. Names are not unique and none of these fields is an authentication credential. Treat UUIDs as stable for the life of a provisioned device, but allow them to change after a factory reset or reprovisioning.

#Device state and capabilities

/api/device-state/get is a broad snapshot intended for initial application startup. It combines identities, system information, settings, connectivity, storage, MIDI, recording, lifetime statistics, and current issues. Use the smaller subsystem endpoints for later refreshes so the client transfers and parses only the state it needs.

A capabilities response says which versioned feature families the device understands. /api/meta/endpoints says exactly which calls are present in the currently running firmware. Check both when compatibility matters: capability flags are convenient feature gates, while the endpoint list is definitive for an individual URI.

#Issues, alerts, and logs

These three APIs describe different levels of device health and activity:

APIWhat it representsTypical client use
IssuesAggregated operational conditions such as missing storage, invalid time, failed Wi-Fi, transport overruns, update failures, or an unexpected reboot. An issue has occurrence counts and active/resolved state.Show health status, guide recovery, and collect structured support data.
AlertsLightweight event notifications such as a change to Wi-Fi, identities, or issues. Recent alerts can be fetched; new alert tokens can be streamed.Invalidate cached state, then refetch the affected API.
LogsRaw diagnostic text and live log output.Troubleshooting and support, not application state.

/api/issues/current contains unresolved issue records. /api/issues/history also includes resolved records. Both include totalRaiseCount, which increases as conditions are raised and can help a client detect change. A record may contain issue, subIssue, occurrences, isResolved, first/latest wall-clock and since-boot timestamps, time since the previous occurrence, didBuzzUser, and an attached error object.

Calling /api/issues/clear/current marks all current records resolved. It does not repair the underlying condition and does not erase history. If the problem continues, firmware can raise the issue again. Applications should display known user-actionable issues prominently and retain unknown issue names for forward compatibility.

#Recordings, assets, and MIDI stones

Jamcorder records MIDI into its native JMX asset format. The library API lists recording assets and can convert the newest recording to a standard MIDI file. An asset is associated with the Jamcorder identity that created it; a single SD card can therefore contain assets from more than one device.

A MIDI stone is an indexed chunk of a JMX recording. Stone downloads and the stone WebSocket support incremental transfer without downloading an entire asset. A negative stoneIdx counts backward from the newest stone, which is useful for tailing a recording.

The MIDI APIs have separate roles: recorder controls what is captured, commands turns configured MIDI input into device actions such as bookmarks, I/O controls live routing between DIN, USB, Bluetooth, and WebSocket, piano state summarizes held and sustained notes, and lifetime statistics tracks cumulative playing activity.

#API domain guide

DomainPurpose
Getting started and device information
MetaDiscover capability flags and the exact endpoint set.
SystemIdentify the running firmware, check liveness, and reboot the device.
Device stateFetch a consolidated startup snapshot.
IdentitiesRead stable IDs and edit display names.
TimeMaintain timestamps, local offset, daylight-saving rules, and SNTP.
Music and recordings
PianoRead derived real-time note, sustain, and activity state.
MIDI recorderConfigure capture, silence skipping, and recording fidelity.
MIDI commandsMap MIDI gestures to device actions and create bookmarks.
MIDI I/OConfigure live routing and stream MIDI over WebSocket.
LibraryFind recording assets and export the newest recording as MIDI.
MIDI stonesDownload or stream indexed chunks of a recording.
Lifetime statisticsRead or clear cumulative note and playing-time totals.
Storage and content
SD cardInspect storage capacity and format or repair the card.
FilesList, download, upload, move, and delete device-side files.
ExtensionsInstall and remove device-hosted extension content.
Device health and feedback
AlertsRead and stream lightweight change notifications.
IssuesRead and clear structured, persistent device-health records.
LogsRead recent diagnostic output and stream live logs.
CoredumpInspect and download crash data.
BuzzerConfigure or trigger device sounds.
Updates and maintenance
OTAInspect installed firmware and perform firmware updates.
Automatic rebootConfigure scheduled maintenance reboots.
Factory resetErase device settings and optionally preserve lifetime statistics.
Connectivity and setup
Discovery modeAdvertise a Wi-Fi hotspot. Used for Web-based setup.
Wi-FiInspect connectivity, scan networks, and configure credentials.
BluetoothInspect Bluetooth controller, service, and connection state.
USBInspect USB state and attached MIDI-device descriptors.
Engineering and manufacturing
Fabrication infoRead manufacturing identity and provision its protected values.
Verbose loggingControl detailed logging tags used for support and engineering.
Asset diagnosticsInspect recording headers and parsed JMX summaries.
Developer settingsControl internal developer-mode switches.
Heap diagnosticsInspect memory use, check integrity, and trace allocations.
System debugInspect low-level runtime state or deliberately force a crash.
NVS debugInspect and modify persistent key-value storage.
Self-testList and run hardware tests and the factory test suite.
Factory modeUnlock protected manufacturing operations and provision certificates.
STSAFERead certificates and perform secure-element challenges.
MIDI hardware testsInject and emit diagnostic MIDI sequences.

#Runtime discovery and compatibility

Call these endpoints before using a feature:

MethodPathPurpose
GET/api/meta/capabilitiesMerged feature flags such as supportsFilesApiV1 and supportsMidiIOApiV1.
GET/api/meta/endpointsExact registered URI, MIME type, and internal signature for each endpoint.
GET/api/system/software-infoRunning application name, version, build information, and hashes.
GET/api/ota/overviewRunning environment and installed firmware version information.

An endpoint entry has this shape:

{
  "uri": "/api/identities/get",
  "mimeType": "application/json",
  "sig": "voidToJson"
}

The sig determines the HTTP method and body type:

Registry signatureHTTP methodRequestResponse
voidToJsonGETNo bodyJSON
uriToJsonGETURI itself is inputJSON
jsonToJsonPOSTJSONJSON
emptyPostToJsonPOSTEmptyJSON
voidToDownloadGETNo bodyBinary/text download
uriToDownloadGETURI itself is inputBinary/text download
jsonToDownloadPOSTJSONBinary/text download
jsbnUploadToJsonPOSTJAMCJSBN uploadJSON
websocketGetWebSocket upgradeSee WebSocketsBinary frames

Endpoint availability can vary by firmware build, and MIDI player endpoints are not available in current builds. Treat /api/meta/endpoints as definitive for the connected device.

#HTTP contract

#Requests

#Success responses

JSON endpoints return 200 OK and a resource-specific JSON value. There is no universal success envelope: some mutation endpoints include apiSuccess, success, or another status field, while read endpoints return their object directly. Treat the HTTP status as authoritative and parse the schema for the specific endpoint.

Large JSON responses are zlib-wrapped and carry Content-Encoding: deflate. Standards-compliant HTTP clients normally decode this automatically when they request compressed content.

Downloads use the MIME type shown by /api/meta/endpoints. File downloads may also set Content-Disposition and Content-Length.

#Error responses

An API failure returns 400 Bad Request with JSON similar to:

{
  "error1": "directory does not exist",
  "error2": "unable to list directory",
  "errorCodeNum": 2,
  "errorCodeStr": "generic",
  "uri": "/api/files/list/overview",
  "apiSuccess": false
}

Errors accumulate as error1, error2, and so on. Known errorCodeStr values are generic, nonexistant (spelling preserved by the wire protocol), timedOut, deviceGone, and canceled.

If a streaming download fails after response bytes have begun, the server can only close the stream; it cannot replace the partial body with the JSON error object.

#JSON-plus-binary uploads (JAMCJSBN)

Six upload endpoints accept a custom body consisting of optional JSON metadata followed by raw binary bytes:

offset  size  value
0       8     ASCII "JAMCJSBN"
8       4     JSON byte length, uint32 little-endian
12      N     N bytes of UTF-8 JSON (not NUL-terminated)
12 + N  ...   binary payload

Set Content-Length to the size of the entire framed body. The binary payload begins immediately after the JSON. If the first eight body bytes are not the magic value, the server treats the entire body as binary and supplies an empty metadata object. Endpoints that require metadata, such as file upload, must use the framed form.

Example Python body construction (the result can be sent with any HTTP client):

import json
import struct

metadata = json.dumps({"filepath": "/upload.bin"}, separators=(",", ":")).encode()
file_bytes = open("upload.bin", "rb").read()
body = b"JAMCJSBN" + struct.pack("<I", len(metadata)) + metadata + file_bytes
PathMetadataBinary payload
/api/files/upload/simple{"filepath": string}File contents.
/api/extensions/upload-install-html{"filename": string}HTML extension file.
/api/extensions/upload-install-tar{"filename": string}Extension TAR archive.
/api/ota/sd/upload/simpleNoneEncrypted firmware image written to SD card.
/api/ota/direct/install/simpleNoneEncrypted firmware image installed directly.
/api/ota/resumable/install/upload-chunk{"otaWritten": integer} matching current progressOne firmware chunk.

#WebSockets

WebSockets are HTTP-only and use ws://<device>/api/.... The server supports at most a small number of simultaneous sockets, so clients should reconnect with backoff and close unused streams.

The common binary frame convention reserves the first byte:

ByteMeaning
0x00Standard application frame; endpoint payload follows.
0x01Server keepalive ping.
0x02Client keepalive pong.

Reply to a one-byte 0x01 frame with a binary one-byte 0x02 frame. Current handlers update liveness on any received frame, but clients should use the defined pong value for forward compatibility.

URLServer-to-client payloadClient-to-server payload
/api/alerts/websocket0x00 followed by an ASCII alert token.Keepalive pong only.
/api/logs/websocketRaw log bytes. A one-byte 0x01 is still a ping.Keepalive pong only.
/api/midi-io/websocket0x00, one reserved byte, then zero or more 12-byte MIDI records.Same framing; bit 0 of record byte 1 requests recording.
/api/midi-stones/stream0x00, then a stream type byte and its payload.Keepalive pong only.

Each MIDI record is:

Record offsetSizeMeaning
01Input source enum.
11Flags/reserved; inbound bit 0 is shouldRecord.
26Event timestamp, unsigned big-endian milliseconds.
81USB-MIDI cable/CIN header.
93MIDI bytes.

MIDI-stone stream type values are 18 error string, 19 no asset yet, 21 raw file data, and 22 deflate-compressed file data.

#Endpoint reference

The detailed endpoint reference follows the same purpose-based order as the API domain guide. JSON in the request column means a UTF-8 JSON body. Empty means send a zero-length body. Paths containing /debug/ and sections explicitly marked dangerous are not stable application-facing contracts.

#Getting started and device information

#Meta

MethodPathRequestResponse
GET/api/meta/capabilitiesNoneMerged API capability flags.
GET/api/meta/endpointsNoneRegistered endpoint array.

#System

MethodPathRequestResponse
GET/api/system/capabilitiesNoneSystem API version flags.
GET/api/system/software-infoNoneApplication, ESP-IDF, partition, hash, and build information.
GET/api/system/cpu-infoNoneChip, CPU, MAC, and installed-app information.
GET/api/system/is-aliveNoneLiveness response.
POST/api/system/rebootEmptyAcknowledges and schedules a reboot.

#Device state

MethodPathRequestResponse
GET/api/device-state/capabilitiesNoneDevice-state API version flags.
GET/api/device-state/getNoneAggregated identity, settings, system, SD, USB, Bluetooth, piano, and recording state.

The aggregated response is convenient for initial UI hydration, but individual endpoints are preferable for polling a single subsystem.

#Identities

UUID fields are stable keys; name fields are editable labels. Renaming changes only the corresponding display name and returns the complete identities object.

MethodPathRequestResponse
GET/api/identities/capabilitiesNoneIdentities API version flags.
GET/api/identities/getNonejamcorderUuid, jamcorderName, performerUuid, and performerName.
POST/api/identities/rename/jamcorder{"jamcorderName": string}Updated identities object.
POST/api/identities/rename/performer{"performerName": string}Updated identities object.

#Time

unixtime is seconds since the Unix epoch. localOffset is minutes from UTC. timeSource must be factory, manual, or app; app is normally the right choice for an application client. daylightSavings is the firmware's CSV rule string and is optional; omitting it clears the rule.

MethodPathRequestResponse
GET/api/time/capabilitiesNoneTime API version flags.
GET/api/time/getNoneUnix time, local offset/string, daylight-saving rule, source, drift estimate, and SNTP state.
POST/api/time/set{"unixtime": number, "localOffset": number, "timeSource": string, "daylightSavings"?: string}Updated time object.
POST/api/time/sntp/disableEmptysntpEnabled: false.
POST/api/time/sntp/enableEmptysntpEnabled: true.

#Music and recordings

#Piano

Piano state is a derived, real-time view of musical activity rather than a recording file. Use it to render a keyboard or activity UI without decoding the library.

MethodPathRequestResponse
GET/api/piano/capabilitiesNonePiano API version flags.
GET/api/piano/stateNonePer-channel held/sustained notes, RPN state, activity, sound, and timing information.

#MIDI recorder

maxSilence is milliseconds. recordMode is grand, expressive, technical, or custom. In custom mode, statusMap and exprFidelity are numeric bitfields and ccFidelity is a 128-character hex encoding of 64 bytes. The three custom fields are optional and default to zero/null at the interface layer.

MethodPathRequestResponse
GET/api/midi-recorder/capabilitiesNoneRecorder API version flags.
GET/api/midi-recorder/settings/getNoneCurrent recorder settings.
POST/api/midi-recorder/settings/setsilenceSkip, maxSilence, recordMode, optional statusMap, exprFidelity, ccFidelityUpdated recorder settings.

#MIDI commands

MIDI commands map selected incoming MIDI gestures to Jamcorder actions. The bookmark endpoint triggers that action directly; the settings endpoints control whether command families are accepted and which octave/safety note identifies them.

MethodPathRequestResponse
GET/api/midi-cmd/capabilitiesNoneMIDI-command API version flags.
POST/api/midi-cmd/bookmarkEmptyCreates a bookmark and returns its result.
GET/api/midi-cmd/settings/getNoneCurrent command toggles, octave, and safety note.
POST/api/midi-cmd/settings/setdisableAllCmds, disablePlayerCmds, disableBookmarkCmds booleans plus integer cmdOctave, cmdSafetyNoteUpdated settings.

#MIDI I/O

All eight booleans are required when setting routes.

MethodPathRequestResponse
GET/api/midi-io/capabilitiesNoneMIDI-I/O API version flags.
GET/api/midi-io/settings/getNoneCurrent filtering and routing matrix.
POST/api/midi-io/settings/setBooleans filtering, dinToDin, dinToBle, dinToUsb, usbToDin, usbToBle, bleToUsb, bleToDinUpdated routing matrix.
GET/api/midi-io/msg-countsNonePer-transport input/output and routed message counters.
GET/api/midi-io/active-convertersNoneactiveInputs and activeOutputs arrays.
WS/api/midi-io/websocketWebSocket upgradeBidirectional framed MIDI records.

#Library

The library is the catalog of recorded JMX assets on storage. Listing can be continued with midiPathContinue; request only the optional metadata a client needs to reduce scanning work. The on-disk recording structure is documented in the JMX MIDI files specification.

MethodPathRequestResponse
GET/api/library/capabilitiesNoneLibrary API version flags.
GET/api/library/download/newest/midiNoneNewest recording as audio/midi.
POST/api/library/list/assetsgetJmxEof, getFilesize, getAllDevices booleans; optional preferredCount integer and midiPathContinue stringPaginated/recent asset list.
GET/api/library/list/yearsNoneYears represented in the library.

#MIDI stones

stoneIdx may be an absolute stone index or a negative index counted backward from the newest stone.

MethodPathRequestResponse
POST/api/midi-stones/download/stone{"midiPath": string, "stoneIdx": integer}Deflate-compressed raw stone bytes.
WS/api/midi-stones/streamWebSocket upgradeLive raw/compressed asset fragments.

#Lifetime statistics

Clearing lifetime statistics is destructive. The clear operation uses compare-and-clear protection. Both string values must exactly match a preceding get response or the request fails.

MethodPathRequestResponse
GET/api/lifestats/capabilitiesNoneLifetime-statistics API version flags.
GET/api/lifestats/getNoneNumeric lifeNotesPlayed and lifeMillisPlayed.
POST/api/lifestats/clearMatching decimal strings lifeNotesPlayed and lifeMillisPlayedcleared: true.

#Storage and content

#SD card — format is destructive

MethodPathRequestResponse
GET/api/sdcard/capabilitiesNoneSD-card API version flags.
GET/api/sdcard/infoNoneDetection, mount, capacity, and free-space information.
GET/api/sdcard/free-bytes/simpleNoneFree bytes.
POST/api/sdcard/format-fix/simpleEmptyFormats/repairs the card and returns card information.
GET/api/sdcard/debug/detailsNoneDetailed SD/FAT diagnostics.

#Files

Filepaths are device-side absolute paths. Use paths returned by the API rather than assuming an SD-card mount name.

MethodPathRequestResponse
GET/api/files/capabilitiesNoneFiles API version flags.
POST/api/files/list/overview{"filepath": string}dir and an array of child names.
POST/api/files/list/detailed{"filepath": string}dir and entries containing filename, isDirectory, sizeBytes, and modifiedLocalTime.
POST/api/files/download/simple{"filepath": string}Whole file with attachment filename.
POST/api/files/download/offset{"filepath": string, "offset": integer, "length": integer}File range. Negative offset is relative to EOF; length <= 0 means through EOF.
POST/api/files/upload/simpleJAMCJSBN with {"filepath": string}Upload result.

Download example:

curl --fail --output recording.jmx \
  -H 'Content-Type: application/json' \
  -d '{"filepath":"/recording.jmx"}' \
  "$JAMCORDER/api/files/download/simple"

#Extensions

MethodPathRequestResponse
GET/api/extensions/capabilitiesNoneExtensions API version flags.
GET/api/extensions/listNoneInstalled extensions.
POST/api/extensions/upload-install-htmlJAMCJSBN with {"filename": string}Install result.
POST/api/extensions/upload-install-tarJAMCJSBN with {"filename": string}Install result.
POST/api/extensions/uninstall{"extFolder": string}Uninstall result.

Installed extension resources are served by the wildcard /extensions/* route. See Local web extensions for folder structure, packaging, browser API access, development, installation, and security guidance. The device-hosted extension page is /docs/extensions.

#Device health and feedback

#Alerts

Alert tokens mean that something changed; they are not complete state objects. Use the token to decide which read endpoint to refresh.

MethodPathRequestResponse
GET/api/alerts/capabilitiesNoneAlerts API version flags.
GET/api/alerts/recentNoneUp to ten recent alert records.
WS/api/alerts/websocketWebSocket upgradeLive alert tokens.

#Issues

Issues are structured, persistent health records rather than raw log messages. See Issues, alerts, and logs for record semantics and guidance on clearing them.

MethodPathRequestResponse
GET/api/issues/capabilitiesNoneIssues API version flags.
GET/api/issues/currentNoneCurrent unresolved issues.
GET/api/issues/historyNoneIssue history.
POST/api/issues/clear/currentEmptyClears current issues.

#Logs

MethodPathRequestResponse
GET/api/logs/capabilitiesNoneLogs API version flags.
GET/api/logs/recent/logsNoneRecent general log bytes.
GET/api/logs/recent/errorsNoneWarning ring buffer in the current implementation.
GET/api/logs/recent/warningsNoneError ring buffer in the current implementation.
POST/api/logs/recent/generic{"maxLen": integer, "logLevel": string}Tail of logs, warnings, or errors, limited to maxLen; negative means all.
WS/api/logs/websocketWebSocket upgradeLive raw log frames.

#Coredump

MethodPathRequestResponse
GET/api/coredump/capabilitiesNoneCoredump API version flags.
GET/api/coredump/summaryNoneCrash metadata and hashes.
GET/api/coredump/downloadNoneRaw coredump (application/octet-stream).

#Buzzer

MethodPathRequestResponse
GET/api/buzzer/capabilitiesNoneBuzzer API version flags.
GET/api/buzzer/settings/getNoneCurrent buzzerDisabled setting.
POST/api/buzzer/settings/set{"buzzerDisabled": boolean}Updated setting.

#Updates and maintenance

#OTA

Firmware images are encrypted device artifacts. Install operations can reboot the device or leave it running JFU; coordinate them as an exclusive workflow.

MethodPathRequestResponse
GET/api/ota/capabilitiesNoneOTA version and AES-key hash capability.
GET/api/ota/overviewNoneRunning environment and installed normal-firmware/JFU versions and hashes.
GET/api/ota/jfu/boot-args/getNonePending one-time JFU boot arguments.
POST/api/ota/jfu/boot-args/setBooleans isModeSdCardEnabled, isModeWifiEnabled, isModeBluetoothEnabled, isModeConsoleEnabledStored boot-argument object.
POST/api/ota/jfu/boot-args/clearEmptyEmpty/current boot-argument object.
POST/api/ota/jfu/reboot-intoEmptyAcknowledges and reboots into JFU after about 2.5 seconds.
POST/api/ota/sd/upload/simpleJAMCJSBN firmware bytesUploaded SD-card filepath.
GET/api/ota/sd/firmware/availableNoneFirmware files in pending/completed/failed SD folders.
POST/api/ota/sd/install/simple{"filepath": string}Install result.
POST/api/ota/direct/install/simpleJAMCJSBN firmware bytesDirect-install result.
GET/api/ota/resumable/install/progressNoneCurrent resumable session/progress.
POST/api/ota/resumable/install/upload-chunkJAMCJSBN chunk plus {"otaWritten": integer}Updated otaWritten progress.

#Automatic reboot

MethodPathRequestResponse
GET/api/auto-reboot/capabilitiesNoneAuto-reboot API version flags.
GET/api/auto-reboot/settings/getNoneCurrent autoRebootTime.
POST/api/auto-reboot/settings/set{"autoRebootTime": integer} in minutesUpdated setting.

#Factory reset — destructive

MethodPathRequestResponse
GET/api/factory-reset/capabilitiesNoneFactory-reset API version flags.
POST/api/factory-reset/allEmptyErases all resettable device state.
POST/api/factory-reset/choose{"keepLifeStats": boolean}Resets state, optionally preserving lifetime statistics.

#Connectivity and setup

#Discovery mode

Discovery mode advertises a Wi-Fi hotspot used for Web-based setup. Entering discovery mode schedules a restart; the response only confirms that the transition was accepted, so clients must expect the connection to drop. See Web-based setup for setup instructions.

MethodPathRequestResponse
GET/api/discovery-mode/capabilitiesNoneDiscovery-mode API version flags.
POST/api/discovery-mode/enterEmptyAcknowledges and transitions/reboots into discovery mode.

#Wi-Fi

SSID and password values are hex-encoded byte strings, not plain text. For example, Studio is 53747564696f. This preserves arbitrary SSID bytes. Changing credentials stores them but does not immediately move the device to the new network; reboot after receiving a successful response.

MethodPathRequestResponse
GET/api/wifi/capabilitiesNoneWi-Fi API version flags.
GET/api/wifi/infoNoneMAC address, mode, connection state, hex SSID, IP, RSSI, and hotspot client count as applicable.
POST/api/wifi/credentials/set{"homeWifiSsid": hex-string, "homeWifiPassword": hex-string}Stored credentials as hex.
POST/api/wifi/credentials/clearEmptyEmpty stored credentials.
GET/api/wifi/scan/simpleNoneapCount, scan maximum, and apList entries with hex ssid, rssi, auth, and channel.

#Bluetooth

MethodPathRequestResponse
GET/api/bluetooth/capabilitiesNoneBluetooth API version flags.
GET/api/bluetooth/state/getNoneHigh-level Bluetooth state.
GET/api/bluetooth/state/detailedNoneDetailed controller, service, connection, and client state.

#USB

MethodPathRequestResponse
GET/api/usb/capabilitiesNoneUSB API version flags.
GET/api/usb/stateNoneCurrent USB state.
GET/api/usb/descriptorsNoneAttached USB MIDI descriptors.

#Engineering and manufacturing

#Fabrication info

These endpoints expose manufacturing identity. set is intended for provisioning, not normal client use.

MethodPathRequestResponse
GET/api/fab-info/capabilitiesNoneFabrication API version flags.
GET/api/fab-info/getNoneFabrication timestamp, physical ID, and product key.
POST/api/fab-info/set{"fabUnixtime": number, "fabProductKey": hex-string} after factory unlockStored fabrication record plus physical ID.

#Verbose logging

firehose, clear, persist, and unpersist mutate state even though the current registry exposes them as GET.

MethodPathRequestResponse
GET/api/verbose/capabilitiesNoneVerbose API version flags.
GET/api/verbose/debug/listNoneTag-number-to-name map.
GET/api/verbose/debug/stateNoneKnown, active, and saved verbose tags.
POST/api/verbose/debug/enableA lone JSON integer tag numberEnabled tag record.
POST/api/verbose/debug/disableA lone JSON integer tag numberDisabled tag record.
GET/api/verbose/debug/firehoseNoneEnables almost all verbose tags and returns state.
GET/api/verbose/debug/clearNoneDisables all verbose tags and returns state.
GET/api/verbose/debug/persistNoneSaves enabled tags to NVS.
GET/api/verbose/debug/unpersistNoneClears saved tags.

#Asset diagnostics

MethodPathRequestResponse
GET/api/asset/debug/next-headerNoneHeader for the next/current recording asset.
POST/api/asset/debug/eof-summary{"filepath": string}Parsed JMX EOF summary.

#Developer settings

Command numbers are firmware-internal. Read the list before changing one. The current implementation of /cmd/unset calls the same setter as /cmd/set; clients that need to clear a command should verify the returned state.

MethodPathRequestResponse
GET/api/developer/capabilitiesNoneDeveloper API version flags.
GET/api/developer/settingsNoneCurrent developer-mode settings.
POST/api/developer/mode/enableEmptyEnables developer mode.
POST/api/developer/mode/disableEmptyDisables developer mode.
GET/api/developer/cmd/listNoneKnown developer command numbers and state.
POST/api/developer/cmd/set{"cmd": positive number}Updated developer settings.
POST/api/developer/cmd/unset{"cmd": positive number}Currently behaves like cmd/set; verify response.
POST/api/developer/reset-allEmptyResets developer settings.

#Heap diagnostics

MethodPathRequestResponse
GET/api/heap/debug/free-bytesNoneHeap totals by memory capability.
GET/api/heap/debug/alloc-statsNonePlain-text allocation statistics.
GET/api/heap/debug/check-integrityNoneHeap-integrity result.
POST/api/heap-trace/debug/start-allEmptyStarts tracing all allocations.
POST/api/heap-trace/debug/start-leaksEmptyStarts leak tracing.
POST/api/heap-trace/debug/pauseEmptyPauses tracing.
POST/api/heap-trace/debug/resumeEmptyResumes tracing.
GET/api/heap-trace/debug/dump/allNonePlain-text complete trace.
GET/api/heap-trace/debug/dump/internalNonePlain-text internal-memory trace.
GET/api/heap-trace/debug/dump/spiNonePlain-text SPI-RAM trace.
GET/api/heap-trace/debug/summaryNoneJSON trace summary.

#System debug

MethodPathRequestResponse
GET/api/debug/freertos-tasksNoneFreeRTOS task/runtime information.
GET/api/debug/partition-tableNoneParsed partition table.
GET/api/debug/efuses/listNoneDecoded eFuse list.
GET/api/debug/efuses/rawNoneRaw eFuse data.
POST/api/debug/force-system-crashEmptyDeliberately crashes the running firmware. A normal response is not guaranteed.

#NVS debug

Writing NVS values changes persistent device state.

MethodPathRequestResponse
GET/api/nvs/debug/listNoneKnown NVS keys, types, and readable values. Blob values report length only.
POST/api/nvs/debug/set{"key": string, "value": number or string}Updated full NVS listing. Blob writes are unsupported.

#Self-test

Test numbers are runtime-defined; fetch the list first. Factory-suite execution is registered as a GET even though it operates hardware.

MethodPathRequestResponse
GET/api/self-test/capabilitiesNoneSelf-test API version flags.
GET/api/self-test/listNoneTest numbers and names.
POST/api/self-test/run/single-testA lone JSON integer test numberTest result.
GET/api/self-test/run/factory-test-suiteNoneFactory-suite result.

#Factory mode and certificate provisioning

Factory mode must be unlocked before protected manufacturing writes. PEM values for the upload endpoints are hex-encoded bytes.

MethodPathRequestResponse
GET/api/factory-mode/capabilitiesNoneFactory-mode API version flags.
POST/api/factory-mode/unlock{"password": string}Unlock state.
GET/api/factory-mode/stsafe/preprov-cert-derNonePre-provisioned certificate DER bytes.
POST/api/factory-mode/stsafe/upload-issued-cert-pem{"stsafeIssuedCertPem": hex-string}Provisioning result.
POST/api/factory-mode/stsafe/upload-ca-cert-pem{"stsafeCaCertPem": hex-string}Provisioning result.

#STSAFE

MethodPathRequestResponse
GET/api/stsafe/capabilitiesNoneSTSAFE API version flags.
GET/api/stsafe/ca-cert-pemNoneCA certificate as PEM text.
GET/api/stsafe/issued-cert-pemNoneIssued certificate as PEM text.
POST/api/stsafe/challenge{"challengeHex": hex-string}Challenge signature/result.
POST/api/stsafe/bulk-challenge/simple{"challengeHex": hex-string, "bulkCount": integer}Bulk challenge data download.
POST/api/stsafe/print-all-zone-bytesEmptyPrints secure-element zones and returns status.

#MIDI hardware tests

MethodPathRequestResponse
POST/api/midi-tests/debug/triad-outEmptyEmits an outbound test triad.
POST/api/midi-tests/debug/triad-inEmptyInjects an inbound test triad.
POST/api/midi-tests/debug/complex-inEmptyInjects a complex inbound test sequence.
POST/api/midi-tests/debug/complex-outEmptyEmits a complex outbound test sequence.

#Non-API HTTP routes

These routes serve built-in UI, diagnostics, and installed extension content. Their HTML is not a machine-readable API contract.

MethodRoutePurpose
GET/Firmware index.
GET/favicon.icoFavicon.
GET/logsLive logs page.
GET/webappMain web app.
GET/webapp/*Main web-app assets.
GET/sdcard/?*SD-card web-app route.
GET/extensions/*Installed extension resources.
GET/docs/extensionsExtension documentation page.
GET/internalInternal diagnostics page.
GET/jfuFirmware-update page.
GET/test-pages/websocket-midiMIDI WebSocket test page.
GET/test-pages/websocket-stonesMIDI-stone WebSocket test page.
GET/test-pages/websocket-alertsAlerts WebSocket test page.
GET/test-pages/ble-infoBLE information test page.
GET/test-pages/ble-httpBtHttp test page.
GET/test-pages/ble-stonesBLE MIDI-stone test page.
GET/test-pages/ble-alertsBLE alerts test page.
GET/test-pages/otaOTA test page.

#Other transports

The same registry-backed API can be invoked over HTTP, Bluetooth BtHttp, or the serial console. WebSockets remain HTTP-only.

#Bluetooth BtHttp

BtHttp is exposed by service 02AA0001-4202-649d-ec11-dfdb58e9372d and characteristic 02AA0002-4202-649d-ec11-dfdb58e9372d. Subscribe to indications before writing a request.

Each BLE packet begins with a socket index and delimiter:

OffsetSizeMeaning
01Client-chosen socket index. A connection supports multiple logical sockets.
1110 start, 11 continue, 12 end, or 13 single-packet message.
2...Message fragment. The first fragment begins with a message-type byte.

Message types are 20 request header, 21 request body, 40 response header, and 41 response body. Header messages are NUL-terminated string pairs. A request header begins with method and URI, then field-name/field-value pairs:

GET\0/api/device-state/get\0Content-Length\00\0

A response header begins with Status, its value, then response fields. Every BtHttp request must include a valid Content-Length, including 0 for a GET. Body bytes use the same JSON or JAMCJSBN representation as HTTP. The device can track up to six BLE clients and sixteen logical sockets in the current build.

#Serial console

When the console is enabled, each registered URI is also a command name. JSON input/download commands take a single JSON argument, for example:

/api/identities/get
/api/identities/rename/jamcorder {"jamcorderName":"Bench"}

The console also assigns numeric aliases based on registry order. These are diagnostic conveniences and are not stable across firmware versions. Binary downloads are delimited by [transmissionStart] and [transmissionComplete] and encoded as console-safe hex. Upload endpoints and WebSockets are not supported by the console transport.

#JFU mode

JFU is the firmware updater and recovery environment. Most integrations do not need to account for it. Clients that operate while JFU is running should use /api/meta/endpoints as the definitive runtime list.

#API endpoints available in JFU

DomainAvailable endpoints
Meta/api/meta/capabilities
/api/meta/endpoints
System/api/system/capabilities
/api/system/software-info
/api/system/cpu-info
/api/system/is-alive
/api/system/reboot
Issues/api/issues/capabilities
/api/issues/current
/api/issues/history
/api/issues/clear/current
Logs/api/logs/capabilities
/api/logs/recent/logs
/api/logs/recent/errors
/api/logs/recent/warnings
/api/logs/recent/generic
/api/logs/websocket
Coredump/api/coredump/capabilities
/api/coredump/summary
/api/coredump/download
OTA/api/ota/capabilities
/api/ota/overview
/api/ota/jfu/boot-args/get
/api/ota/jfu/boot-args/set
/api/ota/jfu/boot-args/clear
/api/ota/jfu/reboot-into
/api/ota/sd/upload/simple
/api/ota/sd/firmware/available
/api/ota/sd/install/simple
/api/ota/direct/install/simple
/api/ota/resumable/install/progress
/api/ota/resumable/install/upload-chunk
Factory reset/api/factory-reset/capabilities
/api/factory-reset/all
/api/factory-reset/choose
Fabrication info/api/fab-info/capabilities
/api/fab-info/get
/api/fab-info/set
Verbose logging/api/verbose/capabilities
/api/verbose/debug/list
/api/verbose/debug/state
/api/verbose/debug/enable
/api/verbose/debug/disable
/api/verbose/debug/firehose
/api/verbose/debug/clear

The Verbose logging persistence endpoints, /api/verbose/debug/persist and /api/verbose/debug/unpersist, are not available in JFU.

#Non-API routes available in JFU

MethodRoutePurpose
GET/Firmware index.
GET/favicon.icoFavicon.
GET/logsLive logs page.