← Affiliate dashboard

Build your referral leaderboard

Publisher API v3 · English documentation · USD · UTC timestamps

Read only the players referred by your account, rank them by wager or deposits, and show a leaderboard on your own website.

Download PHP + HTML starter

1. Install the starter

  1. Generate your private key on Affiliate → Your Leaderboard API.
  2. Unzip the starter and upload index.html and leaderboard.php to the same directory on your own PHP 8+ HTTPS host. Enable PHP cURL.
  3. Set the server environment variable RUSTNECRO_AFFILIATE_KEY to your key. If your host requires a PHP config file, keep that file outside the public document root and require it from the backend.
  4. Optionally set RUSTNECRO_CACHE_DIR to a writable directory outside the public document root. The default is the system temporary directory.
  5. Open index.html. The starter shows the top 100 active referrals and refreshes through your backend every 30 seconds.

2. Endpoint and authentication

GET https://rustnecro.com/api/affiliate.php?action=leaderboard&sort=wagered&limit=50
Authorization: Bearer YOUR_API_KEY
Accept: application/json

GET is recommended. Form-encoded POST remains supported. Legacy key=... authentication works, but URLs can be logged: use the Bearer header. Regenerating a key immediately invalidates the old key, including cached requests.

3. Parameters

ParameterSupported values
actionstats (default): aggregate referrals, activity, deposits and earnings.
me / account: referral identity and commission tier.
referrals: paginated referral rows.
leaderboard: the same rows under the leaderboard key.
sortwagered (default), deposited, joined. Descending, then user ID ascending for ties.
limit1–100. Default 50.
offset0–10,000. Default 0.
active_only0 (default) or 1. Restricts rows to referrals with a positive qualifying wager.
user_idOptional positive site user ID. Returns that player only if they belong to your referrals. Zero means no filter.

Filters affect row lists and pagination, while stats remains the overall affiliate summary. With a user filter, rank is the position within that filtered list, not their unfiltered global rank. Bots are excluded. Empty results are successful: leaderboard: [].

4. Response and amount units

{
  "ok": true,
  "meta": {
    "version": 3, "currency": "USD", "amount_unit": "USD",
    "minor_units_per_usd": 100, "period": "since_referral_signup",
    "snapshot_at": "2026-09-25T12:00:00+00:00", "timezone": "UTC",
    "refresh_after_seconds": 30
  },
  "leaderboard": [{
    "rank": 1, "user_id": 42, "username": "ExamplePlayer",
    "avatar": "https://rustnecro.com/assets/example.png", "level": 5,
    "steam_id": "76561198000000000",
    "steam_profile_url": "https://steamcommunity.com/profiles/76561198000000000",
    "referred_at": "2026-09-01T10:00:00Z", "lifetime_games": 24,
    "total_wagered": 1250.75, "total_wagered_minor": 125075,
    "total_deposited": 100.00, "total_deposited_minor": 10000,
    "is_ftd": true, "active": true
  }],
  "pagination": {"limit": 50, "offset": 0, "count": 1, "total": 1,
    "has_more": false, "next_offset": null, "limit_reached": false},
  "sort": "wagered", "filters": {"active_only": false, "user_id": 0}
}

The example omits affiliate, commission, stats and navigation links for brevity. Use the integer *_minor fields for calculations and divide by 100 only for display. Never treat total_wagered as cents. lifetime_games is lifetime account activity, not just referral activity. Steam fields and avatar may be null. is_ftd is based on the minimum qualifying referral deposit shown in stats.ftd_minimum_deposit.

5. Pagination, caching and errors

Follow pagination.next_offset or links.next until null, retaining the same filters and Bearer header. Navigation links never contain your key. If limit_reached is true, the bounded API cannot export additional rows; do not silently assume a complete export. Use user_id for targeted referral lookups.

Snapshots are shared for 30 seconds. The per-key limit is 60 requests per minute. All pages count toward it. Parallel visitors must share your backend cache; do not make one upstream call per visitor. Pagination is a live view, not an immutable export: rankings may move between pages. Deduplicate by user ID and allow for the collection window.

Store the ETag response header and send If-None-Match on a later identical request to accept a 304 response with no body. Authentication and rate limiting still apply. Do not parse a 304 as JSON. X-Affiliate-Cache indicates hit/miss.

StatusAction
400 invalid_parametersFix the query. No immediate retry.
401 missing_keySupply a valid Bearer header.
403 invalid_keyUpdate the key after rotation. Do not repeatedly retry.
405 method_not_allowedUse GET or form-encoded POST.
429 rate_limitWait at least the Retry-After seconds. Share a backend cache.
503 refreshing / temporarily_unavailableKeep the last successful snapshot. Honor Retry-After, then use bounded backoff with jitter.

The starter has a six-second upstream timeout, nonblocking refresh lock, shared 30-second cache, failure cooldown, and a stale-data label. It never forwards raw provider errors or account earnings. HTML uses text nodes for usernames rather than inserting untrusted HTML.

6. Weekly or monthly competitions

This endpoint reports eligible cumulative totals since referral signup. It does not claim to provide historical period totals. from, to, period and since are rejected. Earnings are not a substitute for exact wager totals.

  1. Before a competition starts, collect every eligible referral's ID and integer totals and store an opening snapshot with its timestamp.
  2. Collect closing totals and subtract the opening value per user ID: score_minor = max(0, closing_minor - opening_minor).
  3. For a genuinely new referral whose referred_at is after the opening time, use an opening baseline of zero. Missing old users require review; never assume their baseline is zero.
  4. Sort by score descending and user ID ascending. Save the rules, opening/closing times and final results on your server.

7. Troubleshooting and support

If authentication works using a query key but not Bearer, ensure your host forwards the Authorization header to PHP. If the list is empty, verify the players actually signed up with your referral code and try without active_only=1. If display values are 100× too large, check cents versus dollars. For account-specific problems, open a ticket at discord.gg/rustnecro. Never include a private key in a public support message.