MMOLove Docs
Referral Kit

Testing & sandbox

Dry-run referral events with test:true, use the dashboard "Send test event" button, and read the delivery log to confirm your wiring.

You can prove your integration end-to-end without writing a single real referral. The endpoint has a built-in dry-run mode and the dashboard has a one-click self-test.

test: true — the signature-verified dry run

Add "test": true to any otherwise-valid, signed payload. MMOLove will:

  1. Read the raw body and fully verify the HMAC signature (so it proves your secret + the X-MMOLove-Signature header are correct end-to-end).
  2. Enforce the replay window on the timestamp, exactly as for a real event.
  3. Then short-circuit — it never touches the state machine, never mints an anchor, never writes a referral_events row.

A successful dry run returns:

{ "ok": true, "test": true }

A test: true payload is verified before any state work, so it can't pollute your real analytics or delivery log. It's purely a wiring check.

Because the signature is verified, a test event is the cleanest way to catch the raw-body-signing bug: if your test returns 401 (bad_signature), your real events would too — fix the signing before going live.

Dry-run a registered event

SECRET='your-server-secret'
T=$(date +%s)
BODY='{"event":"registered","token":"<mmref>","server_id":"<server-id>","referee_identity":"<player>","server_event_id":"test-1","ts":'"$T"',"test":true}'
MAC=$(printf '%s' "$T.$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')

curl -i -X POST 'https://mmolove.com/api/referral/events' \
  -H 'Content-Type: application/json' \
  -H "X-MMOLove-Signature: t=$T,v1=sha256=$MAC" \
  -d "$BODY"

The dry run validates the same required fields as a real event, so include referee_identity for a registered test. (Field shape is checked before the test short-circuit, so a malformed test still 400s — which is useful.)

"Send test event" in the dashboard

Don't want to write any code first? On your server's Referrals tab there's a Send test event button. It signs a test: true payload with your current secret and POSTs it for you — proving the secret + signature wiring without writing a real referral. A green result means your end is set up correctly; you only need to wire your registration + milestone hooks.

You need a secret first — if you haven't enabled referrals yet, Generate secret (or enable referrals, which mints one) before the button is active.

Reading the delivery log

The Delivery log on the Referrals tab is the system of record for inbound events. After you send a real event (not a dry run), it appears here, newest first, showing:

  • the event type (registered / qualified / reversed),
  • the referral's current lifecycle state,
  • the received-at timestamp, and
  • a short, PII-light payload snippet.

Dry-run (test: true) events deliberately do not appear — they're never written. So the workflow is:

  1. Send test event (or a test: true curl) → expect 200 { test: true }. Confirms signing.
  2. Fire a real registered → watch it land in the delivery log with state registered.
  3. Fire a real qualified → watch the state advance to qualified.

If a real event returns 2xx but never shows in the log, double-check you didn't leave test: true on it.

A clean test sequence

A good smoke test before going live:

Dry run

Send a test: true registered. Expect 200 { "ok": true, "test": true }. If it 401s, fix signing now.

Real registration

Send a real registered with a throwaway referee_identity and server_event_id: "smoke-reg-1". Expect 200 with state: "registered"; confirm the row in the delivery log.

Real qualification

Send a real qualified with the same token and server_event_id: "smoke-qual-1". Expect 200 with state: "qualified"; confirm the state advanced in the log.

Idempotency

Resend the exact registered from step 2. Expect 200 { "duplicate": true } and no new log row — proof your retries are safe.

See also

On this page