API Docs
Overview.
Fire effects and manual triggers on a running Sub Control from your own backend.
The API is a relay. The Sub Control desktop app keeps a WebSocket open to our server. Your HTTPS call arrives at the server, travels down that socket, and the app's answer comes back as your HTTP response. Nothing you send touches the screen unless the app is open, signed in, and willing.
Base URL for every path in these docs:
https://apidrop.kinkyraven.com/api/v1
All bodies are JSON. Every error uses the same envelope, {"error": "<code>", "message": "<text>"}. Test on the code, never the message.
What you can do
- List the user's effect library and fire a library effect for a number of seconds, or until stopped.
- List the user's manual triggers and fire, stop or clear them. These run through the app's own rules engine, so cooldowns, chances and lifetimes apply exactly as if the user pressed the button.
- Do the same to a friend, but only with the triggers that friend set up, and only where they have allowed the key's owner control.
- Check whether the user's app is online and which of their computers to target.
You cannot pick an arbitrary effect for a friend, fire the Clear effect remotely, or open the forced browser from outside. Those are deliberate. See Errors for the refusal codes.
Before the first call
- The user creates an API key in the app under Settings → Integrations → API and gives it to you. The key is shown once. Store it per user.
- The user's account needs an active supporter subscription from account.kinkyraven.com. Verified creators pass without one.
- The app has to be open with Online connection switched on (Settings → Advanced → Online features).
- To fire anything, an effects session must be running in the app.
The first two are checked by the server. The last two are answered by the app itself, so you find out when you fire. GET /relay/me reports the subscription gate without enforcing it, which makes it the right health check.
Walkthrough
KEY="sc_p9Qw..."
BASE="https://apidrop.kinkyraven.com/api/v1"
# Who am I, is the gate open, what are my budgets?
curl -s "$BASE/relay/me" -H "Authorization: Bearer $KEY"
# 200 {"user": {...}, "patreon": {"active": true}, "rate_limits": {...}}
# Is the app reachable, and on which computer?
curl -s "$BASE/relay/online" -H "Authorization: Bearer $KEY"
# 200 {"online": true, "clients": [{"client_id": "d4e5...", "name": "Gaming PC", "online": true}]}
# Which manual triggers can I fire?
curl -s "$BASE/relay/rules" -H "Authorization: Bearer $KEY"
# 200 {"rules": [{"id": "r_9f2...", "name": "Bubbles"}]}
# Fire one. The Idempotency-Key makes a retry safe.
curl -s -X POST "$BASE/relay/rules/trigger" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: evt_01JXYZ123" \
-d '{"rule_id": "r_9f2..."}'
# 200 {"ok": true, "rule_id": "r_9f2..."}
# Take it back down.
curl -s -X POST "$BASE/relay/rules/stop" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"rule_id": "r_9f2..."}'
# 200 {"ok": true, "rule_id": "r_9f2..."}
Manual triggers are the better door for most integrations. The user decides what "Bubbles" means on their machine and you only decide when. Firing library effects directly gives you more control and more ways to be refused.
Where things are
- Authentication covers keys, the supporter gate and rate limits.
- Endpoints lists every route, plus how targeting and idempotency work.
- Errors is the full code list, grouped by who refused.
---
title: Overview
order: 1
lede: Fire effects and manual triggers on a running Sub Control from your own backend.
description: How the Sub Control API works, what you need before the first call, and a full curl walkthrough.
---
The API is a relay. The Sub Control desktop app keeps a WebSocket open to our server. Your HTTPS call arrives at the server, travels down that socket, and the app's answer comes back as your HTTP response. Nothing you send touches the screen unless the app is open, signed in, and willing.
Base URL for every path in these docs:
```
https://apidrop.kinkyraven.com/api/v1
```
All bodies are JSON. Every error uses the same envelope, `{"error": "<code>", "message": "<text>"}`. Test on the code, never the message.
## What you can do
- List the user's effect library and fire a library effect for a number of seconds, or until stopped.
- List the user's manual triggers and fire, stop or clear them. These run through the app's own rules engine, so cooldowns, chances and lifetimes apply exactly as if the user pressed the button.
- Do the same to a friend, but only with the triggers that friend set up, and only where they have allowed the key's owner control.
- Check whether the user's app is online and which of their computers to target.
You cannot pick an arbitrary effect for a friend, fire the Clear effect remotely, or open the forced browser from outside. Those are deliberate. See [Errors](../errors/index.html) for the refusal codes.
## Before the first call
1. The user creates an API key in the app under Settings → Integrations → API and gives it to you. The key is shown once. Store it per user.
2. The user's account needs an active supporter subscription from account.kinkyraven.com. Verified creators pass without one.
3. The app has to be open with Online connection switched on (Settings → Advanced → Online features).
4. To fire anything, an effects session must be running in the app.
The first two are checked by the server. The last two are answered by the app itself, so you find out when you fire. `GET /relay/me` reports the subscription gate without enforcing it, which makes it the right health check.
## Walkthrough
```bash
KEY="sc_p9Qw..."
BASE="https://apidrop.kinkyraven.com/api/v1"
# Who am I, is the gate open, what are my budgets?
curl -s "$BASE/relay/me" -H "Authorization: Bearer $KEY"
# 200 {"user": {...}, "patreon": {"active": true}, "rate_limits": {...}}
# Is the app reachable, and on which computer?
curl -s "$BASE/relay/online" -H "Authorization: Bearer $KEY"
# 200 {"online": true, "clients": [{"client_id": "d4e5...", "name": "Gaming PC", "online": true}]}
# Which manual triggers can I fire?
curl -s "$BASE/relay/rules" -H "Authorization: Bearer $KEY"
# 200 {"rules": [{"id": "r_9f2...", "name": "Bubbles"}]}
# Fire one. The Idempotency-Key makes a retry safe.
curl -s -X POST "$BASE/relay/rules/trigger" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: evt_01JXYZ123" \
-d '{"rule_id": "r_9f2..."}'
# 200 {"ok": true, "rule_id": "r_9f2..."}
# Take it back down.
curl -s -X POST "$BASE/relay/rules/stop" \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-d '{"rule_id": "r_9f2..."}'
# 200 {"ok": true, "rule_id": "r_9f2..."}
```
Manual triggers are the better door for most integrations. The user decides what "Bubbles" means on their machine and you only decide when. Firing library effects directly gives you more control and more ways to be refused.
## Where things are
- [Authentication](../authentication/index.html) covers keys, the supporter gate and rate limits.
- [Endpoints](../endpoints/index.html) lists every route, plus how targeting and idempotency work.
- [Errors](../errors/index.html) is the full code list, grouped by who refused.