# HTTP API Reference

Vask exposes a Pusher-compatible HTTP API at:

```text
https://api.vask.dev
```

Use your Vask `app_key` in the path and in `auth_key`.

```text
https://api.vask.dev/apps/{app_key}/events
```

If a Pusher-compatible SDK asks for `app_id`, set it to the same `app_key`.

## Authentication

All HTTP API requests are signed with the app secret. See [Authentication and signatures](/docs/authentication) for the full signing rules.

Required query parameters:

```text
auth_key=app_key
auth_timestamp=1715520000
auth_version=1.0
body_md5=md5_hex_for_non_empty_post_body
auth_signature=hmac_sha256_signature
```

## POST event

```text
POST /apps/{app_key}/events
```

Triggers one event on one or more channels.

```json
{
    "name": "message.created",
    "channel": "private-room.42",
    "data": "{\"body\":\"hello\"}"
}
```

Multi-channel trigger:

```json
{
    "name": "deploy.finished",
    "channels": ["public-feed", "private-team.42"],
    "data": "{\"version\":\"2026.05.22\"}"
}
```

Optional fields:

| Field       | Description                                                                       |
| ----------- | --------------------------------------------------------------------------------- |
| `socket_id` | Exclude a single connection from receiving the event.                             |
| `info`      | Comma-separated response attributes such as `subscription_count` or `user_count`. |

Successful response:

```json
{}
```

## POST batch events

```text
POST /apps/{app_key}/batch_events
```

Triggers multiple channel events.

```json
{
    "batch": [
        {
            "name": "message.created",
            "channel": "private-room.1",
            "data": "{\"body\":\"hello\"}"
        },
        {
            "name": "message.created",
            "channel": "private-room.2",
            "data": "{\"body\":\"hello\"}"
        }
    ]
}
```

Successful response:

```json
{}
```

## GET channels

```text
GET /apps/{app_key}/channels
```

Returns occupied channels. Use `filter_by_prefix` to narrow the result.

```text
GET /apps/{app_key}/channels?filter_by_prefix=presence-&info=user_count
```

Successful response:

```json
{
    "channels": {
        "presence-room.1": {
            "user_count": 3
        }
    }
}
```

## GET channel

```text
GET /apps/{app_key}/channels/{channel_name}
```

Returns channel state and requested attributes.

```text
GET /apps/{app_key}/channels/private-room.42?info=subscription_count
```

Successful response:

```json
{
    "occupied": true,
    "subscription_count": 12
}
```

Cache channel response with `info=cache`:

```json
{
    "occupied": true,
    "cache": {
        "event": "location.updated",
        "data": "{\"lat\":51.5,\"lng\":-0.12}",
        "ttl": 60
    }
}
```

## GET presence users

```text
GET /apps/{app_key}/channels/{channel_name}/users
```

This endpoint applies to presence channels only.

```json
{
    "users": [{ "id": "user-123" }, { "id": "user-456" }]
}
```

## POST user event

```text
POST /apps/{app_key}/users/{user_id}/events
```

Sends an event to all active connections that completed `pusher:signin` as that `user_id`.

```json
{
    "name": "notification.created",
    "data": "{\"body\":\"Export ready\"}"
}
```

Successful response:

```json
{}
```

## POST terminate user connections

```text
POST /apps/{app_key}/users/{user_id}/terminate_connections
```

Closes all active connections that completed `pusher:signin` as that `user_id`.

```json
{}
```

Successful response:

```json
{}
```

## Status codes

| Status | Meaning                                                                        |
| ------ | ------------------------------------------------------------------------------ |
| `200`  | Request accepted.                                                              |
| `400`  | Invalid request body, parameters, channel name, or unsupported info attribute. |
| `401`  | Authentication failed.                                                         |
| `403`  | App disabled or quota restriction.                                             |
| `404`  | App, channel, or route not found.                                              |
| `413`  | Payload too large.                                                             |
| `429`  | Quota limit exceeded.                                                          |

## Related docs

- [Events](/docs/events)
- [User connections](/docs/user-connections)
- [Authentication and signatures](/docs/authentication)
