Validated Actions

Validated Actions

Server-checked runs for leaderboards and in-game currency, without writing server code. Single-use run tickets, server-only rules, input logs from top runs and moderation limit what a cheater can gain. Cloud only, not in the self-hosted simpleServer.

Get Started Free

Single-use run tickets

Every run starts with a server ticket bound to the player, the leaderboard and a server seed. A ticket counts exactly once, and a rejected run uses it up too, so nobody can probe your limits with one ticket.

Rules only on the server

Score limits, minimum duration, score per second, stage rules and currency limits per run live on the server. They never appear in app responses or error messages, and only the server writes currency.

Input logs and moderation

For top runs and flagged runs the server asks the game for its input log. You can replay a suspicious run yourself with its seed and log and then decide what to do with it.

Quick Integration

Quick Integration

Set up Validated Actions
Video coming soon

Turn on validated submissions for a leaderboard and set your server rules under Validated Actions. Then follow the checked runs and review the evidence of top runs in the dashboard.

C#
// Unity C#: Validated Actions
// Dashboard: turn on "Validated submissions only" for the leaderboard "weekly"
var va = ValidatedActionsManager.Instance;

// Round start: single-use ticket plus server seed
var run = await va.StartRun("weekly");
if (run == null) { Debug.Log(va.LastErrorCode); return; } // e.g. RUN_RATE_LIMITED
var random = new System.Random(run.seed);

// ... play, record the inputs into inputLog (byte[]) ...

// Round end: score plus input log (the SDK sends its SHA-256 hash)
var result = await va.SubmitValidated(18250, inputLog);
if (result == null)
{
    Debug.Log($"{va.LastErrorCode}, run kept: {va.HasActiveRun}"); // e.g. DURATION_TOO_SHORT
}
REST
# REST API: Validated Actions (needs the player's session token)

# Start a run: returns runId, a single-use ticket, seed and expiresAt
curl -X POST https://eu.horizon.pm/api/v1/app/validated-actions/runs \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Authorization: Bearer SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"userId":"USER_ID","leaderboardKey":"weekly"}'

# Submit the run: score plus the SHA-256 hex of the input log
curl -X POST https://eu.horizon.pm/api/v1/app/validated-actions/submit \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Authorization: Bearer SESSION_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"userId":"USER_ID","ticket":"TICKET","leaderboardKey":"weekly","score":18250,"inputLogHash":"SHA256_HEX"}'

# Rejected runs answer 422 with a code, e.g. TICKET_EXPIRED or DURATION_TOO_SHORT
Frequently Asked Questions

Frequently Asked Questions

Ready to Integrate?

Start building with horizOn today. Free tier included.