API: Difference between revisions
No edit summary |
m Text replacement - "TapScript" to "ZapScript" |
||
(26 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
{{Warn|This page refers to the future version 2.0.0 of | {{Warn|This page refers to the future version 2.0.0 of Zaparoo which is in active development. Please don't use any information on this page until it's been finalised and released.}} | ||
The | The Zaparoo API is available on and published by every device running the [[Zaparoo Core|core Zaparoo software]]. This API allows management of all Zaparoo features locally and remotely. The [https://zaparoo.app/ Zaparoo] app uses this API for all communication with Zaparoo devices, as do most of the flags when Zaparoo is run via the command line. | ||
This page documents the protocol used to communicate with the API and | This page documents the protocol used to communicate with the API and how to interact with it. ''It is the source of truth when developing applications that work with Zaparoo.'' | ||
== Communication Protocol == | == Communication Protocol == | ||
The API uses a standard WebSocket connection to exchange JSON payloads using | The API uses a standard [https://developer.mozilla.org/en-US/docs/Web/API/WebSocket WebSocket] connection to exchange [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON JSON] payloads using the [https://www.jsonrpc.org/specification JSON-RPC 2.0] protocol. | ||
All remote | All remote cleartext WebSocket connections must encrypt every payload using the [[API#Secure Layer|secure layer]] detailed below, or else the payload will be rejected. Local unencrypted connections are allowed, depending on the platform and privilege context of the running service. | ||
Communication follows a loose client-server relationship. Clients, by default, are not expected to implement the API beyond what that particular client needs to function. | |||
=== Connection === | === Connection === | ||
Connections to the API can be established with any standard WebSocket client, using the root endpoint (<code>/</code>) of the HTTP server published by the | Connections to the API can be established with any standard WebSocket client, using the root endpoint (<code>/</code>) of the HTTP server published by the Zaparoo service. By default, the HTTP server is accessible on port <code>7497</code>. This port is configurable by the user. | ||
An example address for connecting to the API: <code>ws://10.0.0.123:7497/</code> | An example address for connecting to the API: <code>ws://10.0.0.123:7497/</code> | ||
The connection requires no special configuration or authentication to | The connection requires no special configuration or authentication to initiate. | ||
=== JSON Payloads === | === JSON Payloads === | ||
Server and clients communicate back and forth using JSON payloads, following the [https://www.jsonrpc.org/specification JSON-RPC 2.0] protocol. | |||
Because a WebSocket connection is asynchronous, request payloads are tagged with a unique ID. The client | Because a WebSocket connection is asynchronous, request payloads are tagged with a unique ID. The client must keep track of IDs sent to another client and wait for a matching response object. A client can continue sending requests while waiting for responses to previous requests. | ||
==== Requests ==== | ==== Requests ==== | ||
A request object asks the connected | A request object asks the connected server to run a predefined [[API#Methods|method]], and report back when it's completed with a response object. | ||
An example request:<syntaxhighlight lang="json"> | An example request:<syntaxhighlight lang="json"> | ||
{ | { | ||
" | "jsonrpc": "2.0", | ||
"id": " | "id": "4b5da056-a5d4-436b-b4e6-b96231e99969", | ||
"method": "media.search", | "method": "media.search", | ||
"params": { | "params": { | ||
Line 35: | Line 36: | ||
} | } | ||
} | } | ||
</syntaxhighlight>This request would query | </syntaxhighlight>This request would query Zaparoo's media database for a filename containing the word "240p" and return a response with the search results. | ||
Request | ===== Request object ===== | ||
{| class="wikitable" | {| class="wikitable" | ||
|+ | |+ | ||
Line 45: | Line 46: | ||
!Description | !Description | ||
|- | |- | ||
| | |jsonrpc | ||
| | |string | ||
|Yes | |Yes | ||
| | |As per the JSON-RPC 2.0 spec, this key's value must be the string <code>2.0</code> for a payload to be accepted. | ||
|- | |- | ||
|id | |id | ||
|string | |string | ||
|Yes* | |Yes* | ||
|A UUID | |A UUID generated by the requesting client, used to match requests back to responses. A request missing this key is valid but would be treated as a notification and not receive any response. | ||
|- | |- | ||
|method | |method | ||
|string | |string | ||
|Yes | |Yes | ||
|A string corresponding to a method to be run by the receiving | |A string corresponding to a method to be run by the receiving server. | ||
|- | |- | ||
|params | |params | ||
Line 70: | Line 66: | ||
|Arguments supplied for the method. The value of this key depends on the method used and is omitted for some methods. | |Arguments supplied for the method. The value of this key depends on the method used and is omitted for some methods. | ||
|} | |} | ||
All available request methods and their parameters are documented below. | All available request methods and their parameters are [[API#Methods|documented below]]. | ||
==== Notifications ==== | |||
Notifications are requests which do not contain an ID. Otherwise, they are identical to a standard request object. Notifications can be sent by either | Notifications are requests which do not contain an ID. Otherwise, they are identical to a standard request object. Notifications can be sent by either server or client and do not receive a response. | ||
Like standard requests, notifications may or may not have parameters and its value will depend on the method. Types of notifications are documented below. | Like standard requests, notifications may or may not have parameters and its value will depend on the method. Types of notifications are [[API#Notifications|documented below]]. | ||
==== Responses ==== | ==== Responses ==== | ||
Every request sent must have a matching response. An example response to the media.search request shown above:<syntaxhighlight lang="json"> | Every request sent must have a matching response. An example response to the media.search request shown above:<syntaxhighlight lang="json"> | ||
{ | { | ||
" | "jsonrpc": "2.0", | ||
"id": " | "id": "4b5da056-a5d4-436b-b4e6-b96231e99969", | ||
"result": { | "result": { | ||
" | "media": [{ | ||
"system": { | "system": { | ||
"id": "Gameboy", | "id": "Gameboy", | ||
Line 95: | Line 90: | ||
} | } | ||
} | } | ||
</syntaxhighlight>Response | </syntaxhighlight> | ||
===== Response object ===== | |||
{| class="wikitable" | {| class="wikitable" | ||
!Key | !Key | ||
Line 102: | Line 99: | ||
!Description | !Description | ||
|- | |- | ||
| | |jsonrpc | ||
|number | |number | ||
|Yes | |Yes | ||
|Same as a request. | |Same as a [[API#Requests|request]]. | ||
|- | |- | ||
|id | |id | ||
|string | |string | ||
|Yes | |Yes | ||
|Same as a request. The same ID sent by the original request | |Same as a [[API#Requests|request]]. The same ID sent by the original request. | ||
|- | |- | ||
|result | |result | ||
|any | |any | ||
|No* | |No* | ||
|Return value of the method. May be null depending on the method. See methods for possible values. | |Return value of the method. May be <code>null</code> depending on the method, will be missing if there was an error. See [[API#Methods|methods]] for possible values. | ||
|- | |- | ||
|error | |error | ||
|Error | |Error | ||
|No* | |No* | ||
|If a method failed, this key will be populated with the error details and the result key will be empty. See below for details about errors. | |If a method failed, this key will be populated with the error details and the result key will be empty. See [[API#Response Errors|below]] for details about errors. | ||
|} | |} | ||
Line 131: | Line 123: | ||
If a method fails, it will populate the error key in the response object with details about the failure. An example of a failed request:<syntaxhighlight lang="json"> | If a method fails, it will populate the error key in the response object with details about the failure. An example of a failed request:<syntaxhighlight lang="json"> | ||
{ | { | ||
" | "jsonrpc": "2.0", | ||
"id": " | "id": "4b5da056-a5d4-436b-b4e6-b96231e99969", | ||
"error": { | "error": { | ||
"code": 1, | "code": 1, | ||
Line 139: | Line 130: | ||
} | } | ||
} | } | ||
</syntaxhighlight>Error | </syntaxhighlight> | ||
===== Error object ===== | |||
{| class="wikitable" | {| class="wikitable" | ||
!Key | !Key | ||
Line 149: | Line 142: | ||
|number | |number | ||
|Yes | |Yes | ||
|An integer specifying the general error category. | |An integer specifying the general error category. '''Error codes are not yet formalised.''' | ||
|- | |- | ||
|message | |message | ||
|string | |string | ||
|Yes | |Yes | ||
|Short human readable message explaining the error cause if possible. | |Short human readable message explaining the error cause, if possible. | ||
|} | |} | ||
==== Protocol Errors ==== | ==== Protocol Errors ==== | ||
If a low-level error occurs before a request context can be established, a protocol error will be sent back. This can happen, for example, if a JSON payload is malformed or a payload could not be decrypted. They're identical to an error response except they will have no ID. | If a low-level error occurs before a request context can be established, a protocol error will be sent back. This can happen, for example, if a JSON payload is malformed or a payload could not be decrypted. They're identical to an error response except they will have no ID. | ||
Protocol errors may be sent | Protocol errors may be sent cleartext if a secure context couldn't be established, but will not contain any sensitive data. | ||
=== Secure Layer === | |||
The API supports a secure layer when communicating via an cleartext WebSocket connection. This layer is required for all cleartext remote WebSocket connections, and payloads will be rejected if not encrypted. | |||
... | |||
If a payload is decrypted successfully, it continues through the standard protocol process until the response which will be encrypted before sending back. | |||
=== Anonymous Access === | |||
Anonymous cleartext access is, generally, allowed when an API connection is made from a loopback address (i.e. from the same device Zaparoo is running). This access depends on the platform and whether the service is running with elevated privileges. Check the page for the specific platform you're using to make sure it's available to you. | |||
This access is also allowed when a connection is made over a WebSocket Secure (wss) connection. | |||
=== Heartbeat === | |||
If sent the bytes <code>ping</code>, the API will immediately respond with the bytes <code>pong</code>. This feature can be used by heartbeat functions in WebSocket libraries. | |||
== Launch Endpoint == | |||
The HTTP server has an additional endpoint which allows restricted access to launch [[ZapScript]] using a GET request. This endpoint is specifically meant to support uses such as QR codes scanned by a phone's camera app or simple launch testing. | |||
The endpoint is: <code>/l/</code> | |||
An example request: <code>GET <nowiki>http://10.0.0.123:7497/l/**launch.system:snes</nowiki></code> | |||
This would act as though a token with the text <code>**launch.system:snes</code> had been scanned. | |||
Requests from the local device are allowed without restriction. Remote requests must be explicitly allowed using the allow_launch config file setting. | |||
== Methods == | |||
Methods are used to execute actions and request data back from the API. See the [[API/Methods|API Methods]] page for detailed definitions and examples of each method. | |||
{| class="wikitable" | |||
|+ | |||
!ID | |||
!Description | |||
|- | |||
|[[API/Methods#launch|launch]] | |||
|Emulate a token scan. | |||
|- | |||
|[[API/Methods#stop|stop]] | |||
|Kill any active launcher, if possible. | |||
|- | |||
|tokens | |||
|List active tokens. | |||
|- | |||
|tokens.history | |||
|Return a list of the latest token launches. | |||
|- | |||
|media | |||
|Return status and statistics about media database. | |||
|- | |||
|media.active | |||
|Return the currently active (now playing) media. | |||
|- | |||
|[[API/Methods#media.search|media.search]] | |||
|Query the media database and return all matching indexed media. | |||
|- | |||
|[[API/Methods#media.index|media.index]] | |||
|Start a new media database index. | |||
|- | |||
|[[API/Methods#systems|systems]] | |||
|List all currently indexed systems. | |||
|- | |||
|[[API/Methods#settings 2|settings]] | |||
|List current configuration settings. | |||
|- | |||
|[[API/Methods#settings.update|settings.update]] | |||
|Update one or more settings in-memory and save changes to disk. | |||
|- | |||
|[[API/Methods#mappings 2|mappings]] | |||
|List all mappings. | |||
|- | |||
|[[API/Methods#mappings.new|mappings.new]] | |||
|Create a new mapping. | |||
|- | |||
|[[API/Methods#mappings.update|mappings.update]] | |||
|Change an existing mapping. | |||
|- | |||
|[[API/Methods#mappings.delete|mappings.delete]] | |||
|Delete an existing mapping. | |||
|- | |||
|[[API/Methods#readers 2|readers]] | |||
|List all currently connected readers. | |||
|- | |||
|[[API/Methods#readers.write|readers.write]] | |||
|Attempt to write given text to the first available write-capable reader, if possible. | |||
|- | |||
|[[API/Methods#clients 2|clients]] | |||
|List all clients (including disconnected) and associated data. | |||
|- | |||
|[[API/Methods#clients.new|clients.new]] | |||
|Create a new client with a newly generated ID and secret. | |||
|- | |||
|[[API/Methods#clients.delete|clients.delete]] | |||
|Delete an existing client. | |||
|- | |||
|[[API/Methods#version|version]] | |||
|Return server's current version and platform. | |||
|} | |||
== Notifications == | |||
Notifications let a server or client know an event has occurred. See the [[API/Notifications|API Notifications]] page for detailed definitions and examples of each notification. | |||
{| class="wikitable" | |||
|+ | |||
!ID | |||
!Description | |||
|- | |||
|launching | |||
|New ZapScript has been added to the launch queue. | |||
|- | |||
|readers.added | |||
|A new reader was connected to the server. | |||
|- | |||
|readers.removed | |||
|A connected reader was disconnected from the server. | |||
|- | |||
|tokens.added | |||
|A new token detected by a reader. | |||
|- | |||
|tokens.removed | |||
|A token was removed. | |||
|- | |||
|media.started | |||
|New media was started on server. | |||
|- | |||
|media.stopped | |||
|Media has stopped on server. | |||
|- | |||
|media.indexing | |||
|The state of the indexing process has changed. | |||
|} |
Latest revision as of 00:11, 30 November 2024
This page refers to the future version 2.0.0 of Zaparoo which is in active development. Please don't use any information on this page until it's been finalised and released. |
The Zaparoo API is available on and published by every device running the core Zaparoo software. This API allows management of all Zaparoo features locally and remotely. The Zaparoo app uses this API for all communication with Zaparoo devices, as do most of the flags when Zaparoo is run via the command line.
This page documents the protocol used to communicate with the API and how to interact with it. It is the source of truth when developing applications that work with Zaparoo.
Communication Protocol
The API uses a standard WebSocket connection to exchange JSON payloads using the JSON-RPC 2.0 protocol.
All remote cleartext WebSocket connections must encrypt every payload using the secure layer detailed below, or else the payload will be rejected. Local unencrypted connections are allowed, depending on the platform and privilege context of the running service.
Communication follows a loose client-server relationship. Clients, by default, are not expected to implement the API beyond what that particular client needs to function.
Connection
Connections to the API can be established with any standard WebSocket client, using the root endpoint (/
) of the HTTP server published by the Zaparoo service. By default, the HTTP server is accessible on port 7497
. This port is configurable by the user.
An example address for connecting to the API: ws://10.0.0.123:7497/
The connection requires no special configuration or authentication to initiate.
JSON Payloads
Server and clients communicate back and forth using JSON payloads, following the JSON-RPC 2.0 protocol.
Because a WebSocket connection is asynchronous, request payloads are tagged with a unique ID. The client must keep track of IDs sent to another client and wait for a matching response object. A client can continue sending requests while waiting for responses to previous requests.
Requests
A request object asks the connected server to run a predefined method, and report back when it's completed with a response object.
An example request:
{
"jsonrpc": "2.0",
"id": "4b5da056-a5d4-436b-b4e6-b96231e99969",
"method": "media.search",
"params": {
"query": "240p"
}
}
This request would query Zaparoo's media database for a filename containing the word "240p" and return a response with the search results.
Request object
Key | Type | Required | Description |
---|---|---|---|
jsonrpc | string | Yes | As per the JSON-RPC 2.0 spec, this key's value must be the string 2.0 for a payload to be accepted.
|
id | string | Yes* | A UUID generated by the requesting client, used to match requests back to responses. A request missing this key is valid but would be treated as a notification and not receive any response. |
method | string | Yes | A string corresponding to a method to be run by the receiving server. |
params | any | No | Arguments supplied for the method. The value of this key depends on the method used and is omitted for some methods. |
All available request methods and their parameters are documented below.
Notifications
Notifications are requests which do not contain an ID. Otherwise, they are identical to a standard request object. Notifications can be sent by either server or client and do not receive a response.
Like standard requests, notifications may or may not have parameters and its value will depend on the method. Types of notifications are documented below.
Responses
Every request sent must have a matching response. An example response to the media.search request shown above:
{
"jsonrpc": "2.0",
"id": "4b5da056-a5d4-436b-b4e6-b96231e99969",
"result": {
"media": [{
"system": {
"id": "Gameboy",
"name": "Gameboy"
},
"name": "240p Test Suite (PD) v0.03 tepples",
"path": "Gameboy/240p Test Suite (PD) v0.03 tepples.gb"
}],
"total": 1
}
}
Response object
Key | Type | Required | Description |
---|---|---|---|
jsonrpc | number | Yes | Same as a request. |
id | string | Yes | Same as a request. The same ID sent by the original request. |
result | any | No* | Return value of the method. May be null depending on the method, will be missing if there was an error. See methods for possible values.
|
error | Error | No* | If a method failed, this key will be populated with the error details and the result key will be empty. See below for details about errors. |
Response Errors
If a method fails, it will populate the error key in the response object with details about the failure. An example of a failed request:
{
"jsonrpc": "2.0",
"id": "4b5da056-a5d4-436b-b4e6-b96231e99969",
"error": {
"code": 1,
"message": "query or system is required"
}
}
Error object
Key | Type | Required | Description |
---|---|---|---|
code | number | Yes | An integer specifying the general error category. Error codes are not yet formalised. |
message | string | Yes | Short human readable message explaining the error cause, if possible. |
Protocol Errors
If a low-level error occurs before a request context can be established, a protocol error will be sent back. This can happen, for example, if a JSON payload is malformed or a payload could not be decrypted. They're identical to an error response except they will have no ID.
Protocol errors may be sent cleartext if a secure context couldn't be established, but will not contain any sensitive data.
Secure Layer
The API supports a secure layer when communicating via an cleartext WebSocket connection. This layer is required for all cleartext remote WebSocket connections, and payloads will be rejected if not encrypted.
...
If a payload is decrypted successfully, it continues through the standard protocol process until the response which will be encrypted before sending back.
Anonymous Access
Anonymous cleartext access is, generally, allowed when an API connection is made from a loopback address (i.e. from the same device Zaparoo is running). This access depends on the platform and whether the service is running with elevated privileges. Check the page for the specific platform you're using to make sure it's available to you.
This access is also allowed when a connection is made over a WebSocket Secure (wss) connection.
Heartbeat
If sent the bytes ping
, the API will immediately respond with the bytes pong
. This feature can be used by heartbeat functions in WebSocket libraries.
Launch Endpoint
The HTTP server has an additional endpoint which allows restricted access to launch ZapScript using a GET request. This endpoint is specifically meant to support uses such as QR codes scanned by a phone's camera app or simple launch testing.
The endpoint is: /l/
An example request: GET http://10.0.0.123:7497/l/**launch.system:snes
This would act as though a token with the text **launch.system:snes
had been scanned.
Requests from the local device are allowed without restriction. Remote requests must be explicitly allowed using the allow_launch config file setting.
Methods
Methods are used to execute actions and request data back from the API. See the API Methods page for detailed definitions and examples of each method.
ID | Description |
---|---|
launch | Emulate a token scan. |
stop | Kill any active launcher, if possible. |
tokens | List active tokens. |
tokens.history | Return a list of the latest token launches. |
media | Return status and statistics about media database. |
media.active | Return the currently active (now playing) media. |
media.search | Query the media database and return all matching indexed media. |
media.index | Start a new media database index. |
systems | List all currently indexed systems. |
settings | List current configuration settings. |
settings.update | Update one or more settings in-memory and save changes to disk. |
mappings | List all mappings. |
mappings.new | Create a new mapping. |
mappings.update | Change an existing mapping. |
mappings.delete | Delete an existing mapping. |
readers | List all currently connected readers. |
readers.write | Attempt to write given text to the first available write-capable reader, if possible. |
clients | List all clients (including disconnected) and associated data. |
clients.new | Create a new client with a newly generated ID and secret. |
clients.delete | Delete an existing client. |
version | Return server's current version and platform. |
Notifications
Notifications let a server or client know an event has occurred. See the API Notifications page for detailed definitions and examples of each notification.
ID | Description |
---|---|
launching | New ZapScript has been added to the launch queue. |
readers.added | A new reader was connected to the server. |
readers.removed | A connected reader was disconnected from the server. |
tokens.added | A new token detected by a reader. |
tokens.removed | A token was removed. |
media.started | New media was started on server. |
media.stopped | Media has stopped on server. |
media.indexing | The state of the indexing process has changed. |