MMOLove Docs
Referral KitSDK guides

cURL

Integrate the Referral Kit with no SDK — sign and POST events from the shell with openssl + curl, including a reusable Bash helper and full worked examples.

No SDK, no language runtime — just curl and openssl. This is the bare-metal path: useful for testing, cron jobs, shell-based game tooling, or proving the contract before you wire a "real" integration. Any language that can compute an HMAC and make an HTTPS POST can do the same thing.

Prefer a packaged path? The official SDKs wrap this exact contract for Node, PHP, Python, and .NET — npm i @mmolove/referral, pip install mmolove-referral, dotnet add package MMOLove.Referral, or a single-file PHP drop-in.

What you need

  • Your signing secret and server id from the Referrals tab.
  • curl and openssl on the box (both ubiquitous).
SECRET='your-server-secret'    # from the Referrals tab — keep it out of shell history
SERVER_ID='<your-server-id>'   # your MMOLove server id
ENDPOINT='https://mmolove.com/api/referral/events'

Don't paste a real secret into an interactive shell (it lands in ~/.bash_history). Read it from an env var or a file: SECRET="$(cat /run/secrets/mmolove)".

The signing recipe

The MAC is HMAC_SHA256(secret, "<t>.<rawBody>") in lower-case hex. Build the body once in $BODY, sign exactly that, and send exactly that.

T=$(date +%s)
BODY='{"event":"registered","token":"<mmref>","server_id":"'"$SERVER_ID"'","referee_identity":"<player>","server_event_id":"reg-<player>","ts":'"$T"'}'

# HMAC-SHA256 over "<T>.<BODY>", hex, stripping openssl's "(stdin)= " prefix.
MAC=$(printf '%s' "$T.$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')

curl -i -X POST "$ENDPOINT" \
  -H 'Content-Type: application/json' \
  -H "X-MMOLove-Signature: t=$T,v1=sha256=$MAC" \
  -d "$BODY"

printf '%s' (not echo) avoids a trailing newline — that newline would change the signed bytes and you'd get a 401. And -d "$BODY" sends the same string you signed. Don't let your shell re-quote or reformat it in between.

A reusable helper

mmolove-send.sh — sign + POST any event. Pass the body as $1.

#!/usr/bin/env bash
set -euo pipefail

SECRET="${MMOLOVE_REFERRAL_SECRET:?set MMOLOVE_REFERRAL_SECRET}"
ENDPOINT='https://mmolove.com/api/referral/events'

# Usage: mmolove-send.sh '<json-body-without-ts>'
# We inject a fresh ts + sign + POST.
mmolove_send() {
  local body_in="$1"
  local t; t=$(date +%s)

  # Inject ts into the body (assumes a trailing '}' to splice before).
  local body="${body_in%\}},\"ts\":$t}"

  local mac; mac=$(printf '%s' "$t.$body" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')

  curl -sS -o /tmp/mmolove_resp -w '%{http_code}' -X POST "$ENDPOINT" \
    -H 'Content-Type: application/json' \
    -H "X-MMOLove-Signature: t=$t,v1=sha256=$mac" \
    -d "$body"
  echo                       # newline after the status code
  cat /tmp/mmolove_resp; echo
}

mmolove_send "$1"

1. Capture the mmref token

There's nothing to call here. MMOLove delivers the token in the browser:

https://your-server.example/register?mmref=<token>

Read mmref from the query string (or the mmref cookie) on your registration page and store it against the new account. Echo it back as token in the events below.

2. Report registered — mint the anchor

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

curl -i -X POST "$ENDPOINT" \
  -H 'Content-Type: application/json' \
  -H "X-MMOLove-Signature: t=$T,v1=sha256=$MAC" \
  -d "$BODY"
# Expect: 200  {"ok":true,"referral_id":"...","state":"registered"}

referee_identity is required here (the anchor key) and should be a stable id, not a renamable name.

3. Report qualified at your milestone

Same token, a new server_event_id:

T=$(date +%s)
BODY='{"event":"qualified","token":"<mmref>","server_id":"'"$SERVER_ID"'","server_event_id":"qual-<player>","ts":'"$T"'}'
MAC=$(printf '%s' "$T.$BODY" | openssl dgst -sha256 -hmac "$SECRET" | sed 's/^.* //')

curl -i -X POST "$ENDPOINT" \
  -H 'Content-Type: application/json' \
  -H "X-MMOLove-Signature: t=$T,v1=sha256=$MAC" \
  -d "$BODY"
# Expect: 200  {"ok":true,"referral_id":"...","state":"qualified"}

Then grant the reward in-game.

Test it first (dry run)

Add "test":true — fully signature-verified, never written:

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 "$ENDPOINT" \
  -H 'Content-Type: application/json' \
  -H "X-MMOLove-Signature: t=$T,v1=sha256=$MAC" \
  -d "$BODY"
# Expect: 200  {"ok":true,"test":true}

Reading the response

The -i flag prints the status line so you can branch on it:

StatusMeaningDo
200Accepted (incl. duplicate / ignored:first_touch_conflict / test)Stop retrying. On qualified, grant the reward.
400MalformedFix the body/header — Errors.
401Bad signature or stale tThe raw-body bug (often a stray newline), wrong/old secret, or clock drift.
404Unknown server/token or referrals offCheck server_id, enable referrals, verify the token.
422Invalid transitionSend registered before qualified.
5xxServer errorRetry with backoff (idempotent via server_event_id).

If a hand-built curl 401s but your code path works (or vice-versa), it's nearly always a whitespace/quoting difference in the signed bytes. Print "$T.$BODY" exactly as signed and compare it byte-for-byte to what you POST.

Next

On this page