# APIs

## HTTP API

Actions and procedures can also be called using the JSON-RPC API exposed by
Platypush.

Your configuration requires the [`backend.http`
section](https://docs.platypush.tech/platypush/backend/http.html) enabled if
you want to use the HTTP API - default listen port: `8008`.

After ensuring that the HTTP backend is enabled, head to
`http://localhost:8008` and register a new user.

![Platypush local user registration
page](https://platypush-static.s3.nl-ams.scw.cloud/screenshots/registration-page-screenshot.png)

From the Web UI, head to _Settings_ → _Tokens_, insert your password again and
click _Generate JWT token_.

![User token generation UI](https://platypush-static.s3.nl-ams.scw.cloud/screenshots/tokens-ui-screenshot.png)

Alternatively, you can retrieve a token via HTTP request:

```shell
❯ curl -XPOST -H 'Content-Type: application/json' -d '
{
  "username": "$YOUR_USER",
  "password": "$YOUR_PASSWORD"
}' http://localhost:8008/auth
```

You can then send requests to Platypush using a simple RPC API:

```bash
❯ curl -XPOST \
    -d '{"type":"request", "action":"procedure.at_home"}' \
    -H "Authorization: Bearer $YOUR_TOKEN" \
    -H "Content-Type: application/json" \
    http://localhost:8008/execute
❮
{
  "id": "724754df98968247a284557ce32f74bb",
  "type": "response",
  "target": "http",
  "origin": "myhost",
  "_timestamp": 1716575901.046127,
  "response": {
    "output": {
      "success": true
    },
    "errors": []
  }
}
```

If your procedure returned something, then that will be returned on the API
response too, so downstream consumers can use it.

The `POST /execute` endpoint accepts a payload in the format:

```javascript
{
  "type": "request",  // Constant
  "action": "<plugin-name>.<action-name>",  // Or procedure.<name>
  "args": {
    "arg1": "arg2",
    // ...
  }
}
```

In our `procedure.at_home` example, you can for instance create an automation
snippet paired with your phone that runs the routine whenever you arrive home
(or your phone does):

1. Install an app like [Tasker](https://tasker.joaoapps.com/) to create
   automation tasks on your Android device.

2. Install a plugin like [AutoLocation](https://joaoapps.com/autolocation/) to
   create automation tasks based on your phone's location.

3. Create a profile that triggers whenever you enter your home location (and/or
   exit it).

![Tasker screenshot showing an At Home/Outside Home pair of
profiles](https://platypush-static.s3.nl-ams.scw.cloud/screenshots/tasker-screenshot-1.png)

4. Leverage the [HTTP
   Request](https://tasker.joaoapps.com/userguide/en/help/ah_http_request.html)
   Tasker action to send a request to your Platypush API to trigger the routine.

### The _Execute_ tab

The Web interface also provides an _Execute_ tab under the menu sidebar. You
can use this tab to dynamically discover the actions exposed by various plugins
(and also your own procedures):

![Screenshot of the Execute tab showing the autocomplete discovery of the
actions](https://platypush-static.s3.nl-ams.scw.cloud/screenshots/execute-panel-screenshot-1.jpg)

![Screenshot of the Execute tab showing the automatically generated
documentation for a given action and its
parameters](https://platypush-static.s3.nl-ams.scw.cloud/screenshots/execute-panel-screenshot-2.jpg)

![Screenshot of the Execute tab showing the output of an action being
run](https://platypush-static.s3.nl-ams.scw.cloud/screenshots/execute-panel-screenshot-3.jpg)

## Websocket API

### Events

You can subscribe to events generated by the application over the `/ws/events`
Websocket endpoint, and send events to this endpoint too.

This is useful if you want to synchronize Platypush events with another client,
or send custom events outside of those native to the application and build
custom automation hooks on them.

Sending events:

```bash
❯ wscat -H "Authorization: Bearer $YOUR_TOKEN" \
    -c "ws://localhost:8008/ws/events" \
    -w 1 \
    -x '
{
  "type": "event",
  "args": {
    "type": "platypush.message.event.custom.CustomEvent",
    "subtype": "foo",
    "args": {
      "bar": "baz"
    }
  }
}'
```

Receiving events:

```bash
❯ wscat -H "Authorization: Bearer $YOUR_TOKEN" -c "ws://localhost:8008/ws/events"
```

### Actions

You can also send requests to the `/ws/requests` Websocket endpoint, and get
responses asynchronously on the same channel:

```bash
❯ wscat -H "Authorization: Bearer $YOUR_TOKEN" \
    -c "ws://localhost:8008/ws/requests" \
    -w 1 \
    -x '{"type": "requests", "action": "procedure.foo.bar"}'
```

## Web hooks

You can use Platypush to expose your custom routines as dynamic Web hooks that
can be called by any client.

All you need is to register a listener for a
[`WebhookEvent`](https://docs.platypush.tech/platypush/events/http.hook.html#platypush.message.event.http.hook.WebhookEvent)

```python
from platypush import run, when
from platypush.events.http.hook import WebhookEvent

hook_token = "abcdefabcdef"

# Expose the hook under the /hook/at_home endpoint
@when(WebhookEvent, hook="at_home")
def at_home_webhook(event: WebhookEvent):
    # Unlike the calls to /execute, custom web hooks are unauthenticated.
    # If you want authentication, you'll need to implement your custom logic by
    # parsing the event headers
    if event.headers.get("X-Token") != hook_token:
        # Tuple with <response, http-code, [response-headers]>
        event.send_response(("Unauthorized", 401))
        return

    run('procedure.at_home')

    # Return anything back to the client
    return {'status': 'ok'}
```

Then you can invoke your custom logic over HTTP:

```bash
❯ curl -H 'X-Token: abcdefabcdef' 'http://localhost:8008/hook/at_home'
```

## Platypush as a library

You can also use Platypush as a library in your own scripts.

For example, you may want to run a bunch of scripts that control your lights
outside of Platypush, but use a Platypush configuration file as your script
configuration, and use a plugin as the API for your controller:

```python
from platypush import run
from platypush.config import Config

# Optional. Defaults to the default config.yaml if missing
Config.init('/path/to/my/config.yaml')

# ...

run('light.hue.toggle', groups=['Living Room', 'Hall'])

# ...
```
