Skip to main content

Native API

The Native API is a localhost HTTP server hosted by Toby.app (the macOS app). It exists for operations that must run under Toby.app’s signed bundle identity — macOS TCC permissions, EventKit, Contacts, Location Services, Accessibility, microphone/system audio capture, and related system controls.

This page is the endpoint reference. For how this differs from the daemon Server API, see Local APIs. Product surfaces of the Mac app are in Toby.app.

:::note Server API is separate Chat, sessions, configure, memories, projects, and recording list/transcribe use the Server API on port 7847. Do not call those routes on the Native API host. :::

Why this API exists

macOS ties permission grants (Calendar, Contacts, Reminders, Location, Microphone, Screen Recording / system audio, Accessibility, Notifications) to the calling binary’s identity. Raw CLI or plugin binaries show confusing names in System Settings, or fail EventKit/XPC checks.

By routing through Toby.app:

  • Users grant permissions once to a clearly named app
  • Plugins stay TypeScript and call HTTP instead of shipping native code
  • Audio capture stays owned by the app process (AVFoundation / ScreenCaptureKit)

Access model

ItemDetail
HostToby.app process (must be running, or auto-launched by clients)
PortEphemeral — written to ~/.toby/native-port as plain text (e.g. 53142)
Base URLhttp://127.0.0.1:<port from native-port>
BindingLocalhost only
AuthNone (local trust) — do not expose this port
EncodingJSON request bodies; JSON responses
Response envelopeSuccess: {"ok":true,"data":{...}} · Failure: {"ok":false,"error":"..."} (often with "needsPermission":true)

Discovery

  1. Ensure Toby.app is installed and can be launched.

  2. Read the port:

    cat ~/.toby/native-port
  3. Confirm liveness:

    curl -s "http://127.0.0.1:$(cat ~/.toby/native-port)/api/native/health"

Example health response:

{ "ok": true, "service": "toby-native" }

First-party plugins (Apple Calendar, Contacts, Reminders, macOS) and the listen/audio path auto-launch Toby.app if the health check fails, then wait for the port file and retry.

Permissions

When access is denied, handlers typically return:

{
"ok": false,
"error": "Calendar access denied.",
"needsPermission": true
}

Grant the relevant permission to Toby.app in System Settings → Privacy & Security (Calendar, Contacts, Reminders, Location Services, Microphone, Screen & System Audio Recording, Accessibility, Notifications, etc.). You can also use Toby.app’s Permissions window.

Who uses the Native API

ClientTypical use
Toby.app (self)Loopback for audio capture so AVFoundation / ScreenCaptureKit stay in-process
toby-plugin-applecalendarEventKit calendar tools
toby-plugin-applecontactsContacts.framework search / detail
toby-plugin-appleremindersEventKit reminder tools
toby-plugin-macosWi‑Fi, battery, audio devices, windows, clipboard, shortcuts, …
CLI / core listen pathStart/stop/combine recording via /api/native/audio/*
Core getMyLocation toolCurrent location via /api/native/location/*

After capture, listing, deleting, and transcribing recordings return to the Server API (/api/listen/…).

Endpoint index

MethodPathPurpose
GET/api/native/healthLiveness check
POST/api/native/calendar/request-accessPrompt Calendar permission
POST/api/native/calendar/listList calendars
POST/api/native/calendar/searchSearch events
POST/api/native/calendar/getGet event by uid
POST/api/native/calendar/createCreate event
POST/api/native/calendar/updateUpdate event
POST/api/native/calendar/deleteDelete event
POST/api/native/contacts/request-accessPrompt Contacts permission
POST/api/native/contacts/searchSearch contacts
POST/api/native/contacts/getGet contact by identifier
POST/api/native/location/statusLocation authorization status
POST/api/native/location/request-accessPrompt Location Services
POST/api/native/location/currentOne-shot current location
POST/api/native/reminders/request-accessPrompt Reminders permission
POST/api/native/reminders/listsList reminder lists
POST/api/native/reminders/searchSearch reminders
POST/api/native/reminders/getGet reminder by id
POST/api/native/reminders/createCreate reminder
POST/api/native/reminders/updateUpdate reminder
POST/api/native/reminders/completeComplete / uncomplete
POST/api/native/reminders/deleteDelete reminder
POST/api/native/schedules/completion-notificationSchedule-run completion notification
GET/api/native/macos/accessibility-statusAccessibility grant status
POST/api/native/macos/wifi-statusWi‑Fi interface status
POST/api/native/macos/wifi-scanScan networks
POST/api/native/macos/wifi-set-powerEnable/disable Wi‑Fi
POST/api/native/macos/battery-statusBattery snapshot
POST/api/native/macos/audio-list-outputsList audio outputs
POST/api/native/macos/audio-switch-outputSwitch default output
POST/api/native/macos/audio-volumeCurrent volume
POST/api/native/macos/audio-set-volumeSet volume 0–100
POST/api/native/macos/audio-set-muteMute/unmute
POST/api/native/macos/bluetooth-statusBluetooth status
POST/api/native/macos/bluetooth-set-powerEnable/disable Bluetooth
POST/api/native/macos/low-power-statusLow Power Mode status
POST/api/native/macos/low-power-setSet Low Power Mode
POST/api/native/macos/shortcuts-runRun a Shortcuts shortcut
POST/api/native/macos/display-brightnessCurrent brightness
POST/api/native/macos/display-set-brightnessSet brightness 0–100
POST/api/native/macos/clipboard-readRead clipboard text
POST/api/native/macos/clipboard-writeWrite clipboard text
POST/api/native/macos/system-infoMachine / OS info
POST/api/native/macos/notification-showShow a user notification
POST/api/native/macos/minimize-allMinimize all windows (Accessibility)
POST/api/native/macos/unminimize-allUnminimize all windows
POST/api/native/macos/minimize-appMinimize one app’s windows
POST/api/native/macos/unminimize-appUnminimize one app’s windows
POST/api/native/macos/windows-hide-allHide all apps
POST/api/native/macos/windows-show-allShow all apps
POST/api/native/macos/window-hide-appHide one app
GET/api/native/audio/statusNative recording state
POST/api/native/audio/startStart mic / system capture
POST/api/native/audio/stopStop and save or discard
POST/api/native/audio/combineCombine mic + system WAVs to combined.m4a

Most operation endpoints accept POST with a JSON body (even when empty). Health and a few status routes use GET.

Health

GET /api/native/health

{ "ok": true, "service": "toby-native" }

Use this before other calls. Unknown paths return 404 with {"ok":false,"error":"…"}.

Calendar (EventKit)

Requires Calendar access for Toby.app.

POST /api/native/calendar/request-access

Prompts if needed.

Success: { "ok": true, "data": { "prompted": true, "granted": true } }
Denied: ok: false, needsPermission: true.

POST /api/native/calendar/list

{
"ok": true,
"data": {
"calendars": [{ "name": "Home", "color": "…" }],
"count": 1
}
}

POST /api/native/calendar/search

type SearchEventsBody = {
query?: string;
calendar?: string; // calendar title filter
dateFrom?: string; // ISO-ish start bound
dateTo?: string;
limit?: number; // default 30, max 200
};

Returns { events, count } under data.

POST /api/native/calendar/get

{ "uid": "…", "calendar": "optional title check" }

POST /api/native/calendar/create

Required: summary, startDate, endDate (ISO 8601, e.g. 2026-01-15T09:00:00).

Optional: calendar, allDay, location, description.

{ "ok": true, "data": { "uid": "…", "summary": "…" } }

POST /api/native/calendar/update

Required: uid. Optional field updates: summary, startDate, endDate, location, description, allDay, calendar (match check).

POST /api/native/calendar/delete

Required: uid.

Contacts

Requires Contacts access for Toby.app.

POST /api/native/contacts/request-access

Same pattern as calendar request-access.

POST /api/native/contacts/search

type SearchContactsBody = {
query?: string; // empty = first N contacts
limit?: number; // default 25, max 100
};

Contact summaries include identifier, displayName, names, organization, emails, phones.

POST /api/native/contacts/get

{ "identifier": "…" }

Returns full contact detail under data.

Location (CoreLocation)

Requires Location Services access for Toby.app. Used by the global getMyLocation chat tool. You can also grant access from Toby.app’s Permissions window (Location Access).

POST /api/native/location/status

Returns authorization status without prompting:

{
"ok": true,
"data": {
"authorizationStatus": "authorizedWhenInUse",
"granted": true,
"servicesEnabled": true
}
}

POST /api/native/location/request-access

Prompts for Location Services when status is not yet determined.

POST /api/native/location/current

One-shot location fix. Prompts for permission when needed.

type CurrentLocationBody = {
accuracy?: "best" | "hundredMeters" | "kilometer"; // default hundredMeters
reverseGeocode?: boolean; // default true
};

Success data includes latitude, longitude, horizontalAccuracyMeters, timestamp, and optional place (reverse-geocoded fields such as locality, country, displayName).

Reminders (EventKit)

Requires Reminders access for Toby.app.

POST /api/native/reminders/request-access

POST /api/native/reminders/lists

{
"ok": true,
"data": {
"lists": [{ "name": "Reminders", "color": "…" }],
"count": 1
}
}

POST /api/native/reminders/search

type SearchRemindersBody = {
query?: string;
list?: string;
completed?: boolean; // default false unless completedFrom/To set
completedFrom?: string;
completedTo?: string;
dueFrom?: string;
dueTo?: string;
limit?: number; // default 30, max 200
};

POST /api/native/reminders/get

Required: id. Optional: list (title match check).

POST /api/native/reminders/create

Required: title. Optional: list, notes, dueDate (ISO 8601), priority (0, 1, 5, or 9), url.

POST /api/native/reminders/update

Required: id. Optional: title, notes, list, dueDate (empty string clears), priority, url.

POST /api/native/reminders/complete

Required: id. Optional: completed (default true).

POST /api/native/reminders/delete

Required: id.

Audio capture

Used by Toby.app UI and the listen / CLI capture path. Microphone and Screen/System Audio permissions belong to Toby.app.

GET /api/native/audio/status

Returns recording state under data (idle vs recording, message, options when active).

POST /api/native/audio/start

{ "mic": true, "system": true }

Defaults: both sources true. At least one source must be selected. Fails if already recording.

POST /api/native/audio/stop

{ "action": "save" }

or

{ "action": "discard" }

Default is save. On save, returns id, outputDir, files (paths), and optional errors. Files land under Toby’s listen storage; use the Server API to list, patch, delete, or transcribe.

POST /api/native/audio/combine

{
"outDir": "/path/to/recording-dir",
"mic": "/path/to/mic.wav",
"system": "/path/to/system.wav"
}

outDir is required. Optional mic / system paths. Returns { "combined": "…/combined.m4a" } on success.

macOS system controls

These endpoints back toby-plugin-macos. Window minimize/unminimize paths need Accessibility for Toby.app. Notification show may prompt for Notifications.

Status / read (body often empty)

PathNotes
GET /api/native/macos/accessibility-statusWhether Accessibility is granted
POST /api/native/macos/wifi-statusInterface power / association
POST /api/native/macos/wifi-scanNearby networks
POST /api/native/macos/battery-statusCharge %, power source
POST /api/native/macos/audio-list-outputsOutput devices
POST /api/native/macos/audio-volumeVolume level
POST /api/native/macos/bluetooth-statusPower / connectivity
POST /api/native/macos/low-power-statusLow Power Mode
POST /api/native/macos/display-brightnessBrightness
POST /api/native/macos/clipboard-readClipboard string
POST /api/native/macos/system-infoHostname, machine, OS version, Apple Silicon flag

Mutations (JSON body)

PathBody fields
/api/native/macos/wifi-set-powerenabled (boolean)
/api/native/macos/audio-switch-outputdeviceSubstring (string)
/api/native/macos/audio-set-volumelevel (0–100)
/api/native/macos/audio-set-mutemuted (boolean)
/api/native/macos/bluetooth-set-powerenabled (boolean)
/api/native/macos/low-power-setenabled (boolean)
/api/native/macos/shortcuts-runname (shortcut name)
/api/native/macos/display-set-brightnesslevel (0–100)
/api/native/macos/clipboard-writetext (non-empty string)
/api/native/macos/notification-showtitle, description (required); ctas (string array, max 4)
/api/native/macos/minimize-appname (app name)
/api/native/macos/unminimize-appname
/api/native/macos/window-hide-appappName

Windows (Accessibility)

No body required for:

  • POST /api/native/macos/minimize-all
  • POST /api/native/macos/unminimize-all
  • POST /api/native/macos/windows-hide-all
  • POST /api/native/macos/windows-show-all

Schedule completion notifications

POST /api/native/schedules/completion-notification

Used when a scheduled job finishes and Toby should surface a local notification.

Typical body fields: scheduleId (required), optional scheduleName, runId, status, error.

Example: call from the shell

PORT=$(cat ~/.toby/native-port)

curl -s "http://127.0.0.1:${PORT}/api/native/health"

curl -s -X POST "http://127.0.0.1:${PORT}/api/native/calendar/list" \
-H "Content-Type: application/json" \
-d '{}'

curl -s -X POST "http://127.0.0.1:${PORT}/api/native/audio/start" \
-H "Content-Type: application/json" \
-d '{"mic":true,"system":true}'

Plugin integration pattern

First-party plugins use a shared client approach:

  1. Read ~/.toby/native-port
  2. GET /api/native/health
  3. If down, launch Toby.app (open -g …) and retry
  4. POST the operation path with a JSON body
  5. Interpret { ok, data, error, needsPermission }

Optional env: TOBY_APP_PATH to point at a specific .app bundle when auto-launching.

See also