app.api - API Availability Query
Query the availability and version information of API functions.
Methods
app.api.version()
Get the current API engine version.
Returns: string
local ver = app.api.version()
-- "1.1.0"
app.api.available(path)
Check whether a specified API function is available (registered and not denied by permissions).
Parameters:
path(string) - full function path, e.g."app.bluetooth.watch"
Returns: boolean
if app.api.available("app.bluetooth.watch") then
app.bluetooth.watch("deviceDisconnected", function(e)
app.log.info("Device disconnected: " .. e.name)
end)
else
app.log.warn("Bluetooth watch API is not available")
end
app.api.since(path)
Query the version in which a specified API function was introduced.
Parameters:
path(string) - full function path
Returns: string | nil - introduction version, or nil if unknown
local v = app.api.since("app.bluetooth.watch")
-- "1.1.0"
local v2 = app.api.since("app.nonexistent.fn")
-- nil
Description
- L0 security module — available to all plugins without additional permissions
- Replaces the deprecated
_API_VERSIONglobal variable app.api.availabledistinguishes between “function does not exist” and “denied by permissions”; if a function exists but the current plugin lacks the required permission, it still returnsfalse- Recommended to call
app.api.availablebefore invoking high-privilege APIs to provide graceful degradation messages to users
Error Codes app.errors
The err.code value returned by any API call comes from a fixed set of constants exposed via app.errors.*. Use them instead of magic strings:
| Constant | Value | Meaning |
|---|---|---|
app.errors.INVALID_ARGUMENT |
"INVALID_ARGUMENT" |
Missing argument, wrong type, or invalid format |
app.errors.OPERATION_FAILED |
"OPERATION_FAILED" |
Operation failed (default catch-all) |
app.errors.PERMISSION_DENIED |
"PERMISSION_DENIED" |
Plugin did not declare this permission (plugin.json) |
app.errors.SYSTEM_PERMISSION_NOT_GRANTED |
"SYSTEM_PERMISSION_NOT_GRANTED" |
System permission not granted (accessibility, bluetooth, location, etc.) |
Typical usage:
local ok, err = app.shell.execute("some cmd")
if not ok then
if err.code == app.errors.PERMISSION_DENIED then
app.dialog.alert("Authorization required", err.message)
elseif err.code == app.errors.INVALID_ARGUMENT then
app.log.error("Bad argument: " .. err.message)
else
app.log.error(err.message) -- fallback: just log
end
end
Most plugins only need err.message for display or logging; err.code is useful when you need to branch on the failure reason.
Examples
Select Implementation by Version
function MyPlugin:onMenuItems(context)
-- Prefer newer API, fall back gracefully on older engines
if app.api.available("app.chooser.show") then
local item = app.chooser.show({{text = "Option A"}, {text = "Option B"}})
if item then
self:handleChoice(item.text)
end
else
local choice = app.dialog.input("Enter an option", "Option A")
if choice then
self:handleChoice(choice)
end
end
end
Version Detection and User Feedback
function MyPlugin:onMenuItems(context)
local ver = app.api.version()
app.log.info("API engine version: " .. ver)
if not app.api.available("app.ocr.recognize") then
app.dialog.alert("Feature Unavailable", "OCR is not supported in this version. Please upgrade iRightMenu Pro.")
return
end
local text = app.ocr.recognize(context.selectedFiles[1])
app.clipboard.set(text)
app.notification.show("Done", "Copied to clipboard")
end