API en integraties
Elke ruimte heeft een HTTP-API. Start en stop timers, toon berichten, voeg tijd toe en lees de rundown uit vanuit een script, een showcontrolsysteem of alles wat een webverzoek kan doen. Een webhook laat je systeem weten wanneer een timer start of afloopt.


Aan de slag
Een API-sleutel aanmaken
Open API-sleutels en klik op Sleutel aanmaken. Kopieer hem meteen: hij wordt maar één keer getoond. Zie Team en API-sleutels.
De ruimte-id vinden
Dat is het deel na /timer/r/ in het adres van de regieruimte, bijvoorbeeld https://cliqer.io/timer/r/<room>/control.
Een aanroep doen
Stuur de sleutel mee met elk verzoek. ping controleert of de ruimte bestaat.
De API bedient dezelfde ruimte als de regieruimte: een aanroep vanuit je tool verschijnt tegelijk op elk scherm.
Verzoeken
Elke aanroep gaat naar https://cliqer.io/api/timer/v1/<room>/<action>. GET, POST, PUT en PATCH werken allemaal. Parameters gaan in de querystring, of in een JSON-body bij POST, PUT en PATCH; de body wint als beide er een hebben. Streepjes in de actienaam werken ook, dus add-time is add_time. /api/timer/v0/ accepteert dezelfde aanroepen.
Stuur de sleutel mee op een van deze manieren, gecontroleerd in deze volgorde:
| Waar | Voorbeeld |
|---|---|
Authorization-header | Authorization: Bearer <key> |
x-api-key-header | x-api-key: <key> |
api_key-query | ?api_key=<key>. Vermijd dit waar je kunt: adressen belanden in logs. |
curl -X POST https://cliqer.io/api/timer/v1/<room>/add_time \
-H "Authorization: Bearer $CLIQER_KEY" \
-H "content-type: application/json" \
-d '{"timer_id": "<timer>", "amount": "2m"}'
const res = await fetch('https://cliqer.io/api/timer/v1/<room>/add_time', {
method: 'POST',
headers: { 'authorization': `Bearer ${process.env.CLIQER_KEY}`, 'content-type': 'application/json' },
body: JSON.stringify({ timer_id: '<timer>', amount: '2m' }),
})
const { ok, message, data } = await res.json()
import os, requests
r = requests.post(
"https://cliqer.io/api/timer/v1/<room>/add_time",
headers={"Authorization": f"Bearer {os.environ['CLIQER_KEY']}"},
json={"timer_id": "<timer>", "amount": "2m"},
)
print(r.json())
Sleutels en rechten
De API-sleutel van je account kan alles in ruimtes die van jou zijn. Een ruimte kan ook eigen sleutels hebben, elk met een of meer van drie rechten:
| Recht | Staat toe |
|---|---|
| Lezen | De get_-acties en export. |
| Show aansturen | Transport, tijd, blackout, on air en berichten. |
| Bewerken | Verwijderen, importeren, ruwe intents en de webhook. |
Een aanroep die een recht nodig heeft dat de sleutel mist, krijgt 401. Het geheim van een ruimtesleutel wordt één keer getoond, bij het aanmaken. Om de API überhaupt te gebruiken moet de API in je abonnement zitten, zie Abonnementen en limieten.
Acties
timer_id kiest een timer op zijn id; index kiest hem op positie, geteld vanaf 1. Als beide worden meegestuurd, wint timer_id. Laat beide weg om de huidige timer aan te sturen.
| Actie | Geeft terug |
|---|---|
get_room | Titel, datum, tijdzone en instellingen. |
get_status | Wat er nu loopt. |
get_timers | De rundown. |
get_messages | De berichten. |
get_questions | Vragen uit het publiek. |
get_connections | Verbonden apparaten. |
get_logs | Het logboek van de ruimte. limit, offset. |
export | De hele ruimte als download cliqer-timer-<room>.json. |
| Actie | Parameters | Doet |
|---|---|---|
start, start_or_stop | timer_id of index | Start, of schakelt om. |
stop | Stopt de lopende timer. | |
start_fresh | timer_id of index | Start vanaf de volledige lengte. |
select | timer_id of index (één is verplicht) | Maakt hem de huidige timer zonder te starten. |
reset | timer_id of index, autostart, from_memory | Terug naar de volledige lengte. |
next, previous | autostart, from_memory | Gaat door de rundown. |
add_time, subtract_time | timer_id, amount | Wijzigt de lengte van een timer. |
jump | amount | Laat de lopende timer zoveel verspringen. |
set_remaining | amount | Stelt de resterende tijd in. |
flash | count, message | Laat de schermen knipperen. |
stop_flash | Stopt het knipperen. | |
blackout | on | Blackout aan of uit. |
blackout_on, blackout_off, toggle_blackout | Hetzelfde, zonder parameter. | |
focus | on | Zet het bericht in focus. |
on_air | on | De On air-indicator. |
show_message | message_id, focus | Toont een bericht. |
toggle_message | message_id | Toont het, of verbergt het als het al zichtbaar is. |
hide_message | Verbergt het bericht. |
| Actie | Parameters | Doet |
|---|---|---|
delete_timer | timer_id | Verwijdert een timer. |
delete_message | message_id | Verwijdert een bericht. |
delete_question | question_id | Verwijdert een vraag. |
import_csv | csv, replace, date_line, columns, header_row, rows | Importeert rijen, zoals in Importeren uit Stagetimer. |
intent | {"intent": {...}} | Elke wijziging die de regieruimte kan maken, als JSON. |
webhook | url | Stelt de webhook in of wist hem. Zie hieronder. |
| Actie | Parameters | Doet |
|---|---|---|
ping | Antwoordt pong als de ruimte bestaat. | |
submit_question | text (maximaal 1000 tekens), name (maximaal 100) | Stuurt een vraag uit het publiek in. |
vote_question | question_id | Stemt op een vraag. |
Hoeveelheden zijn 30s, 5m, 1h, 250ms of een kaal aantal seconden. seconds werkt in plaats van amount, en met een minteken ga je terug. Schakelaars zoals on, autostart en replace lezen 0, false, off en no als uit en al het andere als aan. Laat on weg bij blackout om hem om te schakelen.
Antwoorden
Elk antwoord is JSON: {"ok": true, "message": "<action>", "data": ...} bij succes, {"ok": false, "message": "...", "code": "..."} bij een fout.
| Status | Bericht | Waarom |
|---|---|---|
| 400 | Either timer_id OR index are required | select zonder timer. |
| 400 | amount is required, like 30s, 5m or 1h | Ontbrekende of onleesbare hoeveelheid. |
| 400 | Refused: invalid | De ruimte kon het niet toepassen. |
| 401 | Access Denied: Valid API key required | Geen sleutel, een verkeerde sleutel of een ontbrekend recht. |
| 403 | The API is not in this plan | Het abonnement van de ruimte bevat geen API. |
| 403 | Refused: forbidden, Refused: readOnly, Refused: limitReached | Niet toegestaan, een alleen-lezen ruimte of een abonnementslimiet. |
| 404 | Room not found, Unknown action <name>, Timer not found | Controleer de ruimte-id, de actie of de timer-id. |
| 409 | Refused: staleEpoch | De ruimte is tijdens de aanroep veranderd. Stuur hem opnieuw. |
| 429 | Too many requests. Please try again later. | Snelheidslimiet. |
| 503 | Refused: authorityOffline | De ruimte staat in de prullenbak. Zet hem eerst terug. |
Snelheidslimiet: 100 aanroepen per minuut per sleutel; aanroepen zonder sleutel tellen per adres. Elk antwoord bevat RateLimit-Limit, RateLimit-Remaining en RateLimit-Reset (het aantal seconden tot de minuut opnieuw begint).
Webhooks
Het adres instellen
Roep webhook aan met een https-url. Het antwoord bevat een secret dat begint met whsec_. Bewaar het: het wordt maar één keer getoond.
Events ontvangen
Cliqer Timer stuurt een POST naar dat adres wanneer er iets in de ruimte gebeurt.
De handtekening controleren
Verifieer elk verzoek voordat je het vertrouwt.
Het adres wissen
Roep webhook aan zonder url. Het adres en het bijbehorende geheim worden allebei verwijderd.
| Event | Wanneer |
|---|---|
timerStarted | Een timer start. |
timerEnded | Een timer bereikt nul. |
wrapUpYellow | Een timer bereikt zijn gele afrondingspunt. |
wrapUpRed | Een timer bereikt zijn rode afrondingspunt. |
messageShown | Er wordt een bericht getoond. |
De body is {"event", "roomId", "timestamp", "payload"}. De header x-cliqer-timestamp bevat de Unix-tijd in seconden, en x-cliqer-signature bevat sha256= gevolgd door de hexadecimale HMAC-SHA256 van <timestamp>.<body>, met je geheim als sleutel.
# Recompute the signature of a saved body.
printf '%s.%s' "$TIMESTAMP" "$(cat body.json)" \
| openssl dgst -sha256 -hmac "$WHSEC" -hex
import { createHmac, timingSafeEqual } from 'node:crypto'
export function verify(rawBody: string, timestamp: string, signature: string, secret: string) {
const want = `sha256=${createHmac('sha256', secret).update(`${timestamp}.${rawBody}`).digest('hex')}`
const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300
return fresh && want.length === signature.length && timingSafeEqual(Buffer.from(want), Buffer.from(signature))
}
import hashlib, hmac, time
def verify(raw_body: bytes, timestamp: str, signature: str, secret: str) -> bool:
mac = hmac.new(secret.encode(), timestamp.encode() + b"." + raw_body, hashlib.sha256)
fresh = abs(time.time() - int(timestamp)) < 300
return fresh and hmac.compare_digest("sha256=" + mac.hexdigest(), signature)
Bereken de handtekening over de ruwe body, precies zoals die binnenkwam en vóór enige JSON-parsing. Het venster van vijf minuten is je eigen keuze; het voorkomt dat een oud verzoek opnieuw wordt afgespeeld.
Bezorging gebeurt in één poging met een time-out van 5 seconden. Omleidingen worden niet gevolgd, en een adres dat naar een privénetwerk verwijst, wordt overgeslagen. Is een gemist event belangrijk, lees dan get_status uit om weer bij te zijn.
Korte links
GET https://cliqer.io/api/timer/link/<code> zet een korte-linkcode om in de bijbehorende ruimte: {"ok": true, "data": {"roomId", "link"}}, of 404 Link not found bij een onbekende, ingetrokken of verlopen code of een verkeerd wachtwoord. Stuur bij een link met wachtwoord het wachtwoord mee in de header x-link-password, nooit in het adres.
Companion en Stream Deck
Er is geen Companion-module of Stream Deck-plug-in voor Cliqer Timer-ruimtes. De Generic HTTP-module van Bitfocus Companion kan de acties hierboven aanroepen. De eigen timer van de Cliqer-desktopapp heeft een eigen REST API en ondersteuning voor Stream Deck, zie Timer (desktop) en Host-timer.
Veelgestelde vragen
De sleutel ontbreekt, is verkeerd getypt of is niet van jou: een accountsleutel werkt alleen in ruimtes die van jou zijn. Controleer of de header Authorization: Bearer <key> is, zonder extra spaties.
Het abonnement van de eigenaar van de ruimte bevat geen Timer API. Zie Abonnementen en limieten.
Nee. De API heeft een sleutel nodig voor een ruimte die van jou is, en de demoruimte is van niemand.
Controleer of het adres https is, bereikbaar is vanaf het internet en binnen 5 seconden antwoordt zonder omleiding. Ben je het geheim kwijt, stel het adres dan opnieuw in; het oude geheim werkt daarna niet meer.