Game ideas & features

Your next feature

Matches

Turn-based games with explicit revisions, opaque state and separate result reports.

SDK developRequires a player session
Godot
Illustration of Matches
Your visible result

Coordinate a lobby, alternating turns and independent final reports with two player sessions.

Video coming later

This step does not have a video yet. The guide and MCP request are ready to use.

Turn-based matches

Prepare the same project

  1. Choose the same project in the dashboard as in your game configuration.

    Matches →
  2. No additional definition is needed for the first request. An empty result is valid until matching game data exists.

    Use two separate player sessions: create a lobby, join, start in an explicit order, submit alternating byte-state turns, then report the same final result independently.

    This first example reads data. It creates no group, match or object. An empty list is a valid first response.

Build this feature

You can preview the guide. Running it requires an active project key. Prepare project

SDK installed, project configuration imported and player signed in.

This SDK example uses develop. Check whether the required APIs exist in your installed SDK.

Complete the Quickstart connection with the intended player. Call read_my_matches() from an explicit button or scene action. Opening the file alone sends no request.

GDScript
res://scripts/matches.gd
horizOn call
1extends Node
2​
3# Explicit action after restoring the SAME existing player identity.
4func read_my_matches() -> void:
5 var user = Horizon.auth.getCurrentUser()
6 if user == null:
7 return
8 var result = await Horizon.matches.getMatches(user.userId)
9 if not result.success:
10 push_warning(result.errorCode)
11 return
12 print("Ledger revision: ", result.data.revision)
13 for row in result.data.recent:
14 print(row.id, " ", row.status) # May still be active after this player's forfeit.
15 # Respect result.data.pollAfterSeconds. No background poll.
16# Full two-player, durable-original example in the verified SDK:
17# addons/horizon_sdk/examples/features/matches_example.gd
18# read_matches()/create_reviewed(options), read_match(id), perform_reviewed(kind, body).
19# Each is an explicit player action. Original project+player intent survives host changes.
20# SDK methods: joinMatch(userId,id,originalRevision), startMatch(userId,id,originalRevision,order),
21# submitTurn(userId,id,originalRevision,PackedByteArray,finish),
22# reportResult(userId,id,originalFinalRevision,PackedByteArray,sortedWinnerIds).
23# Unknown create: recovery reads and explicit reconciliation, never a replacement create.
24# Report agreement is ordinary consensus, not validated combat or an automatic reward.
Open the complete SDK sample ↗

Two players, one original turn

Use two separate player sessions: create a lobby, join, start in an explicit order, submit alternating byte-state turns, then report the same final result independently.

Persist the exact request before sending. After a timeout, read current state and reconcile. Never replace its revision or create another intent silently.

Reports use the immutable final state revision. Agreement is not a trusted victory proof; disagreement and missing reports never imply a winner.

Ranked runs require a confirmed ranked match and the existing Validated Actions pipeline. Ordinary match reports do not grant rewards.

PHP supports ordinary match REST routes. Ranked validation and realtime are unavailable and return FEATURE_NOT_SUPPORTED where required.

Test your new feature.

Coordinate a lobby, alternating turns and independent final reports with two player sessions.

Choose the same project in the dashboard as in your game configuration.

Endpoints
  • GET/matches
  • GET/matches/limits
  • GET/matches/open
  • GET/matches/{matchId}
  • POST/matches
  • POST/matches/{matchId}/join
  • POST/matches/{matchId}/decline
  • POST/matches/{matchId}/start
  • POST/matches/{matchId}/turn
  • POST/matches/{matchId}/timeout
  • POST/matches/{matchId}/leave
  • POST/matches/{matchId}/cancel
  • POST/matches/{matchId}/result
  • POST/matches/{matchId}/ranked-run
All endpoints in the API reference
Our suggestion for your next step

Give every round a high score.

Save the score after a round and show who's ahead. Keep using your connection and player session.