Zum Inhalt
RAWCaptureBooth Anwenderhandbuch
Version 3.29.0

Status-Webhook

Die Fotobox meldet ihren Zustand im Takt an eine Adresse, die der Betreiber einträgt. Jede Meldung ist ein JSON mit denselben Werten, die das Portal der Fernverwaltung zu dieser Fotobox zeigt. Was der Empfänger damit anfängt, bestimmt er selbst.

Eingeschaltet wird das im Admin-Bereich "Licht-/Zubehör-Steuerung" > "Status-Webhook". Die Fernverwaltung wird dafür nicht gebraucht: Der Webhook läuft auch an einer Fotobox ohne Portal.

Wofür das gut ist#

  • Auf der eigenen Website zeigen, ob die Fotobox gerade im Einsatz ist und wie viele Fotos schon entstanden sind.
  • Eine eigene Übersicht über mehrere Fotoboxen führen, in einem vorhandenen System.
  • Benachrichtigen lassen, wenn das Papier knapp wird, der Kamera-Akku nachlässt oder eine Fotobox nicht mehr meldet - über eine Hausautomatisierung oder einen Chat.
  • Zähler mitschreiben, etwa für die Abrechnung mit dem Kunden.

Status-Webhook oder Auslöser?#

Beide melden nach außen, aber verschieden:

Status-WebhookAuslöser für Fremdprogramme
Wannim festen Takt, ab Werk alle 30 Sekundenin dem Moment, in dem ein Schritt passiert
Wasder gesamte Zustand der Fotoboxein einzelnes Ereignis mit wenigen Werten
Wohineine Adresse im Internet oder im Netzwerkeine Adresse oder ein Programm auf der Fotobox
TypischAnzeige, Überwachung, StatistikLicht, Steckdosen, Skripte im Ablauf

Beides lässt sich gleichzeitig nutzen. Die Auslöser beschreibt das Kapitel Auslöser für Fremdprogramme.

Einrichten#

  1. Einen Empfänger bereitstellen: eine Adresse, die eine POST-Anfrage mit JSON annimmt und mit einem Status von 200 bis 299 antwortet. Die Beispiele weiter unten reichen dafür.
  2. Im Bereich "Status-Webhook" die Adresse eintragen und speichern. Dabei entsteht der Schlüssel für die Signatur.
  3. Den Schlüssel mit "Kopieren" übernehmen und beim Empfänger eintragen.
  4. "Testmeldung senden" drücken. Darunter erscheinen die Antwort des Empfängers und der gesendete Inhalt.
  5. "Status-Webhook verwenden" einschalten. Die erste Meldung geht sofort raus, danach im eingestellten Abstand.

Was ankommt#

Jede Meldung ist eine POST-Anfrage mit diesen Kopfzeilen:

KopfzeileInhalt
Content-Typeapplication/json; charset=utf-8
User-AgentRAWCaptureBooth-Statuswebhook/<Version>
X-RAWCaptureBooth-TimestampZeitpunkt der Meldung in Sekunden seit 1970 (Unix-Zeit)
X-RAWCaptureBooth-Signaturesha256= und die Signatur, siehe unten

Der Inhalt sieht so aus (gekürzt auf je einen Drucker und Buzzer):

{
  "schema_version": 1,
  "sent_at": "2026-10-03T21:14:05+02:00",
  "report_interval_seconds": 30,
  "computer_name": "FOTOBOX-01",
  "rawcapturebooth_version": "3.28.0",
  "rawcapturebooth_latest_version": "3.28.0",
  "cockpit_version": null,
  "cockpit_latest_version": null,
  "uptime": "5:12:03",
  "network_status": "WLAN (Festsaal)",
  "connectivity_mode": "online",
  "email_enabled": true,
  "print_enabled": true,
  "cloud_enabled": false,
  "event_name": "Hochzeit Müller",
  "sessions_total": 1843,
  "sessions_since_start": 112,
  "session_limit": 0,
  "total_print_jobs": 2210,
  "print_jobs_since_start": 131,
  "print_limit": 300,
  "ai_portraits_total": 0,
  "ai_portraits_since_start": 0,
  "ai_portrait_limit": 0,
  "ai_portrait_warn_threshold": 0,
  "last_session_at": "2026-10-03T19:13:40Z",
  "last_capture_at": "2026-10-03T19:13:40Z",
  "error_count": 0,
  "last_error": null,
  "last_error_at": null,
  "cpu_used_percent": 23.5,
  "memory_used_percent": 61.2,
  "disk_free_gb": 182.4,
  "disk_total_gb": 476.3,
  "outbox_pending": 0,
  "outbox_email_pending": 0,
  "outbox_cloud_pending": 0,
  "camera_battery_percent": null,
  "camera_power_source": "ac",
  "printers": [
    {
      "role": "print",
      "mode": "single",
      "name": "DP-DS620",
      "available": true,
      "state": "ready",
      "queue_length": 0,
      "issues": [],
      "media_remaining": 268,
      "media_capacity": 400,
      "total_prints": 15320
    }
  ],
  "buzzers": [
    {
      "name": "Buzzer 1",
      "connection": "connected",
      "battery_level": 3,
      "millivolt": 4010,
      "seconds_since_press": 25
    }
  ]
}

Den echten Inhalt der eigenen Fotobox zeigt "Testmeldung senden" unter "Gesendeter Inhalt".

Die Felder#

Ein Feld ohne Wert steht als null da. Neue Felder können in späteren Versionen dazukommen; ein Empfänger übergeht, was er nicht kennt. schema_version steigt nur, wenn sich die Bedeutung eines Feldes ändert oder eines wegfällt.

FeldInhalt
schema_versionAufbau der Meldung, derzeit 1
sent_atSendezeitpunkt in der Ortszeit der Fotobox, mit Zeitzone
report_interval_secondsMelde-Abstand in Sekunden
computer_nameRechnername der Fotobox - die Kennung, wenn mehrere Boxen an denselben Empfänger melden
rawcapturebooth_versionInstallierte Version
rawcapturebooth_latest_versionNeueste veröffentlichte Version, leer, solange die Fotobox sie nicht abrufen konnte
cockpit_version, cockpit_latest_versionDasselbe für RAWCaptureBooth Cockpit, leer ohne Cockpit
uptimeLaufzeit seit dem Programmstart, etwa 5:12:03 oder 1 day, 2:03:04
network_statusTatsächliche Netzlage: LAN, WLAN (Netzname), Online oder Offline
connectivity_modeEingestellte Betriebsart: online oder offline
email_enabled, print_enabled, cloud_enabledOb Mail-Versand, Druck und Cloud-Upload eingeschaltet sind
event_nameName des aktiven Events
sessions_total, sessions_since_startSessions insgesamt und seit dem Programmstart
session_limitObergrenze der Sessions, 0 heißt kein Limit
total_print_jobs, print_jobs_since_start, print_limitDasselbe für Druckaufträge
ai_portraits_total, ai_portraits_since_start, ai_portrait_limitDasselbe für KI-Porträts
ai_portrait_warn_thresholdAb dieser Zahl von KI-Porträts warnt die Fotobox, 0 heißt aus
last_session_at, last_capture_atZeitpunkt der letzten Session und der letzten Aufnahme, meist in UTC (endet auf Z)
error_countFehler seit dem Programmstart
last_error, last_error_atDer letzte Fehler als Text, mit Zeitpunkt
cpu_used_percentProzessor-Auslastung seit der letzten Meldung, leer bei der ersten Meldung nach dem Start
memory_used_percentBelegter Arbeitsspeicher
disk_free_gb, disk_total_gbFreier und gesamter Speicher des Laufwerks mit den Aufnahmen
outbox_pendingWartende Mails und Uploads, zum Beispiel ohne Netz
outbox_email_pending, outbox_cloud_pendingDavon Mails und Cloud-Uploads
camera_battery_percentKamera-Akku in Prozent, leer am Netzteil oder wenn die Kamera ihn nicht meldet
camera_power_sourcebattery, ac (Netzteil) oder leer
printersJe Drucker ein Eintrag, siehe unten
buzzersJe Funk-Buzzer ein Eintrag, siehe unten

Ein Eintrag in printers:

FeldInhalt
roleprint (Foto-Drucker) oder strip (Fotostreifen-Drucker)
modesingle (ein Drucker) oder pool (Drucker-Pool, dann zusätzlich strategy)
nameName des Druckers in Windows
availableOb der Drucker bereit ist
stateZustand, etwa ready, printing, paused, error, offline oder unknown
queue_lengthAufträge in der Warteschlange
issuesListe der gemeldeten Probleme, leer ohne Befund
media_remaining, media_capacityRestmaterial und Fassungsvermögen in Blatt, leer ohne Angabe des Druckers
total_printsDrucke über die Lebensdauer, nur bei DNP-Druckern

Ein Eintrag in buzzers:

FeldInhalt
nameName des Funk-Buzzers
connectionconnected, sleeping, disconnected, never (nie verbunden) oder unavailable (Bluetooth nicht verfügbar)
battery_levelBatterie in drei Stufen: 3 voll, 2 halb, 1 schwach, 0 unbekannt
millivoltBatteriespannung in Millivolt
seconds_since_pressSekunden seit dem letzten Drücken, leer, wenn noch nicht gedrückt

Die Signatur prüfen#

Jede Meldung ist mit dem Schlüssel aus dem Admin-Bereich signiert. Der Empfänger rechnet die Signatur selbst nach und nimmt die Meldung nur an, wenn beide übereinstimmen:

  1. Den Inhalt so, wie er ankommt, als Bytes lesen - nicht erst als JSON einlesen und wieder ausgeben.
  2. Zeitstempel aus X-RAWCaptureBooth-Timestamp, einen Punkt und den Inhalt aneinanderhängen.
  3. Darüber HMAC-SHA256 mit dem Schlüssel bilden, als Hex-Zeichenkette, und sha256= voranstellen.
  4. Mit X-RAWCaptureBooth-Signature vergleichen, in konstanter Zeit.
  5. Meldungen ablehnen, deren Zeitstempel mehr als fünf Minuten von der eigenen Uhrzeit abweicht. So lässt sich eine mitgeschnittene Meldung nicht später wieder einspielen.

"Neu erzeugen" im Admin-Bereich ersetzt den Schlüssel. Bis er beim Empfänger nachgetragen ist, lehnt dieser jede Meldung ab.

Beispiel: Anzeige auf der eigenen Website#

Eine Website kann eine Meldung nicht selbst annehmen - sie braucht ein kleines Skript auf dem Server. Dieses PHP-Skript prüft die Signatur und legt nur die Werte, die öffentlich sein sollen, in einer Datei fotobox-status.json ab:

<?php
// fotobox-webhook.php - als Adresse im Admin-Bereich eintragen
$secret = 'HIER-DEN-SCHLUESSEL-EINTRAGEN';

$body = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_RAWCAPTUREBOOTH_TIMESTAMP'] ?? '';
$signature = $_SERVER['HTTP_X_RAWCAPTUREBOOTH_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, $secret);

if (!hash_equals($expected, $signature) || abs(time() - (int) $timestamp) > 300) {
    http_response_code(401);
    exit;
}
$status = json_decode($body, true);
if (!is_array($status)) {
    http_response_code(400);
    exit;
}

// Nur weitergeben, was auf die Website gehört
$public = [
    'event_name' => $status['event_name'] ?? null,
    'sessions_since_start' => $status['sessions_since_start'] ?? 0,
    'report_interval_seconds' => $status['report_interval_seconds'] ?? 30,
    'received_at' => time(),
];
file_put_contents(__DIR__ . '/fotobox-status.json', json_encode($public), LOCK_EX);
http_response_code(204);

Die Website liest die Datei und entscheidet selbst, ob die Fotobox erreichbar ist:

<p id="fotobox">Fotobox: wird geladen …</p>
<script>
fetch('/fotobox-status.json', { cache: 'no-store' })
  .then((response) => response.json())
  .then((status) => {
    const age = Date.now() / 1000 - status.received_at;
    const online = age <= 2 * status.report_interval_seconds;
    document.getElementById('fotobox').textContent = online
      ? 'Fotobox im Einsatz, ' + status.sessions_since_start + ' Sessions seit dem Start'
      : 'Fotobox gerade nicht erreichbar';
  });
</script>

Beispiel: Empfänger in Node.js#

Ohne zusätzliche Pakete, mit dem eingebauten http-Modul:

const http = require('http');
const crypto = require('crypto');

const SECRET = 'HIER-DEN-SCHLUESSEL-EINTRAGEN';

http.createServer((req, res) => {
  const chunks = [];
  req.on('data', (chunk) => chunks.push(chunk));
  req.on('end', () => {
    const body = Buffer.concat(chunks);
    const timestamp = req.headers['x-rawcapturebooth-timestamp'] || '';
    const signature = req.headers['x-rawcapturebooth-signature'] || '';
    const expected = 'sha256=' + crypto.createHmac('sha256', SECRET)
      .update(timestamp + '.').update(body).digest('hex');
    const valid = signature.length === expected.length
      && crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
      && Math.abs(Date.now() / 1000 - Number(timestamp)) <= 300;
    if (!valid) {
      res.writeHead(401).end();
      return;
    }
    const status = JSON.parse(body.toString('utf8'));
    console.log(status.computer_name, status.event_name, status.sessions_total);
    res.writeHead(204).end();
  });
}).listen(8080);

Erkennen, dass eine Fotobox nicht mehr meldet#

"Offline" kann eine Fotobox nicht selbst melden - ohne Verbindung kommt auch keine Meldung an. Der Empfänger merkt sich deshalb, wann die letzte Meldung eintraf. Bleibt sie länger als zwei Melde-Abstände aus (report_interval_seconds), ist die Fotobox nicht erreichbar. Zwei Abstände statt einem fangen eine einzelne verspätete Meldung ab.

Fehlersuche#

  • "Testmeldung senden" meldet HTTP 401 oder 403: Der Empfänger lehnt die Signatur ab. Stimmt der Schlüssel? Wird der Rohinhalt geprüft (siehe oben)? Geht die Uhr des Servers richtig?
  • HTTP 404: Die Adresse stimmt nicht - Pfad und Dateiname prüfen.
  • "Weiterleitung nach …": Die Adresse leitet weiter, oft von http:// auf https:// oder auf eine Adresse mit www. Die Fotobox folgt Weiterleitungen nicht; die Zieladresse aus der Meldung direkt eintragen.
  • "Keine Antwort innerhalb von 15 Sekunden": Der Empfänger ist nicht erreichbar oder antwortet zu langsam. Er sollte die Meldung annehmen und sofort antworten, statt erst weiterzuarbeiten.
  • Meldungen kommen seltener als eingestellt: Nach einem Fehlschlag wartet die Fotobox länger bis zum nächsten Versuch - erst 15 Sekunden, dann doppelt so lang, höchstens eine Viertelstunde. Beim ersten Erfolg gilt wieder der eingestellte Abstand. Wie viele Versuche in Folge gescheitert sind, steht im Bereich unter "Test und Zustand".

Stand: 01.10.2026 · Version 3.29.0