Connect in 5 Minutes
Send your first API request to AudioMap and start building.
Prerequisites
- AudioMap installed and running on your machine with a Pro license
- Any language with WebSocket support (Python, JavaScript, C++, etc.)
The API server starts automatically when AudioMap launches. The API is gated behind the Pro license tier.
Connect via WebSocket
Open a WebSocket connection to ws://127.0.0.1:9010. The API uses JSON-RPC 2.0 — every message is a JSON object with jsonrpc, method, and id fields.
import asyncio, websockets, json
from pathlib import Path
async def main():
async with websockets.connect("ws://127.0.0.1:9010") as ws:
# Step 1: Read the session token
token_path = Path.home() / "Library/Application Support/AudioMap/api_session_token"
token = token_path.read_text().strip()
# Step 2: Authenticate (must be the first message)
await ws.send(json.dumps({
"jsonrpc": "2.0",
"method": "authenticate",
"params": {"token": token},
"id": 1
}))
auth = json.loads(await ws.recv())
assert auth["result"]["authenticated"]
# Step 3: Now you can call any API method
await ws.send(json.dumps({
"jsonrpc": "2.0",
"method": "ping",
"id": 2
}))
response = json.loads(await ws.recv())
print(response)
asyncio.run(main())Install: pip install websockets
import { readFileSync } from "fs";
import { homedir } from "os";
import { join } from "path";
// Read the session token
const tokenPath = join(homedir(), "Library/Application Support/AudioMap/api_session_token");
const token = readFileSync(tokenPath, "utf-8").trim();
const ws = new WebSocket("ws://127.0.0.1:9010");
ws.onopen = () => {
// Authenticate first (must be the first message)
ws.send(JSON.stringify({
jsonrpc: "2.0",
method: "authenticate",
params: { token },
id: 1
}));
};
ws.onmessage = (event) => {
const msg = JSON.parse(event.data);
if (msg.id === 1 && msg.result?.authenticated) {
// Authenticated — now send API requests
ws.send(JSON.stringify({
jsonrpc: "2.0",
method: "ping",
id: 2
}));
} else {
console.log(msg);
}
};Authenticate
The first message on every new connection must be an authenticate call. All other API methods are rejected until authentication succeeds.
How it works
- 1AudioMap generates a random session token on launch and writes it to a local file.
- 2Your client reads the token and sends it with the
authenticatemethod. - 3The token changes every time AudioMap restarts. It is deleted on shutdown.
Token file location
~/Library/Application Support/AudioMap/api_session_token%APPDATA%\AudioMap\api_session_token{
"jsonrpc": "2.0",
"method": "authenticate",
"params": {
"token": "a1b2c3d4e5f6..."
},
"id": 1
}{
"jsonrpc": "2.0",
"result": {
"authenticated": true
},
"id": 1
}Why token-based auth? The token file is only readable by the local user account, preventing other devices on the network from accessing the API without physical access to the machine.
Query App State
Use getState to see the current configuration:
{
"jsonrpc": "2.0",
"method": "getState",
"id": 2
}{
"jsonrpc": "2.0",
"result": {
"audioDevice": "Built-in Output",
"sampleRate": 48000,
"fftSize": 4096,
"numSources": 2,
"numReceivers": 1,
"measurementCount": 5
},
"id": 2
}Trigger a Capture
The capture method is asynchronous — it returns immediately and sends a completion event when done. Subscribe to events first to receive the result.
# 1. Subscribe to capture events
await ws.send(json.dumps({
"jsonrpc": "2.0",
"method": "subscribe",
"params": {"events": ["captureComplete"]},
"id": 3
}))
await ws.recv() # subscription confirmation
# 2. Trigger capture
await ws.send(json.dumps({
"jsonrpc": "2.0",
"method": "capture",
"id": 4
}))
await ws.recv() # {"result": {"captureId": "...", "status": "started"}}
# 3. Wait for completion event
event = json.loads(await ws.recv())
# {"method": "event.captureComplete", "params": {"success": true, ...}}Read Measurement Data
List measurements, then fetch frequency response data for any measurement:
# List all measurements
await ws.send(json.dumps({
"jsonrpc": "2.0",
"method": "getMeasurements",
"id": 5
}))
measurements = json.loads(await ws.recv())
# Get transfer function data for first measurement
measurement_id = measurements["result"]["measurements"][0]["id"]
await ws.send(json.dumps({
"jsonrpc": "2.0",
"method": "getMeasurementData",
"params": {"id": measurement_id},
"id": 6
}))
data = json.loads(await ws.recv())
# data["result"]["frequencies"], data["result"]["magnitude"], etc.Error Handling
Errors follow JSON-RPC 2.0 conventions. Check for an error field in the response:
{
"jsonrpc": "2.0",
"error": {
"code": -32601,
"message": "Method not found"
},
"id": 1
}| Code | Meaning |
|---|---|
| -32700 | Parse error (invalid JSON) |
| -32600 | Invalid request |
| -32601 | Method not found |
| -32602 | Invalid params |
| -32603 | Internal error |
| -32000 | App not ready (audio engine not initialized) |
| -32001 | Capture in progress |
| -32002 | Operation timeout |
| -32003 | Invalid measurement ID |
| -32004 | Not authenticated (send authenticate first) |