
                API DOCS
            
            Übersicht
Make-A-Wish bietet Streamern öffentliche Schnittstellen, die jeder nutzen kann und Schnittstellen für die eine Registrierung notwendig ist
Mit diesen Schnittstellen kannst du auf die wichtigsten Events, zB eine Spende oder eine Änderung des Spendenstands reagieren und zB in deinem Stream Aktionen auslösen.
Öffentliche Schnittstellen
Auf diese Schnittstellen kannst du öffentlich ohne Registrierung zugreifen.
API-Endpunkte
Wenn sich der Inhalt geändert hat, ändert sich das Property hash. Das heißt du kannst diesen vergleichen um zu sehen ob sich die Daten geändert haben.
Wenn du Push-Benachrichtigen bekommen magst, statt den Endpunkt zu pollen (bitte Cache-Busting beim Pollen verwenden), kannst du Websocket-Events für eine Aktualisierung abonnieren.
Allgemeine Infos
Unter https://streamer.make-a-wish.at/projects/charityroyale2025/info.json findest du alle aktuellen Informationen (Spendenstände, Streamer, Wünsche, Spender, ...) zu Charity Royale 2025.
Infos für einen Streamer
Möchtest du nur die Infos für einen bestimmten Streamer (<Streamer>) abfragen, kannst du https://streamer.make-a-wish.at/api/projects/charityroyale2025/streamer/<streamer_slug> abfragen.
Events (Websockets)
Wir verwenden Laravel Reverb um Events im Pusher-style zu übermitteln. Du kannst diese abonnieren um über wichtige Updates direkt informiert zu werden.
Verbindungsinformationen
APP_HOST="streamer.make-a-wish.at"
APP_KEY="mqfzsnt3n1tetbgezmfb"
WS_PORT=443
WSS_PORT=443
                            Info aktualisiert
                                Wenn sich die Informationen zum Projekt geändert haben wird ein App\\Events\\InfoJsonUpdated Event gesendet.
                                Dies kann z.B. sein wenn ein Streamer hinzugefügt oder entfernt wird, wenn ein Wunsch hinzugefügt oder entfernt wird, wenn eine Spende aktualisiert (zB abgeschlossen) wird, wenn ein Wunsch erfüllt wurde, etc
                            
Hier ist eine Beispielstruktur für die InfoJsonUpdated Daten, die über Websockets gesendet werden.
{
    "project_id": 7,
    "project_slug": "charityroyale2025",
    "hash": "09366221f02ef4b177e0daf7413b646709bf8fd0ee3d77b9d2122aea1d7f1dc4"
}
                                        Spende abgeschlossen
Wird eine Spende erfolgreich abgeschlossen kommt ein App\\Events\\DonationCompleted event
Hier ist eine Beispielstruktur für die DonationCompleted Daten, die über Websockets oder Webhooks gesendet werden.
{
    'id' => 12345, // null on test events, numeric id on real donations
    'username' => null, // null if no username (Anonym)
    'amount' => 1055, // amount in cents (10€ plus fees here)
    'amount_net' => 1000, // amount in cents without fees that Make-A-Wish received,
    'message' => 'Let\'s go chat', // null if no message
    'streamer_slug' => '<streamer_slug>', // or any other streamer slug
    // TODO: Check if the streamer_slug is '<streamer_slug>'
    'wish_slug' => 'prinzessin01',
    'date' => 1762221420, // timestamp
    'metadata' => ['action' => 'my-action']  // null if no metadata (default)
};
                                        Beispielcode
Dies ist ein schneller Beispielcode. Wir sind keine Java-Programmierer. Daher bitte entsprechend überprüfen und gerne Feedback geben.
    /*
     * This source file was generated by the Gradle 'init' task
     */
    package org.example;
    import com.pusher.client.Pusher;
    import com.pusher.client.channel.Channel;
    import com.pusher.client.channel.SubscriptionEventListener;
    import com.pusher.client.connection.ConnectionEventListener;
    import com.pusher.client.connection.ConnectionState;
    import com.pusher.client.PusherOptions;
    import com.pusher.client.channel.PusherEvent;
    import com.pusher.client.connection.ConnectionStateChange;
    public class App {
        public String getGreeting() {
            return "Hello World!";
        }
        public static void main(String[] args) {
            System.out.println(new App().getGreeting());
            String YOUR_APP_KEY="mqfzsnt3n1tetbgezmfb";
            String YOUR_APP_HOST="streamer.make-a-wish.at";
            // Create a new Pusher instance
            PusherOptions options = new PusherOptions();
            options.setHost(YOUR_APP_HOST);
            options.setActivityTimeout((long)10000L);
            Pusher pusher = new Pusher(YOUR_APP_KEY, options);
            pusher.connect(new ConnectionEventListener() {
                @Override
                public void onConnectionStateChange(ConnectionStateChange change) {
                    System.out.println("State changed to " + change.getCurrentState() +
                                       " from " + change.getPreviousState());
                }
                @Override
                public void onError(String message, String code, Exception e) {
                    System.out.println("There was a problem connecting!");
                    System.out.println(message);
                    System.out.println(code);
                    System.out.println(e);
                }
            }, ConnectionState.ALL);
            // Subscribe to a channel
            Channel channel = pusher.subscribe("donations");
            // Bind to listen for events called "my-event" sent to "my-channel"
            channel.bind("App\\Events\\DonationCompleted", new SubscriptionEventListener() {
                @Override
                public void onEvent(PusherEvent event) {
                    System.out.println("Received event with data: " + event.toString());
                    // TODO: Check if the streamer of the event is <streamer_slug>
                }
            });
            // Disconnect from the service
            pusher.disconnect();
            // Reconnect, with all channel subscriptions and event bindings automatically recreated
            pusher.connect();
            // The state change listener is notified when the connection has been re-established,
            // the subscription to "my-channel" and binding on "my-event" still exist.
            try
            {
                Thread.sleep(1000 * 60);
            }
            catch(InterruptedException e)
            {
                 // this part is executed when an exception (in this example InterruptedException) occurs
            }
            //delay(5000);
            System.out.println("The end");
        }
    }
                        
                                        Schau die auch die Dokumentation für Laravel Echo / Broadcasting an.
1. Installationnpm install --save-dev laravel-echo pusher-js
                                            2. Setup
                                            
    import Echo from 'laravel-echo';
    import Pusher from 'pusher-js';
    window.Pusher = Pusher;
    window.Echo = new Echo({
        broadcaster: 'reverb',
        key: 'mqfzsnt3n1tetbgezmfb',
        wsHost: 'streamer.make-a-wish.at',
        wsPort: 443,
        wssPort: 443,
        forceTLS: !0,
        enabledTransports: ['ws', 'wss'],
    });
                            
                                            3. Events lauschen
                                            Die Daten im donation event sind die gleichen wie oben im POST-Request
    Echo.channel('donations')
        .listen('DonationCompleted', (donation) => {
        // This will be sent when a real donation is sent.
        // TODO: Check if the streamer of the event is <streamer_slug>
        console.log('Donation retrieved');
        console.log(donation);
    }).listen('DonationCompletedTest', (donation) => {
        // This will be sent when a test is triggered via the backend
        // TODO: Check if the streamer of the event is <streamer_slug>
        console.log('TestDonation retrieved');
        console.log(donation);
    });
                            
                                        Danke an Cyber, der uns folgendes Codeschnipsel zur Verfügung gestellt hat:
Codeimport io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.plugins.websocket.WebSockets
import io.ktor.client.plugins.websocket.webSocket
import io.ktor.http.HttpMethod
import io.ktor.http.URLProtocol
import io.ktor.websocket.Frame
import io.ktor.websocket.readText
import kotlinx.coroutines.delay
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.jsonPrimitive
//JSON Vorlagen
@Serializable
data class BaseEvent(
    val event: String,
    val data: JsonElement? = null
)
@Serializable
data class DonationCompleted(
    val username: String? = null,
    val amount: Int,
    val amount_net: Int,
    val streamer_slug: String,
    val message: String? = null,
    val metadata: JsonElement? = null
)
object Eventhandler {
    val json = Json { ignoreUnknownKeys = true }
    val client = HttpClient(CIO) { install(WebSockets) }
    suspend fun schedule() {
        while (true) {
            try {
                //Verbindung aufbauen
                client.webSocket(
                    method = HttpMethod.Get,
                    host = "streamer.make-a-wish.at",
                    path = "/app/mqfzsnt3n1tetbgezmfb?protocol=7&client=ktor&version=1.0",
                    request = { url.protocol = URLProtocol.WSS }
                ) {
                    //Websocket auslesen
                    for (frame in incoming) {
                        //JSON überprüfen
                        if (frame is Frame.Text) {
                            handle(frame.readText())
                            //Pusher Notification
                            if (frame.readText().contains("pusher:connection_established")) {
                                //Pusher Kanal abonnieren = nur gewisse Events abhören (z.B. 'donations')
                                val subscribe = """{"event":"pusher:subscribe","data":{"channel":"donations"}}"""
                                send(Frame.Text(subscribe))
                            }
                        }
                    }
                }
            } catch (e: Exception) {
                //Delay vor einem Reconnect
                delay(5000)
            }
        }
    }
    fun handle(text: String){
        //JSON String umwandeln
        val base = json.decodeFromString(text)
        //Keine Donation = Pusher notification etc.
        if (!base.event.contains("DonationCompleted")){
            return
        }
        //Informationen holen
        val inner = base.data?.jsonPrimitive?.contentOrNull ?: return
        val data = json.decodeFromString(inner)
        //hier z.B. data.streamer_slug überprüfen etc.
    }
}  
                                            Ausführen
                                            kotlinx.coroutines.GlobalScope.launch {
    Eventhandler.schedule()
}
                                        Schnittstellen nach Registrierung
Die folgenden Schnittstellen sind individuell pro Streamer:in und du benötigst dafür eine Registrierung.
Registrierung
Um dich zu registrieren, schicke uns eine Nachricht in deinen Channel auf Discord und markiere unsere Orga. Schicke uns dazu bitte
- deine E-Mail-Adresse (für Login)
 - ggf Streamer:in für welche du Zugriff benötigst (als Mod)
 
Spenden-Buttons
Du hast die Möglichkeiten Spendenbuttons auf deiner Spendenseite einzubetten, um zB gewisse Aktionen in deinem Stream automatisch auslösen zu können.
Die Webhooks / Events bekommen dann ein Feld mit metadata['action' => 'gewählte Aktion'].
Webhooks
Anstelle der Events kannst du auch einen Webhook eintragen, der einen POST-Request bei jeder abgeschlossenen Spende bekommt.
Testmöglichkeiten
Im Backend hast du auch die Möglichkeit diese Events zu testen.