Instant Games

Tournaments

Updated: Mar 3, 2026
Copy for LLM
Tournaments are time-limited competitive events
This guide covers what tournaments are, how they work from the player’s perspective, how to create and manage tournaments using the SDK, tournament lifecycle, sharing mechanics, notification behavior, and best practices for designing engaging tournament experiences.

What Are Tournaments?

A tournament is a competitive event with a defined start time, end time, and scoring mechanic. Players join a tournament, play the game, and submit scores. When the tournament ends, players are ranked, and results are shared.
Tournaments differ from leaderboards in several important ways:
FeatureLeaderboardsTournaments
Duration
Permanent or long-running
Time-limited (hours to days)
Urgency
Low (play anytime)
High (must play before it ends)
Shareability
Passive
Active (players invite friends to join)
Lifecycle
Always active
Has creation, active, and ended phases
Social dynamics
Ongoing comparison
Event-based competition with a clear conclusion
The time-limited nature of tournaments is what makes them special. A tournament that ends in 24 hours creates urgency that a permanent leaderboard cannot. Players think: “I need to play now, or I will miss my chance.” This urgency drives engagement spikes and brings players back during the tournament window.

How Tournaments Work: The Player Experience

From the player’s perspective, the typical tournament flow is:
  1. Discovery: The player sees a tournament -- either through a friend’s share, an in-game prompt, or a notification.
  2. Joining: The player taps to join the tournament. They may see the current standings, the time remaining, and information about any rewards.
  3. Playing: The player plays the game and submits a score to the tournament.
  4. Checking standings: The player can check their rank relative to other participants at any time during the tournament.
  5. Sharing: The player shares the tournament with friends to invite them to compete.
  6. Returning: The player returns during the tournament period to improve their score or check if anyone has passed them.
  7. Results: When the tournament ends, the player sees the final standings.

SDK API Reference

Creating a Tournament

Use FBInstant.tournament.createAsync() to create a new tournament. This method opens a native dialog where the player configures and shares the tournament.
async function createTournament(initialScore) {
  try {
    const tournament = await FBInstant.tournament.createAsync({
      initialScore: initialScore,
      config: {
        title: 'Weekend Challenge',
        image: 'data:image/png;base64,...', // Base64-encoded image
        sortOrder: 'HIGHER_IS_BETTER',
        scoreFormat: 'NUMERIC',
        endTime: Math.floor(Date.now() / 1000) + 86400, // Ends in 24 hours (Unix timestamp)
      },
      data: {
        gameMode: 'challenge',
        difficulty: 'normal',
      },
    });

    console.log('Tournament created!');
    return tournament;
  } catch (error) {
    if (error.code === 'USER_INPUT') {
      console.log('Player cancelled tournament creation');
    } else {
      console.error('Failed to create tournament:', error);
    }
    return null;
  }
}

Create Parameters

ParameterTypeRequiredDescription
initialScore
number
Yes
The creating player’s initial score for the tournament.
config.title
string
No
The display title of the tournament.
config.image
string
No
A base64-encoded image for the tournament card.
config.sortOrder
string
No
Score sorting: 'HIGHER_IS_BETTER' (default) or 'LOWER_IS_BETTER'.
config.scoreFormat
string
No
How scores are displayed: 'NUMERIC' (default) or 'TIME'.
config.endTime
number
No
Unix timestamp (in seconds) for when the tournament ends.
data
object
No
Custom data associated with the tournament. Available to all participants.

Sharing a Tournament

Use FBInstant.tournament.shareAsync() to let the player share an active tournament with friends. This opens a native share dialog.
async function shareTournament() {
  try {
    await FBInstant.tournament.shareAsync({
      score: currentScore,
      data: {
        gameMode: 'challenge',
      },
    });
    console.log('Tournament shared!');
  } catch (error) {
    if (error.code === 'USER_INPUT') {
      console.log('Player cancelled sharing');
    } else {
      console.error('Failed to share tournament:', error);
    }
  }
}

Joining a Tournament

When a player opens your game from a tournament share or notification, the game is automatically placed in the tournament context. You can detect this and retrieve tournament data:
async function checkForTournamentContext() {
  const entryPointData = FBInstant.getEntryPointData();
  const contextType = FBInstant.context.getType();

  if (entryPointData && entryPointData.tournamentID) {
    console.log('Player entered from a tournament!');
    console.log('Tournament ID:', entryPointData.tournamentID);
    // Load the tournament game mode
    startTournamentMode(entryPointData);
  }
}

Posting a Score

Use FBInstant.tournament.postScoreAsync() to submit a score to the active tournament.
async function postTournamentScore(score) {
  try {
    await FBInstant.tournament.postScoreAsync(score);
    console.log('Tournament score posted:', score);
  } catch (error) {
    console.error('Failed to post tournament score:', error);
  }
}
The platform keeps track of the player’s best score. If the new score is lower than the existing best (for HIGHER_IS_BETTER tournaments) or higher (for LOWER_IS_BETTER tournaments), the existing score is preserved.

Getting Tournament Data

Use FBInstant.tournament.getTournamentsAsync() to retrieve a list of tournaments the player is currently participating in.
async function getMyTournaments() {
  try {
    const tournaments = await FBInstant.tournament.getTournamentsAsync();

    tournaments.forEach(tournament => {
      console.log('Tournament ID:', tournament.getID());
      console.log('Title:', tournament.getTitle());
      console.log('End Time:', new Date(tournament.getEndTime() * 1000));
      console.log('Context ID:', tournament.getContextID());

      const payload = tournament.getPayload();
      if (payload) {
        console.log('Custom data:', JSON.parse(payload));
      }
    });

    return tournaments;
  } catch (error) {
    console.error('Failed to get tournaments:', error);
    return [];
  }
}

Tournament Object Methods

MethodReturn TypeDescription
getID()
string
The unique identifier of the tournament.
getContextID()
string
The context ID associated with the tournament.
getEndTime()
number
Unix timestamp (seconds) of when the tournament ends.
getTitle()
string \| null
The display title of the tournament.
getPayload()
string \| null
The custom data payload as a JSON string.

Switching to a Tournament Context

Use FBInstant.tournament.joinAsync() to switch the player into a specific tournament context.
async function joinTournament(tournamentID) {
  try {
    await FBInstant.tournament.joinAsync(tournamentID);
    console.log('Joined tournament:', tournamentID);
    // The context has now switched to the tournament
    startTournamentMode();
  } catch (error) {
    if (error.code === 'USER_INPUT') {
      console.log('Player cancelled joining');
    } else {
      console.error('Failed to join tournament:', error);
    }
  }
}

Tournament Lifecycle

Every tournament goes through three phases:

1. Creation

A tournament is created by a player using FBInstant.tournament.createAsync(). During creation:
  • The player sets their initial score
  • The tournament configuration (title, image, sort order, end time) is established
  • The player is prompted to share the tournament with friends
  • The tournament becomes active immediately

2. Active Period

During the active period:
  • Players can join the tournament by tapping on a share or notification
  • Participants play the game and submit scores using postScoreAsync()
  • Scores are ranked according to the configured sort order
  • Players can check standings and share the tournament to invite more friends
  • New participants can join at any time before the tournament ends

3. Ended

When the tournament’s end time is reached:
  • No more scores can be submitted
  • Final rankings are determined
  • Players can view the results
  • The tournament context remains available for viewing but is no longer active

Tournament Notifications

The Facebook platform automatically handles certain notifications related to tournaments:
  • Share notifications: When a player shares a tournament, their selected friends receive a notification inviting them to join.
  • Score beat notifications: When a participant’s score is surpassed by another player, the platform may send a notification encouraging them to return and improve their score.
  • Ending soon notifications: As the tournament end time approaches, participants may receive a reminder to submit their final scores.
These notifications are managed by the platform and do not require additional SDK calls from your game. However, you can complement them with your own Custom Updates for a richer experience.

Complete Code Example

Here is a complete example demonstrating the full tournament flow in a game:
// --- Game initialization ---

async function initializeGame() {
  await FBInstant.initializeAsync();
  FBInstant.setLoadingProgress(100);
  await FBInstant.startGameAsync();

  // Check if the player entered from a tournament
  const entryData = FBInstant.getEntryPointData();
  if (entryData && entryData.tournamentID) {
    await startTournamentMode(entryData);
  } else {
    await showMainMenu();
  }
}

// --- Main menu with tournament options ---

async function showMainMenu() {
  // Check for active tournaments
  const tournaments = await FBInstant.tournament.getTournamentsAsync();

  if (tournaments.length > 0) {
    // Show active tournaments
    displayActiveTournaments(tournaments);
  }

  // Show "Create Tournament" button
  displayCreateTournamentButton();

  // Show "Play Solo" button
  displayPlaySoloButton();
}

// --- Creating a tournament ---

async function onCreateTournamentClicked() {
  // First, play a round to get an initial score
  const initialScore = await playGameRound();

  // Create the tournament with the initial score
  try {
    await FBInstant.tournament.createAsync({
      initialScore: initialScore,
      config: {
        title: 'Can You Beat Me?',
        image: generateTournamentImage(initialScore),
        sortOrder: 'HIGHER_IS_BETTER',
        scoreFormat: 'NUMERIC',
        endTime: Math.floor(Date.now() / 1000) + 172800, // 48 hours
      },
      data: {
        gameMode: 'classic',
        creatorName: FBInstant.player.getName(),
      },
    });

    showMessage('Tournament created and shared!');
  } catch (error) {
    if (error.code !== 'USER_INPUT') {
      console.error('Tournament creation failed:', error);
    }
  }
}

// --- Playing in a tournament ---

async function startTournamentMode(tournamentData) {
  showMessage('Tournament Mode!');
  showTournamentTimer(tournamentData.endTime);

  const score = await playGameRound();

  // Post the score to the tournament
  try {
    await FBInstant.tournament.postScoreAsync(score);
    showMessage(`Score submitted: ${score.toLocaleString()}`);
  } catch (error) {
    console.error('Failed to post score:', error);
  }

  // Offer to share or play again
  displayPostGameOptions(score);
}

// --- Post-game options ---

async function displayPostGameOptions(score) {
  // Option 1: Share the tournament
  const shareButton = document.getElementById('share-tournament');
  shareButton.onclick = async () => {
    try {
      await FBInstant.tournament.shareAsync({
        score: score,
        data: { gameMode: 'classic' },
      });
    } catch (error) {
      if (error.code !== 'USER_INPUT') {
        console.error('Share failed:', error);
      }
    }
  };

  // Option 2: Play again to improve score
  const playAgainButton = document.getElementById('play-again');
  playAgainButton.onclick = async () => {
    const newScore = await playGameRound();
    try {
      await FBInstant.tournament.postScoreAsync(newScore);
      showMessage(`New score: ${newScore.toLocaleString()}`);
      displayPostGameOptions(newScore);
    } catch (error) {
      console.error('Failed to post score:', error);
    }
  };
}

// --- Joining an existing tournament ---

async function onTournamentSelected(tournament) {
  try {
    await FBInstant.tournament.joinAsync(tournament.getID());
    const payload = tournament.getPayload();
    const data = payload ? JSON.parse(payload) : {};
    await startTournamentMode({
      ...data,
      endTime: tournament.getEndTime(),
    });
  } catch (error) {
    if (error.code !== 'USER_INPUT') {
      console.error('Failed to join tournament:', error);
    }
  }
}

initializeGame();

Best Practices

Choose the Right Duration

Tournament duration significantly affects player behavior:
  • Short tournaments (1-4 hours): Create intense, focused competition. Best for games with short play sessions and highly engaged audiences. Players check in frequently.
  • Medium tournaments (12-48 hours): The sweet spot for most games. Long enough for players in different time zones to participate, short enough to maintain urgency.
  • Long tournaments (3-7 days): Best for games where scores accumulate over multiple sessions. Allow casual players to participate on their own schedule, but may lose urgency.
For most games, 24-48 hour tournaments perform well. They give enough time for friends to discover and join while maintaining a sense of urgency.

Make Tournaments Accessible

Not every player is highly skilled. If your tournaments only reward the very best players, most participants will feel like they have no chance and stop engaging. Consider:
  • Multiple skill brackets: Create separate tournaments for different skill levels, or match players with others of similar ability.
  • Participation rewards: Give all participants something for joining, not just the winner. Even a small bonus for participating encourages people to try.
  • Progress-based scoring: Instead of (or in addition to) skill-based scores, consider scoring based on improvement or activity. “Most improved” or “most games played” metrics give less skilled players a path to success.

Promote Sharing

Tournaments grow through sharing. Encourage players to share at multiple points:
  • After creating a tournament: The creation dialog naturally prompts sharing, but you can also remind the player to share if they skip it.
  • After submitting a score: “Share your score with friends and challenge them to beat it!”
  • When a friend beats their score: “Sarah just passed you! Share the tournament and invite more friends to compete.”
  • When time is running out: “Only 2 hours left! Make sure your friends have joined.”

Create a Visual Identity

Give each tournament a distinct visual identity with a custom image, title, and theme. This makes the tournament feel like a special event rather than just another leaderboard. If your game has seasonal content, tie tournaments to those themes.

Show Tournament Status Prominently

When a player is in an active tournament, always show:
  • Their current rank
  • The score they need to beat to move up
  • Time remaining
  • A button to play again or share
This information should be visible on the main screen, not hidden in a menu.

Stagger Tournament Availability

Rather than running tournaments continuously, stagger them so that there are natural gaps between events. This prevents tournament fatigue and makes each tournament feel special. Consider a cadence like:
  • Daily mini-tournaments (1-4 hours) during peak hours
  • Weekend tournaments (Friday to Sunday)
  • Monthly special events with unique themes

Use Custom Data for Rich Experiences

The data parameter in tournament creation allows you to attach custom data that all participants can read. Use this to:
  • Specify a game mode or difficulty level for the tournament
  • Define special rules or modifiers
  • Include theme information for visual customization
  • Store any game-specific configuration

Next Steps

  • Leaderboards -- Implement persistent competitive rankings alongside time-limited tournaments.
  • Custom Updates -- Send rich messages to complement tournament notifications.
  • Play With Friends -- Find friends to invite to your tournaments.
  • Building Social Games -- Learn the strategic principles behind competitive social game design.