API Docs
Errors.
One envelope, stable codes, and three places a call can be refused.
Every error is JSON with the same shape:
{"error": "rate_limited", "message": "API rate limit exceeded", "retryAfter": 47}
erroris the stable machine-readable code. Test on this.messageis for humans and may change.retryAfterappears only on429, in seconds until the window resets. The same value is sent as aRetry-Afterheader.- Some codes add context.
ambiguous_clientincludes aclientsarray.
A call can fail at three points. Knowing which one tells you what to do about it.
Refused by the server
Nothing reached the user's app.
401 unauthorized. Missing, wrong or revoked key. Stop retrying and ask the user for a new one.403 patreon_required. The key's account has no active supporter subscription. The user fixes this at account.kinkyraven.com.429 rate_limited. WaitretryAfterseconds. Idempotent retries after a429re-execute, since nothing happened.400 bad_request. A required field is missing, usuallyeffect_idorrule_id.400 bad_rule. Therule_idis over 128 characters or contains control characters.
Refused by the relay
The server tried to reach a device and could not.
404 client_not_found. Theclient_idyou passed is not on this account.409 ambiguous_client. Several of the user's computers are online and you passed noclient_id. The body lists them.503 device_offline. The target is offline, or nothing is online.504 client_timeout. The app did not answer within 10 seconds.
Any of these can come back from a relayed endpoint. See Targeting.
Refused by the app
The call reached the user's computer and the app said no. These come back with the app's own status.
403 remote_disabled. Online connection is switched off in the app.409 session_off. No effects session is running. The user has to start one.404 effect_not_found. Unknowneffect_id.404 rule_not_found. Unknownrule_id, or a trigger that is disabled or gated. The two cases are deliberately indistinguishable.403 premium_required. The effect needs a supporter membership on the target account and it has lapsed.403 high_risk_disabled. The user has "Disable High Risk Effects" on and this effect is strobe-class.403 not_remotely_fireable. The Clear effect and the forced browser can only be fired on the computer they run on.403 unlock_unavailable. A type-to-unlock cover, on a platform whose overlay cannot take typing.403or400 app_outdated. The user's app predates this endpoint. They need to update.
Friend paths only
404 not_friends. Not on the key owner's friends list.403 friend_control_disabled. The friend has not allowed the key's owner control. Listing their triggers fails with this.403 friend_trigger_disabled. Same switch, reported when firing.403 target_patreon_required. The friend needs an active supporter subscription to receive effects.502 rules_unavailable. The friend's app refused to list, or predates the feature.
What to retry
Retry 429, 503 and 504 with backoff. Retry POST triggers with the same Idempotency-Key so a lost response never fires twice. Do not retry 401, 403 or 404 until something has changed on the user's side. Stops and clears are always safe to send again.
---
title: Errors
order: 4
lede: One envelope, stable codes, and three places a call can be refused.
description: Every Sub Control API error code, grouped by whether the server, the relay or the user's app refused the call.
---
Every error is JSON with the same shape:
```json
{"error": "rate_limited", "message": "API rate limit exceeded", "retryAfter": 47}
```
- `error` is the stable machine-readable code. Test on this.
- `message` is for humans and may change.
- `retryAfter` appears only on `429`, in seconds until the window resets. The same value is sent as a `Retry-After` header.
- Some codes add context. `ambiguous_client` includes a `clients` array.
A call can fail at three points. Knowing which one tells you what to do about it.
## Refused by the server
Nothing reached the user's app.
- `401 unauthorized`. Missing, wrong or revoked key. Stop retrying and ask the user for a new one.
- `403 patreon_required`. The key's account has no active supporter subscription. The user fixes this at account.kinkyraven.com.
- `429 rate_limited`. Wait `retryAfter` seconds. Idempotent retries after a `429` re-execute, since nothing happened.
- `400 bad_request`. A required field is missing, usually `effect_id` or `rule_id`.
- `400 bad_rule`. The `rule_id` is over 128 characters or contains control characters.
## Refused by the relay
The server tried to reach a device and could not.
- `404 client_not_found`. The `client_id` you passed is not on this account.
- `409 ambiguous_client`. Several of the user's computers are online and you passed no `client_id`. The body lists them.
- `503 device_offline`. The target is offline, or nothing is online.
- `504 client_timeout`. The app did not answer within 10 seconds.
Any of these can come back from a relayed endpoint. See [Targeting](../endpoints/index.html#targeting).
## Refused by the app
The call reached the user's computer and the app said no. These come back with the app's own status.
- `403 remote_disabled`. Online connection is switched off in the app.
- `409 session_off`. No effects session is running. The user has to start one.
- `404 effect_not_found`. Unknown `effect_id`.
- `404 rule_not_found`. Unknown `rule_id`, or a trigger that is disabled or gated. The two cases are deliberately indistinguishable.
- `403 premium_required`. The effect needs a supporter membership on the target account and it has lapsed.
- `403 high_risk_disabled`. The user has "Disable High Risk Effects" on and this effect is strobe-class.
- `403 not_remotely_fireable`. The Clear effect and the forced browser can only be fired on the computer they run on.
- `403 unlock_unavailable`. A type-to-unlock cover, on a platform whose overlay cannot take typing.
- `403` or `400 app_outdated`. The user's app predates this endpoint. They need to update.
## Friend paths only
- `404 not_friends`. Not on the key owner's friends list.
- `403 friend_control_disabled`. The friend has not allowed the key's owner control. Listing their triggers fails with this.
- `403 friend_trigger_disabled`. Same switch, reported when firing.
- `403 target_patreon_required`. The friend needs an active supporter subscription to receive effects.
- `502 rules_unavailable`. The friend's app refused to list, or predates the feature.
## What to retry
Retry `429`, `503` and `504` with backoff. Retry `POST` triggers with the same `Idempotency-Key` so a lost response never fires twice. Do not retry `401`, `403` or `404` until something has changed on the user's side. Stops and clears are always safe to send again.