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:
- Read the raw body and fully verify the HMAC signature (so it proves your
secret + the
X-MMOLove-Signatureheader are correct end-to-end). - Enforce the replay window on the timestamp, exactly as for a real event.
- Then short-circuit — it never touches the state machine, never mints an
anchor, never writes a
referral_eventsrow.
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:
- Send test event (or a
test: truecurl) → expect200 { test: true }. Confirms signing. - Fire a real
registered→ watch it land in the delivery log with stateregistered. - Fire a real
qualified→ watch the state advance toqualified.
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
Errors & troubleshooting
Every status code the ingest endpoint returns, with cause and fix — plus the raw-body-signing gotcha and how to debug with the delivery log.
PHP
A complete, copy-paste PHP integration for the Referral Kit — a single-file drop-in in the vote-callback style, with signing, error handling, and a full worked example.