MMOLove Docs
Reward Callbacks — guides

Quickstart

From zero to a verified reward callback in about five minutes — set the URL, copy your secret, send a test callback, watch it land, then verify and reward.

This is the fastest path from "no callback" to "I just saw a signed heart.counted hit my endpoint and verify cleanly." It's the smallest end-to-end slice — once it works, the real integration is just granting the reward in step 6.

Set your callback URL

Open your server's dashboard → the Integration tab. In Reward callback URL enter a public https:// endpoint, e.g. https://your-server.example/mmolove/callback, and Save.

It must be a public HTTPS address — loopback / private / link-local URLs are rejected for SSRF safety.

Mint your signing secret

Click Rotate secret. The secret is shown once — copy it now and store it where your handler can read it (env var / secrets manager, never the browser or game client). Rotating again invalidates the previous secret immediately.

Drop in a handler

Grab the handler for your stack and wire in your SECRET:

The contract is just: read the raw body, recompute the MAC, compare it to the X-MMOLove-Signature header, then reward.

Verify the signature

The MAC is HMAC_SHA256(secret, "<t>.<rawBody>") in lower-case hex, where t is the t= field of the X-MMOLove-Signature header (it equals the body's timestamp) and rawBody is the exact bytes you received.

<?php
$raw = file_get_contents('php://input');                 // RAW body — read first
$header = $_SERVER['HTTP_X_MMOLOVE_SIGNATURE'] ?? '';
parse_str(str_replace(',', '&', $header), $sig);          // t=..,v1=..
$expected = hash_hmac('sha256', $sig['t'] . '.' . $raw, $SECRET);
$ok = hash_equals($expected, $sig['v1'] ?? '');           // constant-time

Send a test callback and watch the log

On the Integration tab, click Send test callback. MMOLove signs a heart.test payload with your current secret and POSTs it to your URL. A green result (HTTP 2xx) means your endpoint received it and your signature check passed.

Then look at the Delivery log on that same tab — real heart.counted deliveries appear there with their status, HTTP code, attempt count, and time. (The test callback is delivered live, so a successful one proves the loop.)

Grant the reward

On a verified heart.counted, look up username, grant the in-game reward (scale it with streak_day if you like), and return a 2xx. Use heart_id as an idempotency key so a retried delivery never double-rewards. Return non-2xx only when you genuinely want MMOLove to retry.

What's next

Your signing secret is secret. Verify on your backend only — never ship it to a browser or game client.

On this page